From 17485c234ff191cee3dd19e3dd693a80b024e189 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 6 Jan 2010 14:58:15 +1000 Subject: Initial pass at removal of non-KMS support. It's likely there's a lot more that can be cleaned up/removed as a result of this, we can handle that as we come across it. Signed-off-by: Ben Skeggs Signed-off-by: Francisco Jerez Acked-by: Maarten Maathuis --- configure.ac | 27 +- src/Makefile.am | 25 - src/drmmode_display.c | 57 +- src/nouveau_bios.h | 224 --- src/nouveau_calc.c | 617 ------ src/nouveau_connector.h | 65 - src/nouveau_crtc.h | 91 - src/nouveau_exa.c | 6 - src/nouveau_hw.c | 1031 ---------- src/nouveau_hw.h | 352 ---- src/nouveau_modeset.h | 31 - src/nouveau_ms.h | 159 -- src/nouveau_output.h | 69 - src/nouveau_xv.c | 39 +- src/nv04_xv_blit.c | 8 +- src/nv04_xv_ovl.c | 6 +- src/nv10_exa.c | 12 +- src/nv10_xv_ovl.c | 12 +- src/nv30_exa.c | 2 +- src/nv30_xv_tex.c | 5 +- src/nv40_exa.c | 3 +- src/nv40_xv_tex.c | 5 +- src/nv50_connector.c | 123 -- src/nv50_crtc.c | 535 ------ src/nv50_cursor.c | 77 - src/nv50_dac.c | 225 --- src/nv50_display.c | 150 -- src/nv50_output.c | 236 --- src/nv50_randr.c | 899 --------- src/nv50_randr.h | 41 - src/nv50_sor.c | 216 --- src/nv50reg.h | 449 ----- src/nv_accel_common.c | 4 +- src/nv_bios.c | 4810 ----------------------------------------------- src/nv_const.h | 8 - src/nv_crtc.c | 1095 ----------- src/nv_cursor.c | 216 --- src/nv_dma.c | 1 - src/nv_driver.c | 539 +----- src/nv_i2c.c | 158 -- src/nv_include.h | 3 - src/nv_output.c | 1293 ------------- src/nv_proto.h | 102 - src/nv_setup.c | 207 -- src/nv_type.h | 124 +- src/nvreg.h | 503 ----- 46 files changed, 176 insertions(+), 14684 deletions(-) delete mode 100644 src/nouveau_bios.h delete mode 100644 src/nouveau_calc.c delete mode 100644 src/nouveau_connector.h delete mode 100644 src/nouveau_crtc.h delete mode 100644 src/nouveau_hw.c delete mode 100644 src/nouveau_hw.h delete mode 100644 src/nouveau_modeset.h delete mode 100644 src/nouveau_ms.h delete mode 100644 src/nouveau_output.h delete mode 100644 src/nv50_connector.c delete mode 100644 src/nv50_crtc.c delete mode 100644 src/nv50_cursor.c delete mode 100644 src/nv50_dac.c delete mode 100644 src/nv50_display.c delete mode 100644 src/nv50_output.c delete mode 100644 src/nv50_randr.c delete mode 100644 src/nv50_randr.h delete mode 100644 src/nv50_sor.c delete mode 100644 src/nv50reg.h delete mode 100644 src/nv_bios.c delete mode 100644 src/nv_crtc.c delete mode 100644 src/nv_cursor.c delete mode 100644 src/nv_i2c.c delete mode 100644 src/nv_output.c delete mode 100644 src/nv_setup.c delete mode 100644 src/nvreg.h diff --git a/configure.ac b/configure.ac index e917c01..201bfc6 100644 --- a/configure.ac +++ b/configure.ac @@ -22,18 +22,18 @@ AC_PREREQ(2.57) AC_INIT([xf86-video-nouveau], - 0.0.10, + 0.0.15, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xf86-video-nouveau) AC_DEFINE_UNQUOTED([NV_MAJOR_VERSION], - [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\)\.[[0-9]]\.[[0-9]]/\1/')], + [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]*\)\.[[0-9]]*\.[[0-9]]*/\1/')], [Major version]) AC_DEFINE_UNQUOTED([NV_MINOR_VERSION], - [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.\([[0-9]]\)\.[[0-9]]/\1/')], + [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.\([[0-9]]*\)\.[[0-9]]*/\1/')], [Minor version]) AC_DEFINE_UNQUOTED([NV_PATCHLEVEL], - [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.[[0-9]]\.\([[0-9]]\)/\1/')], + [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)/\1/')], [Patch version]) AC_DEFINE_UNQUOTED([NV_DRIVER_DATE], [$(echo -n \";git log |head -3|tail -1|tr -d '\n';echo -n \")], @@ -96,25 +96,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ ]])], # needed for the next test CFLAGS="$CFLAGS $XORG_CFLAGS" -AC_MSG_CHECKING(for DRM modesetting) -AC_ARG_WITH( - kms, - [ --with-kms=yes,no compile with drm modesetting support (default: auto)], - kms="$withval", - kms="yes") -AC_MSG_RESULT($kms) - -if test "x$kms" = xyes; then - AC_CHECK_HEADER([xf86drmMode.h],[kms=yes],[kms=no], - [#include - #include ] - ) -fi - -if test "x$kms" = xyes; then - AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting]) -fi - AC_SUBST([CFLAGS]) AC_SUBST([moduledir]) diff --git a/src/Makefile.am b/src/Makefile.am index 3bd4b8c..2142330 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,17 +29,11 @@ nouveau_drv_la_LDFLAGS = -module -avoid-version @LIBDRM_NOUVEAU_LIBS@ nouveau_drv_ladir = @moduledir@/drivers nouveau_drv_la_SOURCES = \ - nouveau_bios.h \ - nouveau_calc.c \ - nouveau_hw.c nouveau_hw.h \ nouveau_local.h \ - nouveau_ms.h \ nouveau_exa.c nouveau_xv.c nouveau_dri2.c \ nouveau_wfb.c \ nv_accel_common.c \ - nv_bios.c \ nv_const.h \ - nv_cursor.c \ nv_dma.c \ nv_dma.h \ nv_dri.c \ @@ -49,13 +43,8 @@ nouveau_drv_la_SOURCES = \ nv_dripriv.h \ nv_local.h \ nv_proto.h \ - nvreg.h \ - nv_setup.c \ nv_shadow.c \ nv_type.h \ - nv_crtc.c \ - nv_output.c \ - nv_i2c.c \ nv04_exa.c \ nv04_xv_ovl.c \ nv04_xv_blit.c \ @@ -68,23 +57,9 @@ nouveau_drv_la_SOURCES = \ nv40_exa.c \ nv40_xv_tex.c \ nv50_accel.c nv50_accel.h \ - nv50_cursor.c \ - nv50_crtc.c \ - nv50_dac.c \ - nv50_display.c \ nv50_exa.c \ - nv50_output.c \ - nv50_sor.c \ - nv50_randr.c \ - nv50_randr.h \ - nv50_connector.c \ nv50_xv.c \ nv50_texture.h \ - nv50reg.h \ - nouveau_crtc.h \ - nouveau_output.h \ - nouveau_connector.h \ - nouveau_modeset.h \ drmmode_display.c \ vl_hwmc.c \ vl_hwmc.h diff --git a/src/drmmode_display.c b/src/drmmode_display.c index e37e7c1..0c8b4a0 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -33,7 +33,6 @@ #include "xorgVersion.h" -#ifdef XF86DRM_MODE #include "nv_include.h" #include "xf86drmMode.h" #include "X11/Xatom.h" @@ -368,6 +367,52 @@ done: return ret; } +#define SOURCE_MASK_INTERLEAVE 32 +#define TRANSPARENT_PIXEL 0 + +/* + * Convert a source/mask bitmap cursor to an ARGB cursor, clipping or + * padding as necessary. source/mask are assumed to be alternated each + * SOURCE_MASK_INTERLEAVE bits. + */ +void +nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride, + int bpp, uint32_t fg, uint32_t bg) +{ + int width = min(src_stride, dst_stride); + uint32_t b, m, pxval; + int i, j, k; + + for (i = 0; i < width; i++) { + for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) { + int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j; + int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE; + + b = src[2*src_off]; + m = src[2*src_off + 1]; + + for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) { + pxval = TRANSPARENT_PIXEL; +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (m & 0x80000000) + pxval = (b & 0x80000000) ? fg : bg; + b <<= 1; + m <<= 1; +#else + if (m & 1) + pxval = (b & 1) ? fg : bg; + b >>= 1; + m >>= 1; +#endif + if (bpp == 32) + ((uint32_t *)dst)[dst_off + k] = pxval; + else + ((uint16_t *)dst)[dst_off + k] = pxval; + } + } + } +} + static void drmmode_reload_cursor_image(xf86CrtcPtr crtc) { @@ -430,7 +475,6 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) } } - static void drmmode_hide_cursor (xf86CrtcPtr crtc) { @@ -1196,9 +1240,6 @@ drmmode_is_rotate_pixmap(PixmapPtr ppix, struct nouveau_bo **bo) xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); int i; - if (!NVPTR(pScrn)->kms_enable) - return FALSE; - for (i = 0; i < config->num_crtc; i++) { xf86CrtcPtr crtc = config->crtc[i]; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; @@ -1237,9 +1278,6 @@ drmmode_remove_fb(ScrnInfoPtr pScrn) drmmode_crtc_private_ptr drmmode_crtc; drmmode_ptr drmmode; - if (!NVPTR(pScrn)->kms_enable) - return; - if (config) crtc = config->crtc[0]; if (!crtc) @@ -1260,10 +1298,9 @@ drmmode_cursor_init(ScreenPtr pScreen) int size = nv_cursor_width(pNv); int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | - (pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0) | + (pNv->NVArch >= 0x11 ? HARDWARE_CURSOR_ARGB : 0) | HARDWARE_CURSOR_UPDATE_UNHIDDEN; return xf86_cursors_init(pScreen, size, size, flags); } -#endif diff --git a/src/nouveau_bios.h b/src/nouveau_bios.h deleted file mode 100644 index 125862e..0000000 --- a/src/nouveau_bios.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright 2007-2008 Nouveau Project - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __NOUVEAU_BIOS_H__ -#define __NOUVEAU_BIOS_H__ - -#include "nvreg.h" - -#define DCB_MAX_NUM_ENTRIES 16 -#define DCB_MAX_NUM_I2C_ENTRIES 16 - -#define DCB_LOC_ON_CHIP 0 - -struct dcb_entry { - int index; /* may not be raw dcb index if merging has happened */ - uint8_t type; - uint8_t i2c_index; - uint8_t heads; - uint8_t bus; - uint8_t location; - uint8_t or; - bool duallink_possible; - union { - struct { - int maxfreq; - } crtconf; - struct { - bool use_straps_for_mode; - bool use_power_scripts; - } lvdsconf; - }; - bool i2c_upper_default; -}; - -struct dcb_i2c_entry { - uint8_t port_type; - uint8_t read, write; - I2CBusPtr chan; -}; - -struct parsed_dcb { - int entries; - struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; - struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES]; -}; - -struct bios_parsed_dcb { - uint8_t version; - - struct parsed_dcb dcb; - - uint16_t init8e_table_ptr; - uint8_t *i2c_table; - uint8_t i2c_default_indices; -}; - -enum nouveau_encoder_type -{ - /* 0-3 match DCB types */ - OUTPUT_NONE = 4, - OUTPUT_ANALOG = 0, - OUTPUT_TMDS = 2, - OUTPUT_LVDS = 3, - OUTPUT_TV = 1, - OUTPUT_ANY = 5, -}; - -#define IS_DFP(t) (t == OUTPUT_LVDS || t == OUTPUT_TMDS) - -enum nouveau_or { - OUTPUT_A = (1 << 0), - OUTPUT_B = (1 << 1), - OUTPUT_C = (1 << 2) -}; - -enum LVDS_script { - /* Order *does* matter here */ - LVDS_INIT = 1, - LVDS_RESET, - LVDS_BACKLIGHT_ON, - LVDS_BACKLIGHT_OFF, - LVDS_PANEL_ON, - LVDS_PANEL_OFF -}; - -/* changing these requires matching changes to reg tables in nv_get_clock */ -#define MAX_PLL_TYPES 4 -enum pll_types { - NVPLL, - MPLL, - VPLL1, - VPLL2 -}; - -struct pll_lims { - struct { - int minfreq; - int maxfreq; - int min_inputfreq; - int max_inputfreq; - - uint8_t min_m; - uint8_t max_m; - uint8_t min_n; - uint8_t max_n; - } vco1, vco2; - - uint8_t max_log2p; - /* - * for most pre nv50 cards setting a log2P of 7 (the common max_log2p - * value) is no different to 6 (at least for vplls) so allowing the MNP - * calc to use 7 causes the generated clock to be out by a factor of 2. - * however, max_log2p cannot be fixed-up during parsing as the - * unmodified max_log2p value is still needed for setting mplls, hence - * an additional max_usable_log2p member - */ - uint8_t max_usable_log2p; - uint8_t log2p_bias; - int refclk; -}; - -struct nouveau_bios_info { - struct parsed_dcb *dcb; - - uint8_t chip_version; - - uint32_t dactestval; - uint8_t digital_min_front_porch; - bool fp_no_ddc; -}; - -struct nvbios { - struct nouveau_bios_info pub; - - uint8_t data[NV_PROM_SIZE]; - unsigned int length; - bool execute; - - uint8_t major_version; - uint8_t feature_byte; - bool is_mobile; - - uint32_t fmaxvco, fminvco; - - bool old_style_init; - uint16_t init_script_tbls_ptr; - uint16_t extra_init_script_tbl_ptr; - uint16_t macro_index_tbl_ptr; - uint16_t macro_tbl_ptr; - uint16_t condition_tbl_ptr; - uint16_t io_condition_tbl_ptr; - uint16_t io_flag_condition_tbl_ptr; - uint16_t init_function_tbl_ptr; - - uint16_t pll_limit_tbl_ptr; - uint16_t ram_restrict_tbl_ptr; - - struct bios_parsed_dcb bdcb; - - struct { - int head; - uint16_t script_table_ptr; - } display; - - struct { - uint16_t fptablepointer; /* also used by tmds */ - uint16_t fpxlatetableptr; - int xlatwidth; - uint16_t lvdsmanufacturerpointer; - uint16_t fpxlatemanufacturertableptr; - uint16_t mode_ptr; - uint16_t xlated_entry; - bool power_off_for_reset; - bool reset_after_pclk_change; - bool dual_link; - bool link_c_increment; - bool BITbit1; - int duallink_transition_clk; - uint8_t *edid; - - /* will need resetting after suspend */ - int last_script_invoc; - bool lvds_init_run; - } fp; - - struct { - uint16_t output0_script_ptr; - uint16_t output1_script_ptr; - } tmds; - - struct { - uint16_t mem_init_tbl_ptr; - uint16_t sdr_seq_tbl_ptr; - uint16_t ddr_seq_tbl_ptr; - - struct { - uint8_t crt, tv, panel; - } i2c_indices; - - uint16_t lvds_single_a_script_ptr; - } legacy; -}; - -#endif diff --git a/src/nouveau_calc.c b/src/nouveau_calc.c deleted file mode 100644 index f12486c..0000000 --- a/src/nouveau_calc.c +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Copyright 1993-2003 NVIDIA, Corporation - * Copyright 2007-2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -/****************************************************************************\ -* * -* The video arbitration routines calculate some "magic" numbers. Fixes * -* the snow seen when accessing the framebuffer without it. * -* It just works (I hope). * -* * -\****************************************************************************/ - -struct nv_fifo_info { - int graphics_lwm; - int video_lwm; - int graphics_burst_size; - int video_burst_size; - bool valid; -}; - -struct nv_sim_state { - int pclk_khz; - int mclk_khz; - int nvclk_khz; - int pix_bpp; - bool enable_mp; - bool enable_video; - int mem_page_miss; - int mem_latency; - int memory_type; - int memory_width; -}; - -static void nv4CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb) -{ - int pagemiss, cas, width, video_enable, bpp; - int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs; - int found, mclk_extra, mclk_loop, cbs, m1, p1; - int mclk_freq, pclk_freq, nvclk_freq, mp_enable; - int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate; - int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm; - - pclk_freq = arb->pclk_khz; - mclk_freq = arb->mclk_khz; - nvclk_freq = arb->nvclk_khz; - pagemiss = arb->mem_page_miss; - cas = arb->mem_latency; - width = arb->memory_width >> 6; - video_enable = arb->enable_video; - bpp = arb->pix_bpp; - mp_enable = arb->enable_mp; - clwm = 0; - vlwm = 0; - cbs = 128; - pclks = 2; - nvclks = 2; - nvclks += 2; - nvclks += 1; - mclks = 5; - mclks += 3; - mclks += 1; - mclks += cas; - mclks += 1; - mclks += 1; - mclks += 1; - mclks += 1; - mclk_extra = 3; - nvclks += 2; - nvclks += 1; - nvclks += 1; - nvclks += 1; - if (mp_enable) - mclks += 4; - nvclks += 0; - pclks += 0; - found = 0; - vbs = 0; - while (found != 1) { - fifo->valid = true; - found = 1; - mclk_loop = mclks + mclk_extra; - us_m = mclk_loop * 1000 * 1000 / mclk_freq; - us_n = nvclks * 1000 * 1000 / nvclk_freq; - us_p = nvclks * 1000 * 1000 / pclk_freq; - if (video_enable) { - video_drain_rate = pclk_freq * 2; - crtc_drain_rate = pclk_freq * bpp / 8; - vpagemiss = 2; - vpagemiss += 1; - crtpagemiss = 2; - vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - if (nvclk_freq * 2 > mclk_freq * width) - video_fill_us = cbs * 1000 * 1000 / 16 / nvclk_freq; - else - video_fill_us = cbs * 1000 * 1000 / (8 * width) / mclk_freq; - us_video = vpm_us + us_m + us_n + us_p + video_fill_us; - vlwm = us_video * video_drain_rate / (1000 * 1000); - vlwm++; - vbs = 128; - if (vlwm > 128) - vbs = 64; - if (vlwm > (256 - 64)) - vbs = 32; - if (nvclk_freq * 2 > mclk_freq * width) - video_fill_us = vbs * 1000 * 1000 / 16 / nvclk_freq; - else - video_fill_us = vbs * 1000 * 1000 / (8 * width) / mclk_freq; - cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - us_crt = us_video + video_fill_us + cpm_us + us_m + us_n + us_p; - clwm = us_crt * crtc_drain_rate / (1000 * 1000); - clwm++; - } else { - crtc_drain_rate = pclk_freq * bpp / 8; - crtpagemiss = 2; - crtpagemiss += 1; - cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - us_crt = cpm_us + us_m + us_n + us_p; - clwm = us_crt * crtc_drain_rate / (1000 * 1000); - clwm++; - } - m1 = clwm + cbs - 512; - p1 = m1 * pclk_freq / mclk_freq; - p1 = p1 * bpp / 8; - if ((p1 < m1 && m1 > 0) || - (video_enable && (clwm > 511 || vlwm > 255)) || - (!video_enable && clwm > 519)) { - fifo->valid = false; - found = !mclk_extra; - mclk_extra--; - } - if (clwm < 384) - clwm = 384; - if (vlwm < 128) - vlwm = 128; - fifo->graphics_lwm = clwm; - fifo->graphics_burst_size = 128; - fifo->video_lwm = vlwm + 15; - fifo->video_burst_size = vbs; - } -} - -static void nv10CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb) -{ - int pagemiss, width, video_enable, bpp; - int nvclks, mclks, pclks, vpagemiss, crtpagemiss; - int nvclk_fill; - int found, mclk_extra, mclk_loop, cbs, m1; - int mclk_freq, pclk_freq, nvclk_freq, mp_enable; - int us_m, us_m_min, us_n, us_p, crtc_drain_rate; - int vus_m; - int vpm_us, us_video, cpm_us, us_crt, clwm; - int clwm_rnd_down; - int m2us, us_pipe_min, p1clk, p2; - int min_mclk_extra; - int us_min_mclk_extra; - - pclk_freq = arb->pclk_khz; /* freq in KHz */ - mclk_freq = arb->mclk_khz; - nvclk_freq = arb->nvclk_khz; - pagemiss = arb->mem_page_miss; - width = arb->memory_width / 64; - video_enable = arb->enable_video; - bpp = arb->pix_bpp; - mp_enable = arb->enable_mp; - clwm = 0; - cbs = 512; - pclks = 4; /* lwm detect. */ - nvclks = 3; /* lwm -> sync. */ - nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */ - mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */ - mclks += 1; /* arb_hp_req */ - mclks += 5; /* ap_hp_req tiling pipeline */ - mclks += 2; /* tc_req latency fifo */ - mclks += 2; /* fb_cas_n_ memory request to fbio block */ - mclks += 7; /* sm_d_rdv data returned from fbio block */ - - /* fb.rd.d.Put_gc need to accumulate 256 bits for read */ - if (arb->memory_type == 0) { - if (arb->memory_width == 64) /* 64 bit bus */ - mclks += 4; - else - mclks += 2; - } else if (arb->memory_width == 64) /* 64 bit bus */ - mclks += 2; - else - mclks += 1; - - if (!video_enable && arb->memory_width == 128) { - mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */ - min_mclk_extra = 17; - } else { - mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */ - /* mclk_extra = 4; *//* Margin of error */ - min_mclk_extra = 18; - } - - nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */ - nvclks += 1; /* fbi_d_rdv_n */ - nvclks += 1; /* Fbi_d_rdata */ - nvclks += 1; /* crtfifo load */ - - if (mp_enable) - mclks += 4; /* Mp can get in with a burst of 8. */ - /* Extra clocks determined by heuristics */ - - nvclks += 0; - pclks += 0; - found = 0; - while (found != 1) { - fifo->valid = true; - found = 1; - mclk_loop = mclks + mclk_extra; - us_m = mclk_loop * 1000 * 1000 / mclk_freq; /* Mclk latency in us */ - us_m_min = mclks * 1000 * 1000 / mclk_freq; /* Minimum Mclk latency in us */ - us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq; - us_n = nvclks * 1000 * 1000 / nvclk_freq; /* nvclk latency in us */ - us_p = pclks * 1000 * 1000 / pclk_freq; /* nvclk latency in us */ - us_pipe_min = us_m_min + us_n + us_p; - - vus_m = mclk_loop * 1000 * 1000 / mclk_freq; /* Mclk latency in us */ - - if (video_enable) { - crtc_drain_rate = pclk_freq * bpp / 8; /* MB/s */ - - vpagemiss = 1; /* self generating page miss */ - vpagemiss += 1; /* One higher priority before */ - - crtpagemiss = 2; /* self generating page miss */ - if (mp_enable) - crtpagemiss += 1; /* if MA0 conflict */ - - vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - - us_video = vpm_us + vus_m; /* Video has separate read return path */ - - cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - us_crt = us_video /* Wait for video */ - + cpm_us /* CRT Page miss */ - + us_m + us_n + us_p; /* other latency */ - - clwm = us_crt * crtc_drain_rate / (1000 * 1000); - clwm++; /* fixed point <= float_point - 1. Fixes that */ - } else { - crtc_drain_rate = pclk_freq * bpp / 8; /* bpp * pclk/8 */ - - crtpagemiss = 1; /* self generating page miss */ - crtpagemiss += 1; /* MA0 page miss */ - if (mp_enable) - crtpagemiss += 1; /* if MA0 conflict */ - cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq; - us_crt = cpm_us + us_m + us_n + us_p; - clwm = us_crt * crtc_drain_rate / (1000 * 1000); - clwm++; /* fixed point <= float_point - 1. Fixes that */ - - /* Finally, a heuristic check when width == 64 bits */ - if (width == 1) { - nvclk_fill = nvclk_freq * 8; - if (crtc_drain_rate * 100 >= nvclk_fill * 102) - clwm = 0xfff; /* Large number to fail */ - else if (crtc_drain_rate * 100 >= nvclk_fill * 98) { - clwm = 1024; - cbs = 512; - } - } - } - - /* - * Overfill check: - */ - - clwm_rnd_down = (clwm / 8) * 8; - if (clwm_rnd_down < clwm) - clwm += 8; - - m1 = clwm + cbs - 1024; /* Amount of overfill */ - m2us = us_pipe_min + us_min_mclk_extra; - - /* pclk cycles to drain */ - p1clk = m2us * pclk_freq / (1000 * 1000); - p2 = p1clk * bpp / 8; /* bytes drained. */ - - if (p2 < m1 && m1 > 0) { - fifo->valid = false; - found = 0; - if (min_mclk_extra == 0) { - if (cbs <= 32) - found = 1; /* Can't adjust anymore! */ - else - cbs = cbs / 2; /* reduce the burst size */ - } else - min_mclk_extra--; - } else if (clwm > 1023) { /* Have some margin */ - fifo->valid = false; - found = 0; - if (min_mclk_extra == 0) - found = 1; /* Can't adjust anymore! */ - else - min_mclk_extra--; - } - - if (clwm < (1024 - cbs + 8)) - clwm = 1024 - cbs + 8; - /* printf("CRT LWM: prog: 0x%x, bs: 256\n", clwm); */ - fifo->graphics_lwm = clwm; - fifo->graphics_burst_size = cbs; - - fifo->video_lwm = 1024; - fifo->video_burst_size = 512; - } -} - -void nv4_10UpdateArbitrationSettings(ScrnInfoPtr pScrn, int VClk, int bpp, int *burst, int *lwm) -{ - NVPtr pNv = NVPTR(pScrn); - struct nv_fifo_info fifo_data; - struct nv_sim_state sim_data; - int MClk = nouveau_hw_get_clock(pScrn, MPLL); - int NVClk = nouveau_hw_get_clock(pScrn, NVPLL); - uint32_t cfg1 = nvReadFB(pNv, NV_PFB_CFG1); - - sim_data.pclk_khz = VClk; - sim_data.mclk_khz = MClk; - sim_data.nvclk_khz = NVClk; - sim_data.pix_bpp = bpp; - sim_data.enable_mp = false; - if ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE || - (pNv->Chipset & 0xffff) == CHIPSET_NFORCE2) { - struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 1); - uint32_t data; - - pci_device_cfg_read_u32(dev, &data, 0x7c); - - sim_data.enable_video = false; - sim_data.memory_type = (data >> 12) & 1; - sim_data.memory_width = 64; - sim_data.mem_latency = 3; - sim_data.mem_page_miss = 10; - } else { - sim_data.enable_video = (pNv->Architecture != NV_ARCH_04); - sim_data.memory_type = nvReadFB(pNv, NV_PFB_CFG0) & 0x1; - sim_data.memory_width = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; - sim_data.mem_latency = cfg1 & 0xf; - sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); - } - - if (pNv->Architecture == NV_ARCH_04) - nv4CalcArbitration(&fifo_data, &sim_data); - else - nv10CalcArbitration(&fifo_data, &sim_data); - - if (fifo_data.valid) { - int b = fifo_data.graphics_burst_size >> 4; - *burst = 0; - while (b >>= 1) - (*burst)++; - *lwm = fifo_data.graphics_lwm >> 3; - } -} - -void nv30UpdateArbitrationSettings(int *burst, int *lwm) -{ - unsigned int fifo_size, burst_size, graphics_lwm; - - fifo_size = 2048; - burst_size = 512; - graphics_lwm = fifo_size - burst_size; - - *burst = 0; - burst_size >>= 5; - while (burst_size >>= 1) - (*burst)++; - *lwm = graphics_lwm >> 3; -} - -void -nouveau_calc_arb(ScrnInfoPtr pScrn, int vclk, int bpp, int *burst, int *lwm) -{ - NVPtr pNv = NVPTR(pScrn); - - if (pNv->Architecture < NV_ARCH_30) - nv4_10UpdateArbitrationSettings(pScrn, vclk, bpp, burst, lwm); - else if ((pNv->Chipset & 0xfff0) == CHIPSET_C51 || - (pNv->Chipset & 0xfff0) == CHIPSET_C512) { - *burst = 128; - *lwm = 0x0480; - } else - nv30UpdateArbitrationSettings(burst, lwm); -} - -static int getMNP_single(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *bestpv) -{ - /* Find M, N and P for a single stage PLL - * - * Note that some bioses (NV3x) have lookup tables of precomputed MNP - * values, but we're too lazy to use those atm - * - * "clk" parameter in kHz - * returns calculated clock - */ - - int cv = NVPTR(pScrn)->vbios->chip_version; - int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq; - int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m; - int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n; - int minU = pll_lim->vco1.min_inputfreq, maxU = pll_lim->vco1.max_inputfreq; - int maxlog2P = pll_lim->max_usable_log2p; - int crystal = pll_lim->refclk; - int M, N, log2P, P; - int clkP, calcclk; - int delta, bestdelta = INT_MAX; - int bestclk = 0; - - /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */ - /* possibly correlated with introduction of 27MHz crystal */ - if (cv < 0x17 || cv == 0x1a || cv == 0x20) { - if (clk > 250000) - maxM = 6; - if (clk > 340000) - maxM = 2; - } else if (cv < 0x40) { - if (clk > 150000) - maxM = 6; - if (clk > 200000) - maxM = 4; - if (clk > 340000) - maxM = 2; - } - - if ((clk << maxlog2P) < minvco) { - minvco = clk << maxlog2P; - maxvco = minvco * 2; - } - if (clk + clk/200 > maxvco) /* +0.5% */ - maxvco = clk + clk/200; - - /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */ - for (log2P = 0; log2P <= maxlog2P; log2P++) { - P = 1 << log2P; - clkP = clk * P; - - if (clkP < minvco) - continue; - if (clkP > maxvco) - return bestclk; - - for (M = minM; M <= maxM; M++) { - if (crystal/M < minU) - return bestclk; - if (crystal/M > maxU) - continue; - - /* add crystal/2 to round better */ - N = (clkP * M + crystal/2) / crystal; - - if (N < minN) - continue; - if (N > maxN) - break; - - /* more rounding additions */ - calcclk = ((N * crystal + P/2) / P + M/2) / M; - delta = abs(calcclk - clk); - /* we do an exhaustive search rather than terminating - * on an optimality condition... - */ - if (delta < bestdelta) { - bestdelta = delta; - bestclk = calcclk; - bestpv->N1 = N; - bestpv->M1 = M; - bestpv->log2P = log2P; - if (delta == 0) /* except this one */ - return bestclk; - } - } - } - - return bestclk; -} - -static int getMNP_double(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *bestpv) -{ - /* Find M, N and P for a two stage PLL - * - * Note that some bioses (NV30+) have lookup tables of precomputed MNP - * values, but we're too lazy to use those atm - * - * "clk" parameter in kHz - * returns calculated clock - */ - - int chip_version = NVPTR(pScrn)->vbios->chip_version; - int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq; - int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq; - int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq; - int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq; - int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m; - int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n; - int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m; - int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n; - int maxlog2P = pll_lim->max_usable_log2p; - int crystal = pll_lim->refclk; - bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2); - int M1, N1, M2, N2, log2P; - int clkP, calcclk1, calcclk2, calcclkout; - int delta, bestdelta = INT_MAX; - int bestclk = 0; - - int vco2 = (maxvco2 - maxvco2/200) / 2; - for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++) - ; - clkP = clk << log2P; - - if (maxvco2 < clk + clk/200) /* +0.5% */ - maxvco2 = clk + clk/200; - - for (M1 = minM1; M1 <= maxM1; M1++) { - if (crystal/M1 < minU1) - return bestclk; - if (crystal/M1 > maxU1) - continue; - - for (N1 = minN1; N1 <= maxN1; N1++) { - calcclk1 = crystal * N1 / M1; - if (calcclk1 < minvco1) - continue; - if (calcclk1 > maxvco1) - break; - - for (M2 = minM2; M2 <= maxM2; M2++) { - if (calcclk1/M2 < minU2) - break; - if (calcclk1/M2 > maxU2) - continue; - - /* add calcclk1/2 to round better */ - N2 = (clkP * M2 + calcclk1/2) / calcclk1; - if (N2 < minN2) - continue; - if (N2 > maxN2) - break; - - if (!fixedgain2) { - if (chip_version < 0x60) - if (N2/M2 < 4 || N2/M2 > 10) - continue; - - calcclk2 = calcclk1 * N2 / M2; - if (calcclk2 < minvco2) - break; - if (calcclk2 > maxvco2) - continue; - } else - calcclk2 = calcclk1; - - calcclkout = calcclk2 >> log2P; - delta = abs(calcclkout - clk); - /* we do an exhaustive search rather than terminating - * on an optimality condition... - */ - if (delta < bestdelta) { - bestdelta = delta; - bestclk = calcclkout; - bestpv->N1 = N1; - bestpv->M1 = M1; - bestpv->N2 = N2; - bestpv->M2 = M2; - bestpv->log2P = log2P; - if (delta == 0) /* except this one */ - return bestclk; - } - } - } - } - - return bestclk; -} - -int nouveau_calc_pll_mnp(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *pv) -{ - int outclk; - - if (!pll_lim->vco2.maxfreq) - outclk = getMNP_single(pScrn, pll_lim, clk, pv); - else - outclk = getMNP_double(pScrn, pll_lim, clk, pv); - - if (!outclk) - NV_ERROR(pScrn, - "Could not find a compatible set of PLL values\n"); - - return outclk; -} diff --git a/src/nouveau_connector.h b/src/nouveau_connector.h deleted file mode 100644 index 5d2c8af..0000000 --- a/src/nouveau_connector.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NOUVEAU_CONNECTOR_H_ -#define __NOUVEAU_CONNECTOR_H_ - -#include "nv_include.h" -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" - -/* I have yet to find specific information on connectors, so it's all derived from outputs. */ -typedef enum { - CONNECTOR_NONE = 4, - CONNECTOR_VGA = 0, - CONNECTOR_DVI = 1, - CONNECTOR_TV = 2, - CONNECTOR_PANEL = 3 -} NVConnectorType; - -#define MAX_OUTPUTS_PER_CONNECTOR 2 - -typedef struct nouveauConnector { - ScrnInfoPtr scrn; - int index; - - char *name; - Bool active; - - NVConnectorType type; - - I2CBusPtr pDDCBus; - int i2c_index; - - /* For load detect amongst other things. */ - nouveauOutputPtr outputs[MAX_OUTPUTS_PER_CONNECTOR]; - int connected_output; - - Bool hotplug_detected; /* better name? */ - /* Function pointers. */ - Bool (*HotplugDetect) (nouveauConnectorPtr connector); - xf86MonPtr (*DDCDetect) (nouveauConnectorPtr connector); - DisplayModePtr (*GetDDCModes) (nouveauConnectorPtr connector); -} nouveauConnectorRec; - -#endif /* __NOUVEAU_CONNECTOR_H_ */ diff --git a/src/nouveau_crtc.h b/src/nouveau_crtc.h deleted file mode 100644 index 45d0eee..0000000 --- a/src/nouveau_crtc.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NOUVEAU_CRTC_H_ -#define __NOUVEAU_CRTC_H_ - -#include "nv_include.h" -#include "nouveau_modeset.h" - -typedef struct nouveauCrtc { - ScrnInfoPtr scrn; - - char *name; - uint8_t index; - Bool active; - Bool blanked; - - /* Scanout area. */ - struct nouveau_bo * front_buffer; - uint32_t fb_pitch; - uint32_t x; /* relative to the frontbuffer */ - uint32_t y; - - /* Gamma */ - struct nouveau_bo *lut; - struct { - uint16_t red; - uint16_t green; - uint16_t blue; - uint16_t unused; - } lut_values[256]; - bool lut_values_valid; - - /* Options and some state. */ - Bool modeset_lock; - Bool dithering; - Bool cursor_visible; - Bool use_native_mode; - int scale_mode; - int pixel_clock; - - /* Mode info. */ - DisplayModePtr cur_mode; - DisplayModePtr native_mode; - DisplayModePtr mode_list; - - /* Function pointers. */ - Bool (*ModeValid) (nouveauCrtcPtr crtc, DisplayModePtr mode); - void (*ModeSet) (nouveauCrtcPtr crtc, DisplayModePtr mode); - void (*SetPixelClock) (nouveauCrtcPtr crtc, int clock); - void (*SetClockMode) (nouveauCrtcPtr crtc, int clock); /* maybe another name? */ - - void (*SetFB) (nouveauCrtcPtr crtc, struct nouveau_bo * buffer); - void (*SetFBOffset) (nouveauCrtcPtr crtc, uint32_t x, uint32_t y); - - void (*Blank) (nouveauCrtcPtr crtc, Bool blanked); - void (*SetDither) (nouveauCrtcPtr crtc); - - void (*SetScaleMode) (nouveauCrtcPtr crtc, int scale); - - void (*ShowCursor) (nouveauCrtcPtr crtc, Bool forced_lock); - void (*HideCursor) (nouveauCrtcPtr crtc, Bool forced_lock); - void (*SetCursorPosition) (nouveauCrtcPtr crtc, int x, int y); - void (*LoadCursor) (nouveauCrtcPtr crtc, Bool argb, uint32_t *src); - - void (*GammaSet) (nouveauCrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size); - - void (*Save) (nouveauCrtcPtr crtc); - void (*Load) (nouveauCrtcPtr crtc); -} nouveauCrtcRec; - -#endif /* __NOUVEAU_CRTC_H_ */ diff --git a/src/nouveau_exa.c b/src/nouveau_exa.c index 5707add..d8c2d45 100644 --- a/src/nouveau_exa.c +++ b/src/nouveau_exa.c @@ -724,12 +724,6 @@ nouveau_exa_init(ScreenPtr pScreen) if (!exaDriverInit(pScreen, exa)) return FALSE; - else - /* EXA init catches this, but only for xserver >= 1.4 */ - if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n"); - return FALSE; - } pNv->EXADriverPtr = exa; return TRUE; diff --git a/src/nouveau_hw.c b/src/nouveau_hw.c deleted file mode 100644 index ff36407..0000000 --- a/src/nouveau_hw.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Copyright 2006 Dave Airlie - * Copyright 2007 Maarten Maathuis - * Copyright 2007-2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -/* - * misc hw access wrappers/control functions - */ - -void NVWriteVgaSeq(NVPtr pNv, int head, uint8_t index, uint8_t value) -{ - NVWritePRMVIO(pNv, head, NV_PRMVIO_SRX, index); - NVWritePRMVIO(pNv, head, NV_PRMVIO_SR, value); -} - -uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index) -{ - NVWritePRMVIO(pNv, head, NV_PRMVIO_SRX, index); - return NVReadPRMVIO(pNv, head, NV_PRMVIO_SR); -} - -void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value) -{ - NVWritePRMVIO(pNv, head, NV_PRMVIO_GRX, index); - NVWritePRMVIO(pNv, head, NV_PRMVIO_GX, value); -} - -uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index) -{ - NVWritePRMVIO(pNv, head, NV_PRMVIO_GRX, index); - return NVReadPRMVIO(pNv, head, NV_PRMVIO_GX); -} - -/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied) - * it affects only the 8 bit vga io regs, which we access using mmio at - * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d* - * in general, the set value of cr44 does not matter: reg access works as - * expected and values can be set for the appropriate head by using a 0x2000 - * offset as required - * however: - * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and - * cr44 must be set to 0 or 3 for accessing values on the correct head - * through the common 0xc03c* addresses - * b) in tied mode (4) head B is programmed to the values set on head A, and - * access using the head B addresses can have strange results, ergo we leave - * tied mode in init once we know to what cr44 should be restored on exit - * - * the owner parameter is slightly abused: - * 0 and 1 are treated as head values and so the set value is (owner * 3) - * other values are treated as literal values to set - */ -void NVSetOwner(NVPtr pNv, int owner) -{ - if (owner == 1) - owner *= 3; - /* CR44 is always changed on CRTC0 */ - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_44, owner); - if (pNv->NVArch == 0x11) { /* set me harder */ - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_2E, owner); - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_2E, owner); - } -} - -/* - * on nv11 this may not be reliable - * returned value is suitable for directly programming back into cr44 - */ -int nouveau_hw_get_current_head(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - int cr44; - - if (pNv->NVArch != 0x11) - return NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44); - - /* reading CR44 is broken on nv11, so we attempt to infer it */ - if (nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */ - cr44 = 0x4; - else { - bool slaved_on_A, tvA = false; - bool slaved_on_B, tvB = false; - bool waslocked; - - waslocked = NVLockVgaCrtcs(pNv, false); - - slaved_on_A = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX) & 0x80; - if (slaved_on_A) - tvA = !(NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_LCD__INDEX) & MASK(NV_CIO_CRE_LCD_LCD_SELECT)); - - slaved_on_B = NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_PIXEL_INDEX) & 0x80; - if (slaved_on_B) - tvB = !(NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_LCD__INDEX) & MASK(NV_CIO_CRE_LCD_LCD_SELECT)); - - if (waslocked) - NVLockVgaCrtcs(pNv, true); - - if (slaved_on_A && !tvA) - cr44 = 0x0; - else if (slaved_on_B && !tvB) - cr44 = 0x3; - else if (slaved_on_A) - cr44 = 0x0; - else if (slaved_on_B) - cr44 = 0x3; - else - cr44 = 0x0; - } - - return cr44; -} - -void NVBlankScreen(NVPtr pNv, int head, bool blank) -{ - unsigned char seq1; - - if (pNv->twoHeads) - NVSetOwner(pNv, head); - - seq1 = NVReadVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX); - - NVVgaSeqReset(pNv, head, true); - if (blank) - NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20); - else - NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); - NVVgaSeqReset(pNv, head, false); -} - -/* - * PLL setting - */ - -static int powerctrl_1_shift(int chip_version, int reg) -{ - int shift = -4; - - if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20) - return shift; - - switch (reg) { - case NV_RAMDAC_VPLL2: - shift += 4; - case NV_PRAMDAC_VPLL_COEFF: - shift += 4; - case NV_PRAMDAC_MPLL_COEFF: - shift += 4; - case NV_PRAMDAC_NVPLL_COEFF: - shift += 4; - } - - /* - * the shift for vpll regs is only used for nv3x chips with a single - * stage pll - */ - if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 || - chip_version == 0x36 || chip_version >= 0x40)) - shift = -4; - - return shift; -} - -static void setPLL_single(ScrnInfoPtr pScrn, uint32_t reg, - struct nouveau_pll_vals *pv) -{ - NVPtr pNv = NVPTR(pScrn); - int chip_version = pNv->vbios->chip_version; - uint32_t oldpll = NVReadRAMDAC(pNv, 0, reg); - int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff; - uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1; - uint32_t saved_powerctrl_1 = 0; - int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg); - - if (oldpll == pll) - return; /* already set */ - - if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nvReadMC(pNv, NV_PBUS_POWERCTRL_1); - nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, - (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | - 1 << shift_powerctrl_1); - } - - if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1)) - /* upclock -- write new post divider first */ - NVWriteRAMDAC(pNv, 0, reg, pv->log2P << 16 | (oldpll & 0xffff)); - else - /* downclock -- write new NM first */ - NVWriteRAMDAC(pNv, 0, reg, (oldpll & 0xffff0000) | pv->NM1); - - if (chip_version < 0x17 && chip_version != 0x11) - /* wait a bit on older chips */ - usleep(64000); - NVReadRAMDAC(pNv, 0, reg); - - /* then write the other half as well */ - NVWriteRAMDAC(pNv, 0, reg, pll); - - if (shift_powerctrl_1 >= 0) - nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); -} - -static uint32_t new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580) -{ - bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF); - - if (ss) /* single stage pll mode */ - ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE : - NV_RAMDAC_580_VPLL2_ACTIVE; - else - ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE : - ~NV_RAMDAC_580_VPLL2_ACTIVE; - - return ramdac580; -} - -static void setPLL_double_highregs(ScrnInfoPtr pScrn, uint32_t reg1, - struct nouveau_pll_vals *pv) -{ - NVPtr pNv = NVPTR(pScrn); - int chip_version = pNv->vbios->chip_version; - bool nv3035 = chip_version == 0x30 || chip_version == 0x35; - uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70); - uint32_t oldpll1 = NVReadRAMDAC(pNv, 0, reg1); - uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(pNv, 0, reg2) : 0; - uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1; - uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2; - uint32_t oldramdac580 = 0, ramdac580 = 0; - bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */ - uint32_t saved_powerctrl_1 = 0, savedc040 = 0; - int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1); - - /* model specific additions to generic pll1 and pll2 set up above */ - if (nv3035) { - pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 | - (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4; - pll2 = 0; - } - if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */ - oldramdac580 = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_580); - ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580); - if (oldramdac580 != ramdac580) - oldpll1 = ~0; /* force mismatch */ - if (single_stage) - /* magic value used by nvidia in single stage mode */ - pll2 |= 0x011f; - } - if (chip_version > 0x70) - /* magic bits set by the blob (but not the bios) on g71-73 */ - pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28; - - if (oldpll1 == pll1 && oldpll2 == pll2) - return; /* already set */ - - if (shift_powerctrl_1 >= 0) { - saved_powerctrl_1 = nvReadMC(pNv, NV_PBUS_POWERCTRL_1); - nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, - (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) | - 1 << shift_powerctrl_1); - } - - if (chip_version >= 0x40) { - int shift_c040 = 14; - - switch (reg1) { - case NV_PRAMDAC_MPLL_COEFF: - shift_c040 += 2; - case NV_PRAMDAC_NVPLL_COEFF: - shift_c040 += 2; - case NV_RAMDAC_VPLL2: - shift_c040 += 2; - case NV_PRAMDAC_VPLL_COEFF: - shift_c040 += 2; - } - - savedc040 = nvReadMC(pNv, 0xc040); - if (shift_c040 != 14) - nvWriteMC(pNv, 0xc040, savedc040 & ~(3 << shift_c040)); - } - - if (oldramdac580 != ramdac580) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_580, ramdac580); - - if (!nv3035) - NVWriteRAMDAC(pNv, 0, reg2, pll2); - NVWriteRAMDAC(pNv, 0, reg1, pll1); - - if (shift_powerctrl_1 >= 0) - nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, saved_powerctrl_1); - if (chip_version >= 0x40) - nvWriteMC(pNv, 0xc040, savedc040); -} - -static void setPLL_double_lowregs(ScrnInfoPtr pScrn, uint32_t NMNMreg, - struct nouveau_pll_vals *pv) -{ - /* When setting PLLs, there is a merry game of disabling and enabling - * various bits of hardware during the process. This function is a - * synthesis of six nv4x traces, nearly each card doing a subtly - * different thing. With luck all the necessary bits for each card are - * combined herein. Without luck it deviates from each card's formula - * so as to not work on any :) - */ - - NVPtr pNv = NVPTR(pScrn); - uint32_t Preg = NMNMreg - 4; - bool mpll = Preg == 0x4020; - uint32_t oldPval = nvReadMC(pNv, Preg); - uint32_t NMNM = pv->NM2 << 16 | pv->NM1; - uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) | - 0xc << 28 | pv->log2P << 16; - uint32_t saved4600 = 0; - /* some cards have different maskc040s */ - uint32_t maskc040 = ~(3 << 14), savedc040; - bool single_stage = !pv->NM2 || pv->N2 == pv->M2; - - if (nvReadMC(pNv, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval) - return; - - if (Preg == 0x4000) - maskc040 = ~0x333; - if (Preg == 0x4058) - maskc040 = ~(0xc << 24); - - if (mpll) { - struct pll_lims pll_lim; - uint8_t Pval2; - - if (get_pll_limits(pScrn, Preg, &pll_lim)) - return; - - Pval2 = pv->log2P + pll_lim.log2p_bias; - if (Pval2 > pll_lim.max_log2p) - Pval2 = pll_lim.max_log2p; - Pval |= 1 << 28 | Pval2 << 20; - - saved4600 = nvReadMC(pNv, 0x4600); - nvWriteMC(pNv, 0x4600, saved4600 | 8 << 28); - } - if (single_stage) - Pval |= mpll ? 1 << 12 : 1 << 8; - - nvWriteMC(pNv, Preg, oldPval | 1 << 28); - nvWriteMC(pNv, Preg, Pval & ~(4 << 28)); - if (mpll) { - Pval |= 8 << 20; - nvWriteMC(pNv, 0x4020, Pval & ~(0xc << 28)); - nvWriteMC(pNv, 0x4038, Pval & ~(0xc << 28)); - } - - savedc040 = nvReadMC(pNv, 0xc040); - nvWriteMC(pNv, 0xc040, savedc040 & maskc040); - - nvWriteMC(pNv, NMNMreg, NMNM); - if (NMNMreg == 0x4024) - nvWriteMC(pNv, 0x403c, NMNM); - - nvWriteMC(pNv, Preg, Pval); - if (mpll) { - Pval &= ~(8 << 20); - nvWriteMC(pNv, 0x4020, Pval); - nvWriteMC(pNv, 0x4038, Pval); - nvWriteMC(pNv, 0x4600, saved4600); - } - - nvWriteMC(pNv, 0xc040, savedc040); - - if (mpll) { - nvWriteMC(pNv, 0x4020, Pval & ~(1 << 28)); - nvWriteMC(pNv, 0x4038, Pval & ~(1 << 28)); - } -} - -void nouveau_hw_setpll(ScrnInfoPtr pScrn, uint32_t reg1, - struct nouveau_pll_vals *pv) -{ - int cv = NVPTR(pScrn)->vbios->chip_version; - - if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || - cv >= 0x40) { - if (reg1 > 0x405c) - setPLL_double_highregs(pScrn, reg1, pv); - else - setPLL_double_lowregs(pScrn, reg1, pv); - } else - setPLL_single(pScrn, reg1, pv); -} - -/* - * PLL getting - */ - -static void nouveau_hw_decode_pll(NVPtr pNv, uint32_t reg1, - uint32_t pll1, uint32_t pll2, - struct nouveau_pll_vals *pllvals) -{ - /* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */ - - /* log2P is & 0x7 as never more than 7, and nv30/35 only uses 3 bits */ - pllvals->log2P = (pll1 >> 16) & 0x7; - pllvals->N2 = pllvals->M2 = 1; - - if (reg1 <= 0x405c) { - pllvals->NM1 = pll2 & 0xffff; - /* single stage NVPLL and VPLLs use 1 << 8, MPLL uses 1 << 12 */ - if (!(pll1 & 0x1100)) - pllvals->NM2 = pll2 >> 16; - } else { - pllvals->NM1 = pll1 & 0xffff; - if (pNv->two_reg_pll && pll2 & NV31_RAMDAC_ENABLE_VCO2) - pllvals->NM2 = pll2 & 0xffff; - else if (pNv->NVArch == 0x30 || pNv->NVArch == 0x35) { - pllvals->M1 &= 0xf; /* only 4 bits */ - if (pll1 & NV30_RAMDAC_ENABLE_VCO2) { - pllvals->M2 = (pll1 >> 4) & 0x7; - pllvals->N2 = ((pll1 >> 21) & 0x18) | - ((pll1 >> 19) & 0x7); - } - } - } -} - -int nouveau_hw_get_pllvals(ScrnInfoPtr pScrn, enum pll_types plltype, - struct nouveau_pll_vals *pllvals) -{ - NVPtr pNv = NVPTR(pScrn); - const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF, - NV_PRAMDAC_MPLL_COEFF, - NV_PRAMDAC_VPLL_COEFF, - NV_RAMDAC_VPLL2 }; - const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000, - 0x4020, - NV_PRAMDAC_VPLL_COEFF, - NV_RAMDAC_VPLL2 }; - uint32_t reg1, pll1, pll2 = 0; - struct pll_lims pll_lim; - int ret; - - if (pNv->Architecture < NV_ARCH_40) - reg1 = nv04_regs[plltype]; - else - reg1 = nv40_regs[plltype]; - - pll1 = nvReadMC(pNv, reg1); - - if (reg1 <= 0x405c) - pll2 = nvReadMC(pNv, reg1 + 4); - else if (pNv->two_reg_pll) { - uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70); - - pll2 = nvReadMC(pNv, reg2); - } - - if (pNv->Architecture == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { - uint32_t ramdac580 = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_580); - - /* check whether vpll has been forced into single stage mode */ - if (reg1 == NV_PRAMDAC_VPLL_COEFF) { - if (ramdac580 & NV_RAMDAC_580_VPLL1_ACTIVE) - pll2 = 0; - } else - if (ramdac580 & NV_RAMDAC_580_VPLL2_ACTIVE) - pll2 = 0; - } - - nouveau_hw_decode_pll(pNv, reg1, pll1, pll2, pllvals); - - if ((ret = get_pll_limits(pScrn, plltype, &pll_lim))) - return ret; - - pllvals->refclk = pll_lim.refclk; - - return 0; -} - -int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv) -{ - /* Avoid divide by zero if called at an inappropriate time */ - if (!pv->M1 || !pv->M2) - return 0; - - return (pv->N1 * pv->N2 * pv->refclk / (pv->M1 * pv->M2) >> pv->log2P); -} - -int nouveau_hw_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_pll_vals pllvals; - - if (plltype == MPLL && (pNv->Chipset & 0x0ff0) == CHIPSET_NFORCE) { - struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 3); - uint32_t mpllP; - - pci_device_cfg_read_u32(dev, &mpllP, 0x6c); - mpllP = (mpllP >> 8) & 0xf; - - if (!mpllP) - mpllP = 4; - return 400000 / mpllP; - } else - if (plltype == MPLL && (pNv->Chipset & 0xff0) == CHIPSET_NFORCE2) { - struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 5); - uint32_t data; - - pci_device_cfg_read_u32(dev, &data, 0x4c); - - return data / 1000; - } - - nouveau_hw_get_pllvals(pScrn, plltype, &pllvals); - - return nouveau_hw_pllvals_to_clk(&pllvals); -} - -static void nouveau_hw_fix_bad_vpll(ScrnInfoPtr pScrn, int head) -{ - /* the vpll on an unused head can come up with a random value, way - * beyond the pll limits. for some reason this causes the chip to - * lock up when reading the dac palette regs, so set a valid pll here - * when such a condition detected. only seen on nv11 to date - */ - - struct pll_lims pll_lim; - struct nouveau_pll_vals pv; - uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; - - if (get_pll_limits(pScrn, head ? VPLL2 : VPLL1, &pll_lim)) - return; - nouveau_hw_get_pllvals(pScrn, head ? VPLL2 : VPLL1, &pv); - - if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && - pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && - pv.log2P <= pll_lim.max_log2p) - return; - - NV_WARN(pScrn, "VPLL %d outwith limits, attempting to fix\n", head + 1); - - /* set lowest clock within static limits */ - pv.M1 = pll_lim.vco1.max_m; - pv.N1 = pll_lim.vco1.min_n; - pv.log2P = pll_lim.max_usable_log2p; - nouveau_hw_setpll(pScrn, pllreg, &pv); -} - -/* - * vga font save/restore - */ - -void nouveau_hw_save_vga_fonts(ScrnInfoPtr pScrn, bool save) -{ - NVPtr pNv = NVPTR(pScrn); - bool graphicsmode; - uint8_t misc, gr4, gr5, gr6, seq2, seq4; - int i; - - if (pNv->twoHeads) - NVSetOwner(pNv, 0); - - NVSetEnablePalette(pNv, 0, true); - graphicsmode = NVReadVgaAttr(pNv, 0, NV_CIO_AR_MODE_INDEX) & 1; - NVSetEnablePalette(pNv, 0, false); - - if (graphicsmode) /* graphics mode => framebuffer => no need to save */ - return; - - NV_TRACE(pScrn, "%sing VGA fonts\n", save ? "Sav" : "Restor"); - if (pNv->twoHeads) - NVBlankScreen(pNv, 1, true); - NVBlankScreen(pNv, 0, true); - - /* save control regs */ - misc = NVReadPRMVIO(pNv, 0, NV_PRMVIO_MISC__READ); - seq2 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX); - seq4 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX); - gr4 = NVReadVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX); - gr5 = NVReadVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX); - gr6 = NVReadVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX); - - NVWritePRMVIO(pNv, 0, NV_PRMVIO_MISC__WRITE, 0x67); - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX, 0x6); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX, 0x0); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX, 0x5); - - /* store font in plane 0 */ - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x1); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x0); - for (i = 0; i < 16384; i++) - if (save) - pNv->saved_vga_font[0][i] = MMIO_IN32(pNv->FB_BAR, i * 4); - else - MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[0][i]); - - /* store font in plane 1 */ - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x2); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x1); - for (i = 0; i < 16384; i++) - if (save) - pNv->saved_vga_font[1][i] = MMIO_IN32(pNv->FB_BAR, i * 4); - else - MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[1][i]); - - /* store font in plane 2 */ - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x4); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x2); - for (i = 0; i < 16384; i++) - if (save) - pNv->saved_vga_font[2][i] = MMIO_IN32(pNv->FB_BAR, i * 4); - else - MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[2][i]); - - /* store font in plane 3 */ - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x8); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x3); - for (i = 0; i < 16384; i++) - if (save) - pNv->saved_vga_font[3][i] = MMIO_IN32(pNv->FB_BAR, i * 4); - else - MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[3][i]); - - /* restore control regs */ - NVWritePRMVIO(pNv, 0, NV_PRMVIO_MISC__WRITE, misc); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, gr4); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX, gr5); - NVWriteVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX, gr6); - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, seq2); - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX, seq4); - - if (pNv->twoHeads) - NVBlankScreen(pNv, 1, false); - NVBlankScreen(pNv, 0, false); -} - -/* - * mode state save/load - */ - -static void rd_cio_state(NVPtr pNv, int head, - struct nouveau_crtc_state *crtcstate, int index) -{ - crtcstate->CRTC[index] = NVReadVgaCrtc(pNv, head, index); -} - -static void wr_cio_state(NVPtr pNv, int head, - struct nouveau_crtc_state *crtcstate, int index) -{ - NVWriteVgaCrtc(pNv, head, index, crtcstate->CRTC[index]); -} - -static void -nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *state) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc_state *regp = &state->head[head]; - int i; - - if (pNv->Architecture >= NV_ARCH_10) - regp->nv10_cursync = NVReadRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC); - - nouveau_hw_get_pllvals(pScrn, head ? VPLL2 : VPLL1, ®p->pllvals); - state->pllsel = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT); - if (pNv->twoHeads) - state->sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK); - if (pNv->NVArch == 0x11) - regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11); - - regp->ramdac_gen_ctrl = NVReadRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL); - - if (pNv->gf4_disp_arch) - regp->ramdac_630 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_630); - if (pNv->NVArch >= 0x30) - regp->ramdac_634 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_634); - - for (i = 0; i < 7; i++) { - uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4); - - regp->fp_vert_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg); - regp->fp_horiz_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg + 0x20); - } - - if (pNv->gf4_disp_arch) { - regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER); - for (i = 0; i < 3; i++) { - regp->dither_regs[i] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4); - regp->dither_regs[i + 3] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4); - } - } - - regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL); - regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0); - if (!pNv->gf4_disp_arch && head == 0) - /* early chips don't allow access to PRAMDAC_TMDS_* without - * the head A FPCLK on (nv11 even locks up) */ - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0 & - ~NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK); - regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1); - regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2); - - if (pNv->Architecture == NV_ARCH_40) { - regp->ramdac_a20 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A20); - regp->ramdac_a24 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A24); - regp->ramdac_a34 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A34); - } -} - -static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *state) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc_state *regp = &state->head[head]; - uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; - int i; - - if (pNv->Architecture >= NV_ARCH_10) - NVWriteRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync); - - nouveau_hw_setpll(pScrn, pllreg, ®p->pllvals); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); - if (pNv->twoHeads) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk); - if (pNv->NVArch == 0x11) - NVWriteRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11, regp->dither); - - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl); - - if (pNv->gf4_disp_arch) - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_630, regp->ramdac_630); - if (pNv->NVArch >= 0x30) - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_634, regp->ramdac_634); - - for (i = 0; i < 7; i++) { - uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4); - - NVWriteRAMDAC(pNv, head, ramdac_reg, regp->fp_vert_regs[i]); - NVWriteRAMDAC(pNv, head, ramdac_reg + 0x20, regp->fp_horiz_regs[i]); - } - - if (pNv->gf4_disp_arch) { - NVWriteRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER, regp->dither); - for (i = 0; i < 3; i++) { - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4, regp->dither_regs[i]); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4, regp->dither_regs[i + 3]); - } - } - - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2); - - if (pNv->Architecture == NV_ARCH_40) { - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A24, regp->ramdac_a24); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A34, regp->ramdac_a34); - } -} - -static void -nv_save_state_vga(NVPtr pNv, int head, struct nouveau_mode_state *state) -{ - struct nouveau_crtc_state *regp = &state->head[head]; - int i; - - regp->MiscOutReg = NVReadPRMVIO(pNv, head, NV_PRMVIO_MISC__READ); - - for (i = 0; i < 25; i++) - rd_cio_state(pNv, head, regp, i); - - NVSetEnablePalette(pNv, head, true); - for (i = 0; i < 21; i++) - regp->Attribute[i] = NVReadVgaAttr(pNv, head, i); - NVSetEnablePalette(pNv, head, false); - - for (i = 0; i < 9; i++) - regp->Graphics[i] = NVReadVgaGr(pNv, head, i); - - for (i = 0; i < 5; i++) - regp->Sequencer[i] = NVReadVgaSeq(pNv, head, i); -} - -static void nv_load_state_vga(NVPtr pNv, int head, struct nouveau_mode_state *state) -{ - struct nouveau_crtc_state *regp = &state->head[head]; - int i; - - NVWritePRMVIO(pNv, head, NV_PRMVIO_MISC__WRITE, regp->MiscOutReg); - - for (i = 0; i < 5; i++) - NVWriteVgaSeq(pNv, head, i, regp->Sequencer[i]); - - nv_lock_vga_crtc_base(pNv, head, false); - for (i = 0; i < 25; i++) - wr_cio_state(pNv, head, regp, i); - nv_lock_vga_crtc_base(pNv, head, true); - - for (i = 0; i < 9; i++) - NVWriteVgaGr(pNv, head, i, regp->Graphics[i]); - - NVSetEnablePalette(pNv, head, true); - for (i = 0; i < 21; i++) - NVWriteVgaAttr(pNv, head, i, regp->Attribute[i]); - NVSetEnablePalette(pNv, head, false); -} - -static void -nv_save_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *state) -{ - struct nouveau_crtc_state *regp = &state->head[head]; - int i; - - rd_cio_state(pNv, head, regp, NV_CIO_CRE_LCD__INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_RPC0_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_RPC1_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_LSR_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_PIXEL_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_HEB__INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_ENH_INDEX); - - rd_cio_state(pNv, head, regp, NV_CIO_CRE_FF_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_FFLWM__INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_21); - if (pNv->Architecture >= NV_ARCH_30) - rd_cio_state(pNv, head, regp, NV_CIO_CRE_47); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_ILACE__INDEX); - - if (pNv->Architecture >= NV_ARCH_10) { - regp->crtc_830 = NVReadCRTC(pNv, head, NV_PCRTC_830); - regp->crtc_834 = NVReadCRTC(pNv, head, NV_PCRTC_834); - if (pNv->Architecture == NV_ARCH_40) { - regp->crtc_850 = NVReadCRTC(pNv, head, NV_PCRTC_850); - regp->gpio_ext = NVReadCRTC(pNv, head, NV_PCRTC_GPIO_EXT); - } - if (pNv->twoHeads) - regp->crtc_eng_ctrl = NVReadCRTC(pNv, head, NV_PCRTC_ENGINE_CTRL); - regp->cursor_cfg = NVReadCRTC(pNv, head, NV_PCRTC_CURSOR_CONFIG); - } - - regp->crtc_cfg = NVReadCRTC(pNv, head, NV_PCRTC_CONFIG); - - rd_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); - if (pNv->Architecture >= NV_ARCH_10) { - rd_cio_state(pNv, head, regp, NV_CIO_CRE_EBR_INDEX); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_CSB); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_4B); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY); - } - if (pNv->gf4_disp_arch) { - rd_cio_state(pNv, head, regp, NV_CIO_CRE_53); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_54); - - for (i = 0; i < 0x10; i++) - regp->CR58[i] = NVReadVgaCrtc5758(pNv, head, i); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_59); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_5B); - - rd_cio_state(pNv, head, regp, NV_CIO_CRE_85); - rd_cio_state(pNv, head, regp, NV_CIO_CRE_86); - } - - regp->fb_start = NVReadCRTC(pNv, head, NV_PCRTC_START); -} - -static void nv_load_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *state) -{ - struct nouveau_crtc_state *regp = &state->head[head]; - int i; - - if (pNv->Architecture >= NV_ARCH_10) { - if (pNv->twoHeads) - /* setting ENGINE_CTRL (EC) *must* come before - * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in - * EC that should not be overwritten by writing stale EC - */ - NVWriteCRTC(pNv, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl); - - nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1); - nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0); - nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0); - nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0); - nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1); - nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1); - nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1); - nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1); - nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0); - - NVWriteCRTC(pNv, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); - NVWriteCRTC(pNv, head, NV_PCRTC_830, regp->crtc_830); - NVWriteCRTC(pNv, head, NV_PCRTC_834, regp->crtc_834); - if (pNv->Architecture == NV_ARCH_40) { - NVWriteCRTC(pNv, head, NV_PCRTC_850, regp->crtc_850); - NVWriteCRTC(pNv, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext); - } - - if (pNv->Architecture == NV_ARCH_40) { - uint32_t reg900 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_900); - if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_900, reg900 | 0x10000); - else - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_900, reg900 & ~0x10000); - } - } - - NVWriteCRTC(pNv, head, NV_PCRTC_CONFIG, regp->crtc_cfg); - - wr_cio_state(pNv, head, regp, NV_CIO_CRE_RPC0_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_RPC1_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_LSR_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_PIXEL_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_LCD__INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_HEB__INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_ENH_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_FF_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_FFLWM__INDEX); - if (pNv->Architecture >= NV_ARCH_30) - wr_cio_state(pNv, head, regp, NV_CIO_CRE_47); - - wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); - if (pNv->Architecture == NV_ARCH_40) - nv_fix_nv40_hw_cursor(pNv, head); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_ILACE__INDEX); - - wr_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); - if (pNv->Architecture >= NV_ARCH_10) { - wr_cio_state(pNv, head, regp, NV_CIO_CRE_EBR_INDEX); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_CSB); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_4B); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY); - } - if (pNv->gf4_disp_arch) { - wr_cio_state(pNv, head, regp, NV_CIO_CRE_53); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_54); - - for (i = 0; i < 0x10; i++) - NVWriteVgaCrtc5758(pNv, head, i, regp->CR58[i]); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_59); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_5B); - - wr_cio_state(pNv, head, regp, NV_CIO_CRE_85); - wr_cio_state(pNv, head, regp, NV_CIO_CRE_86); - } - - NVWriteCRTC(pNv, head, NV_PCRTC_START, regp->fb_start); - - /* Setting 1 on this value gives you interrupts for every vblank period. */ - NVWriteCRTC(pNv, head, NV_PCRTC_INTR_EN_0, 0); - NVWriteCRTC(pNv, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); -} - -static void -nv_save_state_palette(NVPtr pNv, int head, struct nouveau_mode_state *state) -{ - int head_offset = head * NV_PRMDIO_SIZE, i; - - VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK); - VGA_WR08(pNv->REGS, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); - - for (i = 0; i < 768; i++) { - state->head[head].DAC[i] = NV_RD08(pNv->REGS, NV_PRMDIO_PALETTE_DATA + head_offset); - DDXMMIOH("nv_save_state_palette: head %d reg 0x%04x data 0x%02x\n", head, NV_PRMDIO_PALETTE_DATA + head_offset, state->head[head].DAC[i]); - } - - NVSetEnablePalette(pNv, head, false); -} - -void nouveau_hw_load_state_palette(NVPtr pNv, int head, - struct nouveau_mode_state *state) -{ - int head_offset = head * NV_PRMDIO_SIZE, i; - - VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK); - VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); - - for (i = 0; i < 768; i++) { - DDXMMIOH("nouveau_mode_state_load_palette: head %d reg 0x%04x data 0x%02x\n", head, NV_PRMDIO_PALETTE_DATA + head_offset, state->head[head].DAC[i]); - NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA + head_offset, state->head[head].DAC[i]); - } - - NVSetEnablePalette(pNv, head, false); -} - -void nouveau_hw_save_state(ScrnInfoPtr pScrn, int head, - struct nouveau_mode_state *state) -{ - NVPtr pNv = NVPTR(pScrn); - - if (pNv->NVArch == 0x11) - /* NB: no attempt is made to restore the bad pll later on */ - nouveau_hw_fix_bad_vpll(pScrn, head); - nv_save_state_ramdac(pScrn, head, state); - nv_save_state_vga(pNv, head, state); - nv_save_state_palette(pNv, head, state); - nv_save_state_ext(pNv, head, state); -} - -void nouveau_hw_load_state(ScrnInfoPtr pScrn, int head, - struct nouveau_mode_state *state) -{ - NVPtr pNv = NVPTR(pScrn); - - NVVgaProtect(pNv, head, true); - nv_load_state_ramdac(pScrn, head, state); - nv_load_state_ext(pNv, head, state); - nouveau_hw_load_state_palette(pNv, head, state); - nv_load_state_vga(pNv, head, state); - NVVgaProtect(pNv, head, false); -} diff --git a/src/nouveau_hw.h b/src/nouveau_hw.h deleted file mode 100644 index aa2a3b4..0000000 --- a/src/nouveau_hw.h +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright 2008 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NOUVEAU_HW_H__ -#define __NOUVEAU_HW_H__ - -#define MASK(field) ((0xffffffff >> (31 - ((1?field) - (0?field)))) << (0?field)) -#define XLATE(src, srclowbit, outfield) ((((src) >> (srclowbit)) << (0?outfield)) & MASK(outfield)) - -#define nvReadMC(pNv, reg) DDXMMIOW("nvReadMC: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg)) -#define nvWriteMC(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteMC: reg %08x val %08x\n", reg, val)) - -#define nvReadVIDEO(pNv, reg) DDXMMIOW("nvReadVIDEO: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg)) -#define nvWriteVIDEO(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteVIDEO: reg %08x val %08x\n", reg, val)) - -#define nvReadFB(pNv, reg) DDXMMIOW("nvReadFB: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg)) -#define nvWriteFB(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteFB: reg %08x val %08x\n", reg, val)) - -#define nvReadEXTDEV(pNv, reg) DDXMMIOW("nvReadEXTDEV: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg)) -#define nvWriteEXTDEV(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteEXTDEV: reg %08x val %08x\n", reg, val)) - -static inline uint32_t NVRead(NVPtr pNv, uint32_t reg) -{ - DDXMMIOW("NVRead: reg %08x val %08x\n", reg, (uint32_t)NV_RD32(pNv->REGS, reg)); - return NV_RD32(pNv->REGS, reg); -} - -static inline void NVWrite(NVPtr pNv, uint32_t reg, uint32_t val) -{ - DDXMMIOW("NVWrite: reg %08x val %08x\n", reg, NV_WR32(pNv->REGS, reg, val)); -} - -static inline uint32_t NVReadCRTC(NVPtr pNv, int head, uint32_t reg) -{ - if (head) - reg += NV_PCRTC0_SIZE; - DDXMMIOH("NVReadCRTC: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg)); - return NV_RD32(pNv->REGS, reg); -} - -static inline void NVWriteCRTC(NVPtr pNv, int head, uint32_t reg, uint32_t val) -{ - if (head) - reg += NV_PCRTC0_SIZE; - DDXMMIOH("NVWriteCRTC: head %d reg %08x val %08x\n", head, reg, val); - NV_WR32(pNv->REGS, reg, val); -} - -static inline uint32_t NVReadRAMDAC(NVPtr pNv, int head, uint32_t reg) -{ - if (head) - reg += NV_PRAMDAC0_SIZE; - DDXMMIOH("NVReadRamdac: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg)); - return NV_RD32(pNv->REGS, reg); -} - -static inline void -NVWriteRAMDAC(NVPtr pNv, int head, uint32_t reg, uint32_t val) -{ - if (head) - reg += NV_PRAMDAC0_SIZE; - DDXMMIOH("NVWriteRamdac: head %d reg %08x val %08x\n", head, reg, val); - NV_WR32(pNv->REGS, reg, val); -} - -static inline uint8_t nv_read_tmds(NVPtr pNv, int or, int dl, uint8_t address) -{ - int ramdac = (or & OUTPUT_C) >> 2; - - NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, - NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address); - return NVReadRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8); -} - -static inline void -nv_write_tmds(NVPtr pNv, int or, int dl, uint8_t address, uint8_t data) -{ - int ramdac = (or & OUTPUT_C) >> 2; - - NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data); - NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address); -} - -static inline void -NVWriteVgaCrtc(NVPtr pNv, int head, uint8_t index, uint8_t value) -{ - DDXMMIOH("NVWriteVgaCrtc: head %d index 0x%02x data 0x%02x\n", head, index, value); - NV_WR08(pNv->REGS, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); - NV_WR08(pNv->REGS, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); -} - -static inline uint8_t NVReadVgaCrtc(NVPtr pNv, int head, uint8_t index) -{ - NV_WR08(pNv->REGS, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); - DDXMMIOH("NVReadVgaCrtc: head %d index 0x%02x data 0x%02x\n", head, index, NV_RD08(pNv->REGS, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE)); - return NV_RD08(pNv->REGS, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); -} - -/* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58 - * I suspect they in fact do nothing, but are merely a way to carry useful - * per-head variables around - * - * Known uses: - * CR57 CR58 - * 0x00 index to the appropriate dcb entry (or 7f for inactive) - * 0x02 dcb entry's "or" value (or 00 for inactive) - * 0x03 bit0 set for dual link (LVDS, possibly elsewhere too) - * 0x08 or 0x09 pxclk in MHz - * 0x0f laptop panel info - low nibble for PEXTDEV_BOOT_0 strap - * high nibble for xlat strap value - */ - -static inline void -NVWriteVgaCrtc5758(NVPtr pNv, int head, uint8_t index, uint8_t value) -{ - NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_57, index); - NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_58, value); -} - -static inline uint8_t NVReadVgaCrtc5758(NVPtr pNv, int head, uint8_t index) -{ - NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_57, index); - return NVReadVgaCrtc(pNv, head, NV_CIO_CRE_58); -} - -static inline uint8_t NVReadPRMVIO(NVPtr pNv, int head, uint32_t reg) -{ - /* Only NV4x have two pvio ranges; other twoHeads cards MUST call - * NVSetOwner for the relevant head to be programmed */ - if (head && pNv->Architecture == NV_ARCH_40) - reg += NV_PRMVIO_SIZE; - - DDXMMIOH("NVReadPRMVIO: head %d reg %08x val %02x\n", head, reg, NV_RD08(pNv->REGS, reg)); - return NV_RD08(pNv->REGS, reg); -} - -static inline void -NVWritePRMVIO(NVPtr pNv, int head, uint32_t reg, uint8_t value) -{ - /* Only NV4x have two pvio ranges; other twoHeads cards MUST call - * NVSetOwner for the relevant head to be programmed */ - if (head && pNv->Architecture == NV_ARCH_40) - reg += NV_PRMVIO_SIZE; - - DDXMMIOH("NVWritePRMVIO: head %d reg %08x val %02x\n", head, reg, value); - NV_WR08(pNv->REGS, reg, value); -} - -static inline void NVSetEnablePalette(NVPtr pNv, int head, bool enable) -{ - VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - VGA_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, - enable ? 0 : 0x20); -} - -static inline bool NVGetEnablePalette(NVPtr pNv, int head) -{ - VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - return !(VGA_RD08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & - 0x20); -} - -static inline void NVWriteVgaAttr(NVPtr pNv, int head, uint8_t index, uint8_t value) -{ - if (NVGetEnablePalette(pNv, head)) - index &= ~0x20; - else - index |= 0x20; - - NV_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - DDXMMIOH("NVWriteVgaAttr: head %d index 0x%02x data 0x%02x\n", head, index, value); - NV_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); - NV_WR08(pNv->REGS, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); -} - -static inline uint8_t NVReadVgaAttr(NVPtr pNv, int head, uint8_t index) -{ - if (NVGetEnablePalette(pNv, head)) - index &= ~0x20; - else - index |= 0x20; - - NV_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); - NV_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); - DDXMMIOH("NVReadVgaAttr: head %d index 0x%02x data 0x%02x\n", head, index, NV_RD08(pNv->REGS, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE)); - return NV_RD08(pNv->REGS, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); -} - -static inline void NVVgaSeqReset(NVPtr pNv, int head, bool start) -{ - NVWriteVgaSeq(pNv, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3); -} - -static inline void NVVgaProtect(NVPtr pNv, int head, bool protect) -{ - uint8_t seq1 = NVReadVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX); - - if (protect) { - NVVgaSeqReset(pNv, head, true); - NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20); - } else { - /* Reenable sequencer, then turn on screen */ - NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); /* reenable display */ - NVVgaSeqReset(pNv, head, false); - } - NVSetEnablePalette(pNv, head, protect); -} - -static inline bool nv_heads_tied(NVPtr pNv) -{ - if (pNv->NVArch == 0x11) - return !!(nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)); - - return (NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44) & 0x4); -} - -/* makes cr0-7 on the specified head read-only */ -static inline bool nv_lock_vga_crtc_base(NVPtr pNv, int head, bool lock) -{ - uint8_t cr11 = NVReadVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX); - bool waslocked = cr11 & 0x80; - - if (lock) - cr11 |= 0x80; - else - cr11 &= ~0x80; - NVWriteVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX, cr11); - - return waslocked; -} - -static inline void nv_lock_vga_crtc_shadow(NVPtr pNv, int head, int lock) -{ - /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs - * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB - * bit6: seems to have some effect on CR09 (double scan, VBS_9) - * bit5: unlocks HDE - * bit4: unlocks VDE - * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR - * bit2: same as bit 1 of 0x60?804 - * bit0: same as bit 0 of 0x60?804 - */ - - uint8_t cr21 = lock; - - if (lock < 0) - /* 0xfa is generic "unlock all" mask */ - cr21 = NVReadVgaCrtc(pNv, head, NV_CIO_CRE_21) | 0xfa; - - NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_21, cr21); -} - -/* renders the extended crtc regs (cr19+) on all crtcs impervious: - * immutable and unreadable - */ -static inline bool NVLockVgaCrtcs(NVPtr pNv, bool lock) -{ - bool waslocked = !NVReadVgaCrtc(pNv, 0, NV_CIO_SR_LOCK_INDEX); - - NVWriteVgaCrtc(pNv, 0, NV_CIO_SR_LOCK_INDEX, - lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); - /* NV11 has independently lockable extended crtcs, except when tied */ - if (pNv->NVArch == 0x11 && !nv_heads_tied(pNv)) - NVWriteVgaCrtc(pNv, 1, NV_CIO_SR_LOCK_INDEX, - lock ? NV_CIO_SR_LOCK_VALUE : - NV_CIO_SR_UNLOCK_RW_VALUE); - - return waslocked; -} - -/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */ -#define NV04_CURSOR_SIZE 32 -/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */ -#define NV10_CURSOR_SIZE 64 - -static inline int nv_cursor_width(NVPtr pNv) -{ - return pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; -} - -static inline int nv_cursor_pixels(NVPtr pNv) -{ - int width = nv_cursor_width(pNv); - - return width * width; -} - -static inline void nv_fix_nv40_hw_cursor(NVPtr pNv, int head) -{ - /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40, - * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS - * for changes to the CRTC CURCTL regs to take effect, whether changing - * the pixmap location, or just showing/hiding the cursor - */ - volatile uint32_t curpos = NVReadRAMDAC(pNv, head, - NV_PRAMDAC_CU_START_POS); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_CU_START_POS, curpos); -} - -static inline void nv_show_cursor(NVPtr pNv, int head, bool show) -{ - uint8_t *curctl1 = - &pNv->set_state.head[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; - - if (show) - *curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); - else - *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); - NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); - - if (pNv->Architecture == NV_ARCH_40) - nv_fix_nv40_hw_cursor(pNv, head); -} - -static inline uint32_t nv_pitch_align(NVPtr pNv, uint32_t width, int bpp) -{ - int mask; - - if (bpp == 15) - bpp = 16; - if (bpp == 24 || bpp == 30) - bpp = 8; - - /* Alignment requirements taken from the Haiku driver */ - if (pNv->Architecture == NV_ARCH_04) - mask = 128 / bpp - 1; - else - mask = 512 / bpp - 1; - - return (width + mask) & ~mask; -} - -#endif /* __NOUVEAU_HW_H__ */ diff --git a/src/nouveau_modeset.h b/src/nouveau_modeset.h deleted file mode 100644 index defc699..0000000 --- a/src/nouveau_modeset.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NOUVEAU_MODESET_H_ -#define __NOUVEAU_MODESET_H_ - -/* Forward declarations. */ -typedef struct nouveauCrtc *nouveauCrtcPtr; -typedef struct nouveauConnector *nouveauConnectorPtr; -typedef struct nouveauOutput *nouveauOutputPtr; - -#endif /* __NOUVEAU_MODESET_H_ */ diff --git a/src/nouveau_ms.h b/src/nouveau_ms.h deleted file mode 100644 index c613be3..0000000 --- a/src/nouveau_ms.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2006 Dave Airlie - * Copyright 2007 Maarten Maathuis - * Copyright 2007-2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __NOUVEAU_MS_H__ -#define __NOUVEAU_MS_H__ - -//#define NOUVEAU_DEBUG -#ifdef NOUVEAU_DEBUG -#define NV_DEBUG(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_INFO, fmt, ##arg) -#else -#define NV_DEBUG(d, fmt, arg...) -#endif -#define NV_ERROR(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_ERROR, fmt, ##arg) -#define NV_INFO(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_PROBED, fmt, ##arg) -#define NV_TRACEWARN(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_NOTICE, fmt, ##arg) -#define NV_TRACE(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_INFO, fmt, ##arg) -#define NV_WARN(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_WARNING, fmt, ##arg) - -#define NV_DPMS_CLEARED 0x80 - -enum scaling_modes { - SCALE_PANEL, - SCALE_FULLSCREEN, - SCALE_ASPECT, - SCALE_NOSCALE, - SCALE_INVALID -}; - -struct nouveau_pll_vals { - union { - struct { -#if X_BYTE_ORDER == X_BIG_ENDIAN - uint8_t N1, M1, N2, M2; -#else - uint8_t M1, N1, M2, N2; -#endif - }; - struct { - uint16_t NM1, NM2; - } __attribute__((packed)); - }; - int log2P; - - int refclk; -}; - -struct nouveau_crtc_state { - uint8_t MiscOutReg; - uint8_t CRTC[0x9f]; - uint8_t CR58[0x10]; - uint8_t Sequencer[5]; - uint8_t Graphics[9]; - uint8_t Attribute[21]; - uint8_t DAC[768]; - - /* PCRTC regs */ - uint32_t fb_start; - uint32_t crtc_cfg; - uint32_t cursor_cfg; - uint32_t gpio_ext; - uint32_t crtc_830; - uint32_t crtc_834; - uint32_t crtc_850; - uint32_t crtc_eng_ctrl; - - /* PRAMDAC regs */ - uint32_t nv10_cursync; - struct nouveau_pll_vals pllvals; - uint32_t ramdac_gen_ctrl; - uint32_t ramdac_630; - uint32_t ramdac_634; - uint32_t fp_horiz_regs[7]; - uint32_t fp_vert_regs[7]; - uint32_t dither; - uint32_t fp_control; - uint32_t dither_regs[6]; - uint32_t fp_debug_0; - uint32_t fp_debug_1; - uint32_t fp_debug_2; - uint32_t ramdac_a20; - uint32_t ramdac_a24; - uint32_t ramdac_a34; -}; - -struct nouveau_encoder_state { - uint32_t output; - int head; -}; - -struct nouveau_mode_state -{ - uint32_t pllsel; - uint32_t sel_clk; - - struct nouveau_crtc_state head[2]; -}; - -struct nouveau_crtc { - int head; - uint8_t last_dpms; - int fp_users; - uint32_t dpms_saved_fp_control; - int saturation, sharpness; - - /* convenient pointer to pNv->set_state.head[head_nr] */ - struct nouveau_crtc_state *state; - - uint32_t cursor_fg, cursor_bg; - - struct nouveau_bo *bo; - ExaOffscreenArea *shadow; - unsigned shadow_pitch; -}; - -struct nouveau_encoder { - uint8_t last_dpms; - struct dcb_entry *dcb; - DisplayModePtr native_mode; - uint8_t scaling_mode; - bool dithering; - bool dual_link; - struct nouveau_encoder_state restore; -}; - -struct nouveau_connector { - xf86MonPtr edid; - I2CBusPtr pDDCBus; - uint16_t possible_encoders; - struct nouveau_encoder *detected_encoder; - struct nouveau_encoder *nv_encoder; -}; - -#define to_nouveau_connector(x) ((struct nouveau_connector *)(x)->driver_private) -#define to_nouveau_crtc(x) ((struct nouveau_crtc *)(x)->driver_private) -#define to_nouveau_encoder(x) ((struct nouveau_connector *)(x)->driver_private)->nv_encoder - -#endif /* __NOUVEAU_MS_H__ */ diff --git a/src/nouveau_output.h b/src/nouveau_output.h deleted file mode 100644 index e2e873d..0000000 --- a/src/nouveau_output.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NOUVEAU_OUTPUT_H_ -#define __NOUVEAU_OUTPUT_H_ - -#include "nv_include.h" -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_connector.h" - -typedef struct nouveauOutput { - ScrnInfoPtr scrn; - - char *name; - Bool active; - nouveauOutputPtr next; - - nouveauCrtcPtr crtc; - nouveauConnectorPtr connector; /* the one that is currently in use, not all possibilities. */ - - /* This can change in rare circumstances, when an output resource is shared. */ - struct dcb_entry *dcb; - int type; - uint8_t allowed_crtc; /* bit0: crtc0, bit1: crtc1 */ - int scale_mode; - Bool dithering; - - /* Mode stuff. */ - DisplayModePtr native_mode; - - /* Function pointers. */ - int (*ModeValid) (nouveauOutputPtr output, DisplayModePtr mode); - void (*ModeSet) (nouveauOutputPtr output, DisplayModePtr mode); - void (*SetClockMode) (nouveauOutputPtr output, int clock); /* maybe another name? */ - - /* This will handle the case where output resources are shared. */ - int (*Sense) (nouveauOutputPtr output); /* this is not for ddc or load detect, and will often just return a fixed type. */ - Bool (*Detect) (nouveauOutputPtr output); /* everything that isn't hotplug detect or ddc */ - - void (*SetPowerMode) (nouveauOutputPtr output, int mode); - - /* Get the last associated crtc of the output. */ - nouveauCrtcPtr (*GetCurrentCrtc) (nouveauOutputPtr output); - - void (*Save) (nouveauOutputPtr output); - void (*Load) (nouveauOutputPtr output); -} nouveauOutputRec; - -#endif /* __NOUVEAU_OUTPUT_H_ */ diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index ee72848..cb950e4 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -285,12 +285,13 @@ NVFreeOverlayMemory(ScrnInfoPtr pScrn) NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); NVFreePortMemory(pScrn, pPriv); - +#if NVOVL_SUPPORT /* "power cycle" the overlay */ nvWriteMC(pNv, NV_PMC_ENABLE, (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF)); nvWriteMC(pNv, NV_PMC_ENABLE, (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000)); +#endif } /** @@ -805,6 +806,7 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, } #endif +#ifdef NVOVL_SUPPORT if (USING_OVERLAY) { char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y, drw_w, drw_h); @@ -845,6 +847,7 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv, ->rotation != RR_Rotate_0) *action_flags &= ~USE_OVERLAY; } +#endif /* At this point the adapter we're going to use is _known_. * You cannot change it now. @@ -991,6 +994,7 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, /* The overlay supports hardware double buffering. We handle this here*/ offset = 0; +#ifdef NVOVL_SUPPORT if (pPriv->doubleBuffer) { int mask = 1 << (pPriv->currentBuffer << 2); @@ -1004,6 +1008,7 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, offset += newFBSize >> 1; } } +#endif /* Now we take a decision regarding the way we send the data to the * card. @@ -1601,7 +1606,7 @@ NVSetupBlitVideo (ScreenPtr pScreen) for(i = 0; i < NUM_BLIT_PORTS; i++) adapt->pPortPrivates[i].ptr = (pointer)(pPriv); - if(pNv->WaitVSyncPossible) { + if (pNv->NVArch >= 0x11) { adapt->pAttributes = NVBlitAttributes; adapt->nAttributes = NUM_BLIT_ATTRIBUTES; } else { @@ -1628,7 +1633,7 @@ NVSetupBlitVideo (ScreenPtr pScreen) pPriv->texture = FALSE; pPriv->bicubic = FALSE; pPriv->doubleBuffer = FALSE; - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = (pNv->NVArch >= 0x11); pNv->blitAdaptor = adapt; @@ -1771,7 +1776,7 @@ NVChipsetHasOverlay(NVPtr pNv) case NV_ARCH_30: return TRUE; case NV_ARCH_40: - if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40) + if (pNv->NVArch == 0x40) return TRUE; break; default: @@ -1798,7 +1803,7 @@ NVSetupOverlayVideo(ScreenPtr pScreen) XF86VideoAdaptorPtr overlayAdaptor = NULL; NVPtr pNv = NVPTR(pScrn); - if (pNv->kms_enable || !NVChipsetHasOverlay(pNv)) + if (1 /*pNv->kms_enable*/ || !NVChipsetHasOverlay(pNv)) return NULL; overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen); @@ -1868,14 +1873,8 @@ NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) for(i = 0; i < NUM_TEXTURE_PORTS; i++) adapt->pPortPrivates[i].ptr = (pointer)(pPriv); - if (pNv->WaitVSyncPossible) { - adapt->pAttributes = NVTexturedAttributes; - adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; - } else { - adapt->pAttributes = NULL; - adapt->nAttributes = 0; - } - + adapt->pAttributes = NVTexturedAttributes; + adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; adapt->pImages = NV30TexturedImages; adapt->nImages = NUM_FORMAT_TEXTURED; adapt->PutVideo = NULL; @@ -1895,7 +1894,7 @@ NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) pPriv->texture = TRUE; pPriv->bicubic = bicubic; pPriv->doubleBuffer = FALSE; - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = TRUE; if (bicubic) pNv->textureAdaptor[1] = adapt; @@ -1955,14 +1954,8 @@ NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) for(i = 0; i < NUM_TEXTURE_PORTS; i++) adapt->pPortPrivates[i].ptr = (pointer)(pPriv); - if(pNv->WaitVSyncPossible) { - adapt->pAttributes = NVTexturedAttributes; - adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; - } else { - adapt->pAttributes = NULL; - adapt->nAttributes = 0; - } - + adapt->pAttributes = NVTexturedAttributes; + adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES; adapt->pImages = NV40TexturedImages; adapt->nImages = NUM_FORMAT_TEXTURED; adapt->PutVideo = NULL; @@ -1982,7 +1975,7 @@ NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic) pPriv->texture = TRUE; pPriv->bicubic = bicubic; pPriv->doubleBuffer = FALSE; - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = TRUE; if (bicubic) pNv->textureAdaptor[1] = adapt; diff --git a/src/nv04_xv_blit.c b/src/nv04_xv_blit.c index 990817c..c1451e3 100644 --- a/src/nv04_xv_blit.c +++ b/src/nv04_xv_blit.c @@ -36,6 +36,8 @@ #define FOURCC_RGB 0x0000003 +#define VSYNC_POSSIBLE (pNv->NVArch >= 0x11) + extern Atom xvSetDefaults, xvSyncToVBlank; /** @@ -139,7 +141,7 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset, NVWaitVSync(pScrn, 1); } - if(pNv->BlendingPossible) { + if ((pNv->Chipset & 0xffff) > CHIPSET_NV04) { BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2); OUT_RING (chan, src_format); @@ -214,13 +216,13 @@ NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute, NVPortPrivPtr pPriv = (NVPortPrivPtr)data; NVPtr pNv = NVPTR(pScrn); - if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { + if ((attribute == xvSyncToVBlank) && VSYNC_POSSIBLE) { if ((value < 0) || (value > 1)) return BadValue; pPriv->SyncToVBlank = value; } else if (attribute == xvSetDefaults) { - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = VSYNC_POSSIBLE; } else return BadMatch; diff --git a/src/nv04_xv_ovl.c b/src/nv04_xv_ovl.c index b24379a..a729193 100644 --- a/src/nv04_xv_ovl.c +++ b/src/nv04_xv_ovl.c @@ -43,9 +43,10 @@ NV04PutOverlayImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset, short src_w, short src_h, short drw_w, short drw_h, RegionPtr clipBoxes) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); +#if NVOVL_SUPPORT + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC]; /*This may not work with NV04 overlay according to rivatv source*/ @@ -103,6 +104,7 @@ NV04PutOverlayImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset, nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, 0x111); nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, (nvReadVIDEO(pNv, NV_PVIDEO_SU_STATE) ^ (1 << 16))); +#endif pPriv->videoStatus = CLIENT_VIDEO_ON; } @@ -183,11 +185,13 @@ NV04GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, void NV04StopOverlay (ScrnInfoPtr pScrn) { +#ifdef NVOVL_SUPPORT NVPtr pNv = NVPTR(pScrn); nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, nvReadVIDEO(pNv, NV_PVIDEO_OVERLAY) &~ 0x1); nvWriteVIDEO(pNv, NV_PVIDEO_OE_STATE, 0); nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, 0); nvWriteVIDEO(pNv, NV_PVIDEO_RM_STATE, 0); +#endif } diff --git a/src/nv10_exa.c b/src/nv10_exa.c index a3425a8..d74b052 100644 --- a/src/nv10_exa.c +++ b/src/nv10_exa.c @@ -725,18 +725,18 @@ NVAccelInitNV10TCL(ScrnInfoPtr pScrn) NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *celsius; - uint32_t class = 0, chipset; + uint32_t class = 0; int i; - chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; - if (((chipset & 0xf0) != NV_ARCH_10) && ((chipset & 0xf0) != NV_ARCH_20)) + if (((pNv->NVArch & 0xf0) != NV_ARCH_10) && + ((pNv->NVArch & 0xf0) != NV_ARCH_20)) return FALSE; - if (chipset >= 0x20 || chipset == 0x1a) + if (pNv->NVArch >= 0x20 || pNv->NVArch == 0x1a) class = NV11TCL; - else if (chipset >= 0x17) + else if (pNv->NVArch >= 0x17) class = NV17TCL; - else if (chipset >= 0x11) + else if (pNv->NVArch >= 0x11) class = NV11TCL; else class = NV10TCL; diff --git a/src/nv10_xv_ovl.c b/src/nv10_xv_ovl.c index 66f7399..ce50b26 100644 --- a/src/nv10_xv_ovl.c +++ b/src/nv10_xv_ovl.c @@ -68,6 +68,7 @@ NV10PutOverlayImage(ScrnInfoPtr pScrn, { NVPtr pNv = NVPTR(pScrn); NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); +#ifdef NVOVL_SUPPORT int buffer = pPriv->currentBuffer; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC]; @@ -125,6 +126,7 @@ NV10PutOverlayImage(ScrnInfoPtr pScrn, nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch); nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0); nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1); +#endif pPriv->videoStatus = CLIENT_VIDEO_ON; } @@ -148,7 +150,6 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; - NVPtr pNv = NVPTR(pScrn); if (attribute == xvBrightness) { if ((value < -512) || (value > 512)) @@ -193,7 +194,10 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, if (attribute == xvSetDefaults) { NVSetPortDefaults(pScrn, pPriv); } else +#ifdef NVOVL_SUPPORT if ( attribute == xvOnCRTCNb) { + NVPtr pNv = NVPTR(pScrn); + if ((value < 0) || (value > 1)) return BadValue; pPriv->overlayCRTC = value; @@ -202,6 +206,7 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, NVWriteCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL, NVReadCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL) & ~NV_CRTC_FSEL_OVERLAY); } else +#endif return BadMatch; NV10WriteOverlayParameters(pScrn); @@ -255,8 +260,10 @@ NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute, void NV10StopOverlay (ScrnInfoPtr pScrn) { +#ifdef NVOVL_SUPPORT NVPtr pNv = NVPTR(pScrn); nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1); +#endif } /** @@ -281,6 +288,7 @@ NV10WriteOverlayParameters (ScrnInfoPtr pScrn) if (satCosine < -1024) satCosine = -1024; +#ifdef NVOVL_SUPPORT nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) | pPriv->contrast); nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) | @@ -290,6 +298,6 @@ NV10WriteOverlayParameters (ScrnInfoPtr pScrn) nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) | (satCosine & 0xffff)); nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey); - +#endif } diff --git a/src/nv30_exa.c b/src/nv30_exa.c index 6350828..a50a6eb 100644 --- a/src/nv30_exa.c +++ b/src/nv30_exa.c @@ -679,7 +679,7 @@ NVAccelInitNV30TCL(ScrnInfoPtr pScrn) #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 #define NV34TCL_CHIPSET_3X_MASK 0x00000010 - chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; + chipset = pNv->NVArch; if ((chipset & 0xf0) != NV_ARCH_30) return TRUE; chipset &= 0xf; diff --git a/src/nv30_xv_tex.c b/src/nv30_xv_tex.c index 2d90e8b..1ecc7b7 100644 --- a/src/nv30_xv_tex.c +++ b/src/nv30_xv_tex.c @@ -430,15 +430,14 @@ NV30SetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 value, pointer data) { NVPortPrivPtr pPriv = (NVPortPrivPtr)data; - NVPtr pNv = NVPTR(pScrn); - if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { + if (attribute == xvSyncToVBlank) { if ((value < 0) || (value > 1)) return BadValue; pPriv->SyncToVBlank = value; } else if (attribute == xvSetDefaults) { - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = TRUE; } else return BadMatch; diff --git a/src/nv40_exa.c b/src/nv40_exa.c index 03efce4..2b36f2d 100644 --- a/src/nv40_exa.c +++ b/src/nv40_exa.c @@ -612,8 +612,7 @@ NVAccelInitNV40TCL(ScrnInfoPtr pScrn) if (!nv40_fp_map_a8[0]) NV40EXAHackupA8Shaders(pScrn); - chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; - + chipset = pNv->NVArch; if ( (chipset & 0xf0) == NV_ARCH_40) { chipset &= 0xf; if (NV40TCL_CHIPSET_4X_MASK & (1<WaitVSyncPossible) { + if (attribute == xvSyncToVBlank) { if ((value < 0) || (value > 1)) return BadValue; pPriv->SyncToVBlank = value; } else if (attribute == xvSetDefaults) { - pPriv->SyncToVBlank = pNv->WaitVSyncPossible; + pPriv->SyncToVBlank = TRUE; } else return BadMatch; diff --git a/src/nv50_connector.c b/src/nv50_connector.c deleted file mode 100644 index f7d6133..0000000 --- a/src/nv50_connector.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -static xf86MonPtr -NV50ConnectorGetEDID(nouveauConnectorPtr connector) -{ - ScrnInfoPtr pScrn = connector->scrn; - xf86MonPtr mon = NULL; - -#ifdef EDID_COMPLETE_RAWDATA - mon = xf86DoEEDID(pScrn->scrnIndex, connector->pDDCBus, TRUE); -#else - mon = xf86DoEDID_DDC2(pScrn->scrnIndex, connector->pDDCBus); -#endif - - if (mon) - xf86DDCApplyQuirks(pScrn->scrnIndex, mon); - - return mon; -} - -static xf86MonPtr -NV50ConnectorDDCDetect(nouveauConnectorPtr connector) -{ - ScrnInfoPtr pScrn = connector->scrn; - xf86MonPtr ddc_mon; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50ConnectorDDCDetect is called.\n"); - - if (!connector->pDDCBus) - return FALSE; - - ddc_mon = NV50ConnectorGetEDID(connector); - - return ddc_mon; -} - -static DisplayModePtr -NV50ConnectorGetDDCModes(nouveauConnectorPtr connector) -{ - ScrnInfoPtr pScrn = connector->scrn; - xf86MonPtr ddc_mon; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50ConnectorGetDDCModes is called.\n"); - - if (!connector->pDDCBus) - return FALSE; - - ddc_mon = NV50ConnectorGetEDID(connector); - if (!ddc_mon) - return NULL; - - return xf86DDCGetModes(pScrn->scrnIndex, ddc_mon); -} - -void -NV50ConnectorInit(ScrnInfoPtr pScrn) -{ - int i; - NVPtr pNv = NVPTR(pScrn); - - /* Maybe a bit overdone, because often only 3 or 4 connectors are present. */ - for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) { - nouveauConnectorPtr connector = xnfcalloc(sizeof(nouveauConnectorRec), 1); - connector->scrn = pScrn; - connector->index = i; - - char connector_name[20]; - sprintf(connector_name, "Connector-%d", i); - connector->name = xstrdup(connector_name); - - /* Function pointers. */ - connector->DDCDetect = NV50ConnectorDDCDetect; - connector->GetDDCModes = NV50ConnectorGetDDCModes; - connector->HotplugDetect = NULL; - - pNv->connector[i] = connector; - } -} - -void -NV50ConnectorDestroy(ScrnInfoPtr pScrn) -{ - int i; - NVPtr pNv = NVPTR(pScrn); - - /* Maybe a bit overdone, because often only 3 or 4 connectors are present. */ - for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) { - nouveauConnectorPtr connector = pNv->connector[i]; - - if (!connector) - continue; - - xfree(connector->name); - xfree(connector); - pNv->connector[i] = NULL; - } -} - diff --git a/src/nv50_crtc.c b/src/nv50_crtc.c deleted file mode 100644 index aa85cee..0000000 --- a/src/nv50_crtc.c +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Copyright 2007 NVIDIA, Corporation - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -/* Check if the card wants us to update the any of the video clocks. - * Maybe it would be enough to check only after method 0x80? */ -static void -NV50CheckWriteVClk(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - int t_start = GetTimeInMillis(); - - while (NVRead(pNv, NV50_DISPLAY_CTRL_STATE) & NV50_DISPLAY_CTRL_STATE_PENDING) { - /* An educated guess. */ - const uint32_t supervisor = NVRead(pNv, NV50_DISPLAY_SUPERVISOR); - - if ((GetTimeInMillis() - t_start) > 5000) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "NV50CheckWriteVClk() timed out.\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "A reboot is probably required now.\n"); - break; - } - - /* Simply acknowledge it, maybe we should do more? */ - if (supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn) { - NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn); - } - - if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) { - if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_UPDATE) { - const uint32_t clockvar = NVRead(pNv, NV50_DISPLAY_UNK30_CTRL); - int i; - - for(i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - uint32_t mask = 0; - - if (crtc->index == 1) - mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK1; - else - mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK0; - - if (clockvar & mask) - crtc->SetPixelClock(crtc, crtc->pixel_clock); - /* Always do something if the supervisor wants a clock change. */ - /* This is needed because you get a deadlock if you don't kick the NV50_CRTC0_CLK_CTRL2 register. */ - if (crtc->modeset_lock) { - crtc->SetClockMode(crtc, crtc->pixel_clock); - - nouveauOutputPtr output; - for (output = pNv->output; output != NULL; output = output->next) { - if (output->crtc == crtc) - output->SetClockMode(output, crtc->pixel_clock); - } - } - } - } - - NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 1 << (ffs(supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) - 1)); - NVWrite(pNv, NV50_DISPLAY_UNK30_CTRL, NV50_DISPLAY_UNK30_CTRL_PENDING); - } - } -} - -void NV50DisplayCommand(ScrnInfoPtr pScrn, uint32_t addr, uint32_t value) -{ - DDXMMIOH("NV50DisplayCommand: head %d addr 0x%X value 0x%X\n", 0, addr, value); - NVPtr pNv = NVPTR(pScrn); - NVWrite(pNv, NV50_DISPLAY_CTRL_VAL, value); - NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, addr | 0x10000 | NV50_DISPLAY_CTRL_STATE_ENABLE | NV50_DISPLAY_CTRL_STATE_PENDING); - NV50CheckWriteVClk(pScrn); -} - -void NV50CrtcCommand(nouveauCrtcPtr crtc, uint32_t addr, uint32_t value) -{ - ScrnInfoPtr pScrn = crtc->scrn; - - /* This head dependent offset is only for crtc commands. */ - NV50DisplayCommand(pScrn, addr + 0x400 * crtc->index, value); -} - -static Bool -NV50CrtcModeValid(nouveauCrtcPtr crtc, DisplayModePtr mode) -{ - return TRUE; -} - -static void -NV50CrtcModeSet(nouveauCrtcPtr crtc, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcModeSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - /* Anyone know a more appropriate name? */ - DisplayModePtr desired_mode = crtc->use_native_mode ? crtc->native_mode : mode; - - /* Save the pixel clock for posterity. */ - crtc->pixel_clock = desired_mode->Clock; - crtc->cur_mode = mode; - - uint32_t hsync_dur = desired_mode->CrtcHSyncEnd - desired_mode->CrtcHSyncStart; - uint32_t vsync_dur = desired_mode->CrtcVSyncEnd - desired_mode->CrtcVSyncStart; - uint32_t hsync_start_to_end = desired_mode->CrtcHBlankEnd - desired_mode->CrtcHSyncStart; - uint32_t vsync_start_to_end = desired_mode->CrtcVBlankEnd - desired_mode->CrtcVSyncStart; - /* I can't give this a proper name, anyone else can? */ - uint32_t hunk1 = desired_mode->CrtcHTotal - desired_mode->CrtcHSyncStart + desired_mode->CrtcHBlankStart; - uint32_t vunk1 = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart; - /* Another strange value, this time only for interlaced modes. */ - uint32_t vunk2a = 2*desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart; - uint32_t vunk2b = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankEnd; - - if (desired_mode->Flags & V_INTERLACE) { - vsync_dur /= 2; - vsync_start_to_end /= 2; - vunk1 /= 2; - vunk2a /= 2; - vunk2b /= 2; - /* magic */ - if (desired_mode->Flags & V_DBLSCAN) { - vsync_start_to_end -= 1; - vunk1 -= 1; - vunk2a -= 1; - vunk2b -= 1; - } - } - - /* NV50CrtcCommand includes head offset */ - /* This is the native mode when DFP && !SCALE_PANEL */ - NV50CrtcCommand(crtc, NV50_CRTC0_CLOCK, desired_mode->Clock | 0x800000); - NV50CrtcCommand(crtc, NV50_CRTC0_INTERLACE, (desired_mode->Flags & V_INTERLACE) ? 2 : 0); - NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_START, 0); - NV50CrtcCommand(crtc, NV50_CRTC0_UNK82C, 0); - NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_TOTAL, desired_mode->CrtcVTotal << 16 | desired_mode->CrtcHTotal); - NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_DURATION, (vsync_dur - 1) << 16 | (hsync_dur - 1)); - NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_START_TO_BLANK_END, (vsync_start_to_end - 1) << 16 | (hsync_start_to_end - 1)); - NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK1, (vunk1 - 1) << 16 | (hunk1 - 1)); - if (desired_mode->Flags & V_INTERLACE) { - NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK2, (vunk2b - 1) << 16 | (vunk2a - 1)); - } - NV50CrtcCommand(crtc, NV50_CRTC0_FB_SIZE, pScrn->virtualY << 16 | pScrn->virtualX); - - /* Maybe move this calculation elsewhere? */ - crtc->fb_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); - NV50CrtcCommand(crtc, NV50_CRTC0_FB_PITCH, crtc->fb_pitch | 0x100000); - - switch (pScrn->depth) { - case 8: - NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_8BPP); - break; - case 15: - NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_15BPP); - break; - case 16: - NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_16BPP); - break; - case 24: - NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_24BPP); - break; - } - crtc->SetDither(crtc); - NV50CrtcCommand(crtc, NV50_CRTC0_COLOR_CTRL, NV50_CRTC_COLOR_CTRL_MODE_COLOR); - NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, (crtc->y << 16) | (crtc->x)); - /* This is the actual resolution of the mode. */ - NV50CrtcCommand(crtc, NV50_CRTC0_REAL_RES, (mode->VDisplay << 16) | mode->HDisplay); - NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CENTER_OFFSET, NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0)); - - /* Maybe move this as well? */ - crtc->Blank(crtc, FALSE); -} - -static void -NV50CrtcSetPixelClock(nouveauCrtcPtr crtc, int clock) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetPixelClock is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - NVPtr pNv = NVPTR(pScrn); - - /* I don't know why exactly, but these were in my table. */ - uint32_t pll_reg = crtc->index ? NV50_CRTC1_CLK_CTRL1 : NV50_CRTC0_CLK_CTRL1; - struct pll_lims pll_lim; - struct nouveau_pll_vals pllvals; - - get_pll_limits(pScrn, pll_reg, &pll_lim); - - /* NV5x hardware doesn't seem to support a single vco mode, otherwise the blob is hiding it well. */ - if (!nouveau_calc_pll_mnp(pScrn, &pll_lim, clock, &pllvals)) - return; - - uint32_t reg1 = NVRead(pNv, pll_reg + 4); - uint32_t reg2 = NVRead(pNv, pll_reg + 8); - - /* bit0: The blob (and bios) seem to have this on (almost) always. - * I'm hoping this (experiment) will fix my image stability issues. - */ - NVWrite(pNv, NV50_CRTC0_CLK_CTRL1 + crtc->index * 0x800, NV50_CRTC_CLK_CTRL1_CONNECTED | 0x10000011); - - /* Eventually we should learn ourselves what all the bits should be. */ - reg1 &= 0xff00ff00; - reg2 &= 0x8000ff00; - - reg1 |= (pllvals.M1 << 16) | pllvals.N1; - reg2 |= (pllvals.log2P << 28) | (pllvals.M2 << 16) | pllvals.N2; - - NVWrite(pNv, pll_reg + 4, reg1); - NVWrite(pNv, pll_reg + 8, reg2); -} - -static void -NV50CrtcSetClockMode(nouveauCrtcPtr crtc, int clock) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetClockMode is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - NVPtr pNv = NVPTR(pScrn); - - /* There seem to be a few indicator bits, which are similar to the SOR_CTRL bits. */ - NVWrite(pNv, NV50_CRTC0_CLK_CTRL2 + crtc->index * 0x800, 0); -} - -static void -NV50CrtcSetFB(nouveauCrtcPtr crtc, struct nouveau_bo * buffer) -{ - if (crtc->front_buffer) - nouveau_bo_unpin(crtc->front_buffer); - - /* For the moment the actual hardware settings stays in ModeSet(). */ - nouveau_bo_pin(buffer, NOUVEAU_BO_VRAM); - crtc->front_buffer = buffer; -} - -static void -NV50CrtcSetFBOffset(nouveauCrtcPtr crtc, uint32_t x, uint32_t y) -{ - crtc->x = x; - crtc->y = y; - - NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, (crtc->y << 16) | (crtc->x)); -} - -static void -NV50CrtcBlank(nouveauCrtcPtr crtc, Bool blanked) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcBlank is called (%s) for %s.\n", blanked ? "blanked" : "unblanked", crtc->index ? "CRTC1" : "CRTC0"); - - NVPtr pNv = NVPTR(pScrn); - - if (blanked) { - crtc->HideCursor(crtc, TRUE); - - NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, NV50_CRTC0_CLUT_MODE_BLANK); - NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, 0); - if (pNv->NVArch != 0x50) - NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_BLANK); - NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK); - if (pNv->NVArch != 0x50) - NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_BLANK); - } else { - struct nouveau_device *dev = crtc->front_buffer->device; - uint32_t fb = crtc->front_buffer->offset - dev->vm_vram_base; - uint32_t clut = crtc->lut->offset - dev->vm_vram_base; - uint32_t cursor; - - if (crtc->index) - cursor = pNv->Cursor2->offset - dev->vm_vram_base; - else - cursor = pNv->Cursor->offset - dev->vm_vram_base; - - NV50CrtcCommand(crtc, NV50_CRTC0_FB_OFFSET, fb >> 8); - NV50CrtcCommand(crtc, 0x864, 0); - NVWrite(pNv, NV50_DISPLAY_UNK_380, 0); - /* RAM is clamped to 256 MiB. */ - NVWrite(pNv, NV50_DISPLAY_RAM_AMOUNT, pNv->RamAmountKBytes * 1024 - 1); - NVWrite(pNv, NV50_DISPLAY_UNK_388, 0x150000); - NVWrite(pNv, NV50_DISPLAY_UNK_38C, 0); - NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, cursor >> 8); - if(pNv->NVArch != 0x50) - NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_UNBLANK); - - if (crtc->cursor_visible) - crtc->ShowCursor(crtc, TRUE); - - NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, - pScrn->depth == 8 ? NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON); - /* Each CRTC has it's own CLUT. */ - NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, clut >> 8); - if (pNv->NVArch != 0x50) - NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_UNBLANK); - NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_UNBLANK); - } - - crtc->blanked = blanked; -} - -static void -NV50CrtcSetDither(nouveauCrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetDither is called (%s).\n", !crtc->modeset_lock ? "update" : "no update"); - - NV50CrtcCommand(crtc, NV50_CRTC0_DITHERING_CTRL, crtc->dithering ? - NV50_CRTC0_DITHERING_CTRL_ON : NV50_CRTC0_DITHERING_CTRL_OFF); - - if (!crtc->modeset_lock) - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); -} - -static void -ComputeAspectScale(DisplayModePtr mode, DisplayModePtr adjusted_mode, int *outX, int *outY) -{ - float scaleX, scaleY, scale; - - scaleX = adjusted_mode->HDisplay / (float)mode->HDisplay; - scaleY = adjusted_mode->VDisplay / (float)mode->VDisplay; - - if (scaleX > scaleY) - scale = scaleY; - else - scale = scaleX; - - *outX = mode->HDisplay * scale; - *outY = mode->VDisplay * scale; -} - -static void -NV50CrtcSetScaleMode(nouveauCrtcPtr crtc, int scale) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetScale is called with mode %d for %s.\n", scale, crtc->index ? "CRTC1" : "CRTC0"); - - uint32_t scale_val = 0; - int outX = 0, outY = 0; - - switch(scale) { - case SCALE_ASPECT: - ComputeAspectScale(crtc->cur_mode, crtc->native_mode, &outX, &outY); - break; - case SCALE_FULLSCREEN: - outX = crtc->native_mode->HDisplay; - outY = crtc->native_mode->VDisplay; - break; - case SCALE_NOSCALE: - case SCALE_PANEL: - default: - outX = crtc->cur_mode->HDisplay; - outY = crtc->cur_mode->VDisplay; - break; - } - - /* Got a better name for SCALER_ACTIVE? */ - if ((crtc->cur_mode->Flags & V_DBLSCAN) || (crtc->cur_mode->Flags & V_INTERLACE) || - crtc->cur_mode->HDisplay != outX || crtc->cur_mode->VDisplay != outY) { - scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_ACTIVE; - } else { - scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_INACTIVE; - } - - NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CTRL, scale_val); - NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES1, outY << 16 | outX); - NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES2, outY << 16 | outX); -} - -/* - * Cursor stuff. - */ - -static void -NV50CrtcShowCursor(nouveauCrtcPtr crtc, Bool forced_lock) -{ - ScrnInfoPtr pScrn = crtc->scrn; - //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcShowCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - if (!crtc->modeset_lock) - crtc->cursor_visible = TRUE; - - NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_SHOW); - - /* Calling this during modeset will lock things up. */ - if (!crtc->modeset_lock && !forced_lock) - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); -} - -static void -NV50CrtcHideCursor(nouveauCrtcPtr crtc, Bool forced_lock) -{ - ScrnInfoPtr pScrn = crtc->scrn; - //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcHideCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - if (!crtc->modeset_lock) - crtc->cursor_visible = FALSE; - - NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_HIDE); - - /* Calling this during modeset will lock things up. */ - if (!crtc->modeset_lock && !forced_lock) - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); -} - -static void -NV50CrtcSetCursorPosition(nouveauCrtcPtr crtc, int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - NVWrite(pNv, NV50_CRTC0_CURSOR_POS + crtc->index * 0x1000, (y & 0xFFFF) << 16 | (x & 0xFFFF)); - - /* This is needed to allow the cursor to move. */ - NVWrite(pNv, NV50_CRTC0_CURSOR_POS_CTRL + crtc->index * 0x1000, 0); -} - -static void -NV50CrtcLoadCursor(nouveauCrtcPtr crtc, Bool argb, uint32_t *src) -{ - NVPtr pNv = NVPTR(crtc->scrn); - struct nouveau_bo *cursor = NULL; - - if (!argb) /* FIXME */ - return; - - nouveau_bo_ref(crtc->index ? pNv->Cursor2 : pNv->Cursor, &cursor); - nouveau_bo_map(cursor, NOUVEAU_BO_WR); - /* Assume cursor is 64x64 */ - memcpy(cursor->map, src, 64 * 64 * 4); - nouveau_bo_unmap(cursor); -} - -/* - * Gamma stuff. - */ - -/* - * The indices are a bit strange, but i'll assume it's correct (taken from nv). - * The LUT resolution seems to be 14 bits on NV50 as opposed to the 8 bits of previous hardware. - */ -static void -NV50CrtcGammaSet(nouveauCrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size) -{ - ScrnInfoPtr pScrn = crtc->scrn; - uint32_t i; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcGammaSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0"); - - for (i = 0; i < 256; i++) { - crtc->lut_values[i].red = red[i] >> 2; - crtc->lut_values[i].green = green[i] >> 2; - crtc->lut_values[i].blue = blue[i] >> 2; - } - - crtc->lut_values_valid = true; - - /* This is pre-init, we don't have access to the lut bo now. */ - if (!crtc->lut) - return; - - nouveau_bo_map(crtc->lut, NOUVEAU_BO_WR); - memcpy(crtc->lut->map, crtc->lut_values, 4*256*sizeof(uint16_t)); - nouveau_bo_unmap(crtc->lut); -} - -void -NV50CrtcInit(ScrnInfoPtr pScrn) -{ - int i; - NVPtr pNv = NVPTR(pScrn); - - for (i=0; i < 2; i++) { - nouveauCrtcPtr crtc = xnfcalloc(sizeof(nouveauCrtcRec), 1); - crtc->scrn = pScrn; - crtc->index = i; - - /* Function pointers. */ - crtc->ModeValid = NV50CrtcModeValid; - crtc->ModeSet = NV50CrtcModeSet; - crtc->SetPixelClock = NV50CrtcSetPixelClock; - crtc->SetClockMode = NV50CrtcSetClockMode; - - crtc->SetFB = NV50CrtcSetFB; - crtc->SetFBOffset = NV50CrtcSetFBOffset; - - crtc->Blank = NV50CrtcBlank; - crtc->SetDither = NV50CrtcSetDither; - - crtc->SetScaleMode = NV50CrtcSetScaleMode; - - crtc->ShowCursor = NV50CrtcShowCursor; - crtc->HideCursor = NV50CrtcHideCursor; - crtc->SetCursorPosition = NV50CrtcSetCursorPosition; - crtc->LoadCursor = NV50CrtcLoadCursor; - - crtc->GammaSet = NV50CrtcGammaSet; - - pNv->crtc[i] = crtc; - } -} - -void -NV50CrtcDestroy(ScrnInfoPtr pScrn) -{ - int i; - NVPtr pNv = NVPTR(pScrn); - - for (i=0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - - if (!crtc) - continue; - - xfree(crtc->name); - xfree(crtc); - pNv->crtc[i] = NULL; - } -} diff --git a/src/nv50_cursor.c b/src/nv50_cursor.c deleted file mode 100644 index 11c37cf..0000000 --- a/src/nv50_cursor.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2007 NVIDIA, Corporation - * Copyright (c) 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -#include - -#include "nv_include.h" - -Bool NV50CursorAcquire(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - int i; - - if (!pNv->HWCursor) return TRUE; - - /* Initialize the cursor on each head */ - for (i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - const int headOff = 0x10 * crtc->index; - - NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, 0x2000); - while (NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK); - - NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, NV50_CRTC_CURSOR_CTRL2_ON); - while ((NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK) != NV50_CRTC_CURSOR_CTRL2_STATUS_ACTIVE); - } - - return TRUE; -} - -void NV50CursorRelease(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - int i; - - if (!pNv->HWCursor) return; - - /* Release the cursor on each head */ - for (i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - const int headOff = 0x10 * crtc->index; - - NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, NV50_CRTC_CURSOR_CTRL2_OFF); - while (NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK); - } -} - -Bool NV50CursorInit(ScreenPtr pScreen) -{ - return xf86_cursors_init(pScreen, 64, 64, - HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | - HARDWARE_CURSOR_ARGB); -} - diff --git a/src/nv50_dac.c b/src/nv50_dac.c deleted file mode 100644 index 9ec5eef..0000000 --- a/src/nv50_dac.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2007 NVIDIA, Corporation - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -static int -NV50DacModeValid(nouveauOutputPtr output, DisplayModePtr mode) -{ - if (mode->Clock > 400000) - return MODE_CLOCK_HIGH; - - if (mode->Clock < 25000) - return MODE_CLOCK_LOW; - - return MODE_OK; -} - -static void -NV50DacModeSet(nouveauOutputPtr output, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacModeSet is called.\n"); - - const int dacOff = 0x80 * NV50OrOffset(output); - uint32_t mode_ctl = NV50_DAC_MODE_CTRL_OFF; - uint32_t mode_ctl2 = 0; - - if (!mode) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting DAC.\n"); - NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl); - return; - } - - /* Anyone know a more appropriate name? */ - DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode; - - if (output->crtc) { - if (output->crtc->index == 1) - mode_ctl |= NV50_DAC_MODE_CTRL_CRTC1; - else - mode_ctl |= NV50_DAC_MODE_CTRL_CRTC0; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n"); - return; - } - - if (output->type == OUTPUT_ANALOG) { - /* What is this? */ - mode_ctl |= 0x40; - } else if (output->type == OUTPUT_TV) { - mode_ctl |= 0x100; - } - - if (desired_mode->Flags & V_NHSYNC) - mode_ctl2 |= NV50_DAC_MODE_CTRL2_NHSYNC; - - if (desired_mode->Flags & V_NVSYNC) - mode_ctl2 |= NV50_DAC_MODE_CTRL2_NVSYNC; - - // This wouldn't be necessary, but the server is stupid and calls - // nv50_dac_dpms after the output is disconnected, even though the hardware - // turns it off automatically. - output->SetPowerMode(output, DPMSModeOn); - - NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl); - - NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL2 + dacOff, mode_ctl2); - - output->crtc->SetScaleMode(output->crtc, output->scale_mode); -} - -static void -NV50DacSetClockMode(nouveauOutputPtr output, int clock) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetClockMode is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - NVWrite(pNv, NV50_DAC0_CLK_CTRL2 + NV50OrOffset(output) * 0x800, 0); -} - -static int -NV50DacSense(nouveauOutputPtr output) -{ - switch (output->type) { - case OUTPUT_ANALOG: - case OUTPUT_TV: - return output->type; - default: - return OUTPUT_NONE; - } -} - -static Bool -NV50DacDetect (nouveauOutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - NVPtr pNv = NVPTR(pScrn); - const int scrnIndex = pScrn->scrnIndex; - int sigstate; - uint32_t load, dactestval, tmp; - - NVWrite(pNv, NV50_DAC0_CLK_CTRL1 + NV50OrOffset(output) * 0x800, 0x00000001); - tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800); - - NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING); - while (NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING); - - dactestval = 340; - if (pNv->vbios->dactestval) { - dactestval = pNv->vbios->dactestval; - xf86DrvMsg(scrnIndex, X_INFO, "Using bios provided load value of %d\n", dactestval); - } else { - xf86DrvMsg(scrnIndex, X_INFO, "Using default load value of %d\n", dactestval); - } - - NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, dactestval | NV50_DAC_LOAD_CTRL_ACTIVE); - /* Why is this needed, load detect is almost instantanious and seemingly reliable for me. */ - sigstate = xf86BlockSIGIO(); - usleep(45000); - xf86UnblockSIGIO(sigstate); - load = NVRead(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800); - NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, 0); - NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_PENDING | tmp); - - // Use this DAC if all three channels show load. - if ((load & NV50_DAC_LOAD_CTRL_PRESENT) == NV50_DAC_LOAD_CTRL_PRESENT) { - xf86DrvMsg(scrnIndex, X_PROBED, "Load present on DAC-%i\n", NV50OrOffset(output)); - return TRUE; - } - - xf86DrvMsg(scrnIndex, X_PROBED, "No Load present on DAC-%i\n", NV50OrOffset(output)); - return FALSE; -} - -static void -NV50DacSetPowerMode(nouveauOutputPtr output, int mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetPowerMode is called with mode %d.\n", mode); - - uint32_t tmp; - NVPtr pNv = NVPTR(pScrn); - - /* - * DPMSModeOn everything on - * DPMSModeStandby hsync disabled, vsync enabled - * DPMSModeSuspend hsync enabled, vsync disabled - * DPMSModeOff sync disabled - */ - while(NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING); - - tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800); - tmp &= ~0x7f; - tmp |= NV50_DAC_DPMS_CTRL_PENDING; - - if (mode == DPMSModeStandby || mode == DPMSModeOff) - tmp |= NV50_DAC_DPMS_CTRL_HSYNC_OFF; - if (mode == DPMSModeSuspend || mode == DPMSModeOff) - tmp |= NV50_DAC_DPMS_CTRL_VSYNC_OFF; - if (mode != DPMSModeOn) - tmp |= NV50_DAC_DPMS_CTRL_BLANKED; - if (mode == DPMSModeOff) - tmp |= NV50_DAC_DPMS_CTRL_OFF; - - NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp); -} - -static nouveauCrtcPtr -NV50DacGetCurrentCrtc(nouveauOutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacGetCurrentCrtc is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - uint32_t mode_ctrl = NVRead(pNv, NV50_DAC0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8); - - /* - * MODE_CTRL values only contain one instance of crtc0 and of crtc1. - * This is because we disconnect outputs upon modeset. - * Crtc might be off even if we get a positive return. - * But we are still associated with that crtc. - */ - if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC0) - return pNv->crtc[0]; - else if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC1) - return pNv->crtc[1]; - - return NULL; -} - -void -NV50DacSetFunctionPointers(nouveauOutputPtr output) -{ - output->ModeValid = NV50DacModeValid; - output->ModeSet = NV50DacModeSet; - output->SetClockMode = NV50DacSetClockMode; - output->Sense = NV50DacSense; - output->Detect = NV50DacDetect; - output->SetPowerMode = NV50DacSetPowerMode; - output->GetCurrentCrtc = NV50DacGetCurrentCrtc; -} diff --git a/src/nv50_display.c b/src/nv50_display.c deleted file mode 100644 index 9dcdbd1..0000000 --- a/src/nv50_display.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2007 NVIDIA, Corporation - * Copyright (c) 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include "nv_include.h" - -Bool -NV50DispPreInit(ScrnInfoPtr pScrn) -{ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispPreInit is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - /* - * I get the strange feeling that the 0x006101XX range is some kind of master modesetting control. - * Maybe this what triggers it to be enabled. - */ - NVWrite(pNv, 0x00610184, NVRead(pNv, 0x00614004)); - /* CRTC related? */ - NVWrite(pNv, 0x00610190 + 0 * 0x10, NVRead(pNv, 0x00616100 + 0 * 0x800)); - NVWrite(pNv, 0x00610190 + 1 * 0x10, NVRead(pNv, 0x00616100 + 1 * 0x800)); - NVWrite(pNv, 0x00610194 + 0 * 0x10, NVRead(pNv, 0x00616104 + 0 * 0x800)); - NVWrite(pNv, 0x00610194 + 1 * 0x10, NVRead(pNv, 0x00616104 + 1 * 0x800)); - NVWrite(pNv, 0x00610198 + 0 * 0x10, NVRead(pNv, 0x00616108 + 0 * 0x800)); - NVWrite(pNv, 0x00610198 + 1 * 0x10, NVRead(pNv, 0x00616108 + 1 * 0x800)); - NVWrite(pNv, 0x0061019c + 0 * 0x10, NVRead(pNv, 0x0061610c + 0 * 0x800)); - NVWrite(pNv, 0x0061019c + 1 * 0x10, NVRead(pNv, 0x0061610c + 1 * 0x800)); - NVWrite(pNv, 0x006101d0 + DAC0 * 0x4, NVRead(pNv, 0x0061a000 + DAC0 * 0x800)); - NVWrite(pNv, 0x006101d0 + DAC1 * 0x4, NVRead(pNv, 0x0061a000 + DAC1 * 0x800)); - NVWrite(pNv, 0x006101d0 + DAC2 * 0x4, NVRead(pNv, 0x0061a000 + DAC2 * 0x800)); - NVWrite(pNv, 0x006101e0 + SOR0 * 0x4, NVRead(pNv, 0x0061c000 + SOR0 * 0x800)); - NVWrite(pNv, 0x006101e0 + SOR1 * 0x4, NVRead(pNv, 0x0061c000 + SOR1 * 0x800)); - NVWrite(pNv, 0x006101e0 + SOR2 * 0x4, NVRead(pNv, 0x0061c000 + SOR2 * 0x800)); - /* Maybe TV-out related, or something more generic? */ - /* These are not in nv, so it must be something nv does not use. */ - NVWrite(pNv, 0x006101f0 + 0 * 0x4, NVRead(pNv, 0x0061e000 + 0 * 0x800)); - NVWrite(pNv, 0x006101f0 + 1 * 0x4, NVRead(pNv, 0x0061e000 + 1 * 0x800)); - NVWrite(pNv, 0x006101f0 + 2 * 0x4, NVRead(pNv, 0x0061e000 + 2 * 0x800)); - /* 0x00150000 seems to be the default state on many cards. why the extra bit is needed on some is unknown. */ - NVWrite(pNv, NV50_DAC0_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING); - NVWrite(pNv, NV50_DAC0_CLK_CTRL1, 0x00000001); - NVWrite(pNv, NV50_DAC1_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING); - NVWrite(pNv, NV50_DAC1_CLK_CTRL1, 0x00000001); - NVWrite(pNv, NV50_DAC2_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING); - NVWrite(pNv, NV50_DAC2_CLK_CTRL1, 0x00000001); - - return TRUE; -} - -Bool -NV50DispInit(ScrnInfoPtr pScrn) -{ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispInit is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - uint32_t val; - if (NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & 0x100) { - NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 0x100); - NVWrite(pNv, 0x006194e8, NVRead(pNv, 0x006194e8) & ~1); - while (NVRead(pNv, 0x006194e8) & 2); - } - - NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x2b00); - /* A bugfix (#12637) from the nv driver, to unlock the driver if it's left in a poor state */ - do { - val = NVRead(pNv, NV50_DISPLAY_UNK200_CTRL); - if ((val & 0x9f0000) == 0x20000) - NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x800000); - - if ((val & 0x3f0000) == 0x30000) - NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x200000); - } while ((val & 0x1e0000) != 0); - NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_ENABLE); - NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x1000b03); - while (!(NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x40000000)); - - NV50DisplayCommand(pScrn, NV50_UNK84, 0); - NV50DisplayCommand(pScrn, NV50_UNK88, 0); - /* The GetLVDSNativeMode() function is proof that more than crtc0 is used by the bios. */ - NV50DisplayCommand(pScrn, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK); - NV50DisplayCommand(pScrn, NV50_CRTC0_UNK800, 0); - NV50DisplayCommand(pScrn, NV50_CRTC0_DISPLAY_START, 0); - NV50DisplayCommand(pScrn, NV50_CRTC0_UNK82C, 0); - - return TRUE; -} - -void -NV50DispShutdown(ScrnInfoPtr pScrn) -{ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispShutdown is called.\n"); - NVPtr pNv = NVPTR(pScrn); - int i; - - for(i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - - crtc->Blank(crtc, TRUE); - } - - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); - - for(i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - - /* This is like acknowledging a vblank, maybe this is in the spirit of cleaning up? */ - /* The blob doesn't do it quite this way, it seems to do 0x30C as init and end. */ - /* It doesn't wait for a non-zero value either. */ - if (crtc->active) { - uint32_t mask = 0; - if (crtc->index == 1) - mask = NV50_DISPLAY_SUPERVISOR_CRTC1; - else - mask = NV50_DISPLAY_SUPERVISOR_CRTC0; - - NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, mask); - while(!(NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & mask)); - } - } - - NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x0); - NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_DISABLE); - while ((NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x1e0000) != 0); - while ((NVRead(pNv, NV50_SOR0_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT)); - while ((NVRead(pNv, NV50_SOR1_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT)); -} diff --git a/src/nv50_output.c b/src/nv50_output.c deleted file mode 100644 index c806748..0000000 --- a/src/nv50_output.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2007 NVIDIA, Corporation - * Copyright (c) 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -#include "nv_include.h" - -#include - -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -int -NV50OrOffset(nouveauOutputPtr output) -{ - return ffs(output->dcb->or) - 1; -} - -static void -NV50OutputInit(ScrnInfoPtr pScrn, struct dcb_entry *dcbent) -{ - NVPtr pNv = NVPTR(pScrn); - nouveauConnectorPtr connector = pNv->connector[dcbent->i2c_index]; - nouveauOutputPtr output = NULL; - char name[20]; - int i; - - switch (dcbent->type) { - case OUTPUT_LVDS: - case OUTPUT_TMDS: - sprintf(name, "SOR-%d", ffs(dcbent->or) - 1); - break; - case OUTPUT_ANALOG: - sprintf(name, "DAC-%d", ffs(dcbent->or) - 1); - break; - default: - return; - } - - output = xnfcalloc(sizeof(nouveauOutputRec), 1); - output->name = xstrdup(name); - output->dcb = dcbent; - output->type = dcbent->type; - output->scrn = pScrn; - - /* Put the output in the connector's list of outputs. */ - for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) { - if (connector->outputs[i]) - continue; - connector->outputs[i] = output; - - break; - } - - /* Put ourselves in the main output list. */ - if (!pNv->output) { - pNv->output = output; - } else { - nouveauOutputPtr output_link = pNv->output; - if (output_link->next) { - do { - output_link = output_link->next; - } while (output_link->next); - } - output_link->next = output; - } - - /* Output property for tmds and lvds. */ - output->dithering = (pNv->FPDither || output->type == OUTPUT_LVDS); - - if (output->type == OUTPUT_LVDS || output->type == OUTPUT_TMDS) { - if (pNv->FpScale) /* GPU Scaling */ - output->scale_mode = SCALE_ASPECT; - else if (output->type == OUTPUT_LVDS) - output->scale_mode = SCALE_NOSCALE; - else - output->scale_mode = SCALE_PANEL; - - if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) { - output->scale_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1); - if (output->scale_mode == SCALE_INVALID) - output->scale_mode = SCALE_ASPECT; /* default */ - } - } - - /* NV5x scaling hardware seems to work fine for analog too. */ - if (output->type == OUTPUT_ANALOG) { - output->scale_mode = SCALE_PANEL; - - if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) { - output->scale_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1); - if (output->scale_mode == SCALE_INVALID) - output->scale_mode = SCALE_PANEL; /* default */ - } - } - - /* Usually 3, which means both crtc's. */ - output->allowed_crtc = output->dcb->heads; - - if (output->type == OUTPUT_TMDS) { - NVWrite(pNv, NV50_SOR0_UNK00C + NV50OrOffset(output) * 0x800, 0x03010700); - NVWrite(pNv, NV50_SOR0_UNK010 + NV50OrOffset(output) * 0x800, 0x0000152f); - NVWrite(pNv, NV50_SOR0_UNK014 + NV50OrOffset(output) * 0x800, 0x00000000); - NVWrite(pNv, NV50_SOR0_UNK018 + NV50OrOffset(output) * 0x800, 0x00245af8); - } - -#if 0 - if (output->type == OUTPUT_LVDS) { - /* now fpindex should be known, so reread the table here. */ - /* not that we do a lot with the information. */ - parse_lvds_manufacturer_table(pScrn, 0); - } -#endif - - /* This needs to be handled in the same way as pre-NV5x on the long run. */ - //if (output->type == OUTPUT_LVDS) - // pNv->vbios->fp.native_mode = GetLVDSNativeMode(pScrn); - - /* Function pointers. */ - if (output->type == OUTPUT_TMDS || output->type == OUTPUT_LVDS) { - NV50SorSetFunctionPointers(output); - } else if (output->type == OUTPUT_ANALOG || output->type == OUTPUT_TV) { - NV50DacSetFunctionPointers(output); - } -} - -#define MULTIPLE_ENCODERS(e) ((e) & ((e) - 1)) -void -NV50OutputSetup(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - struct parsed_dcb *dcb = pNv->vbios->dcb; - int lvds = 0, dvi_i = 0, dvi_d = 0, vga = 0; - uint16_t connector[16] = {}; - char name[20]; - int i; - - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; - - switch (dcbent->type) { - case OUTPUT_ANALOG: - case OUTPUT_TMDS: - case OUTPUT_LVDS: - break; - default: - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "DCB encoder type %d not known\n", - dcbent->type); - continue; - } - - connector[dcbent->i2c_index] |= (1 << i); - NV50OutputInit(pScrn, dcbent); - } - - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; - nouveauConnectorPtr c = pNv->connector[dcbent->i2c_index]; - uint16_t encoders; - - encoders = connector[dcbent->i2c_index]; - connector[dcbent->i2c_index] = 0; - - if (!encoders) - continue; - - switch (dcbent->type) { - case OUTPUT_ANALOG: - if (!MULTIPLE_ENCODERS(encoders)) - sprintf(name, "VGA-%d", vga++); - else - sprintf(name, "DVI-I-%d", dvi_i++); - break; - case OUTPUT_TMDS: - if (!MULTIPLE_ENCODERS(encoders)) - sprintf(name, "DVI-D-%d", dvi_d++); - else - sprintf(name, "DVI-I-%d", dvi_i++); - break; - case OUTPUT_LVDS: - sprintf(name, "LVDS-%d", lvds++); - break; - default: - continue; - } - - if (dcbent->i2c_index != 0xf) { - NV_I2CInit(pScrn, &pNv->pI2CBus[dcbent->i2c_index], - &dcb->i2c[dcbent->i2c_index], - xstrdup(name)); - } - - xfree(c->name); - c->name = xstrdup(name); - c->i2c_index = dcbent->i2c_index; - c->pDDCBus = pNv->pI2CBus[dcbent->i2c_index]; - } -} - -void -NV50OutputDestroy(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - nouveauOutputPtr output, next; - - for (output = pNv->output; output != NULL; output = next) { - next = output->next; - xfree(output->name); - xfree(output); - } - - pNv->output = NULL; -} diff --git a/src/nv50_randr.c b/src/nv50_randr.c deleted file mode 100644 index b163fda..0000000 --- a/src/nv50_randr.c +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv50_randr.h" -#include "X11/Xatom.h" - -/* - * A randr-1.2 wrapper around the NV50 driver. - */ - -/* - * CRTC stuff. - */ - -static void -nv50_crtc_dpms(xf86CrtcPtr crtc, int mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_dpms is called with mode %d for %s.\n", mode, nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - switch (mode) { - case DPMSModeOn: - nv_crtc->crtc->active = TRUE; - break; - case DPMSModeSuspend: - case DPMSModeStandby: - case DPMSModeOff: - default: - nv_crtc->crtc->active = FALSE; - break; - } -} - -static Bool -nv50_crtc_lock(xf86CrtcPtr crtc) -{ - return FALSE; -} - -static Bool -nv50_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - return TRUE; -} - -static void -nv50_crtc_prepare(xf86CrtcPtr crtc) -{ - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - nouveauOutputPtr output; - int i; - - /* Rewire internal stucts to match randr-1.2... yet again.. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - NV50OutputPrivatePtr nv50_output = output->driver_private; - nouveauOutputPtr nv_output = nv50_output->output; - - if (output->crtc) { - NV50CrtcPrivatePtr nv50_crtc = - output->crtc->driver_private; - nv_output->crtc = nv50_crtc->crtc; - } else { - nv_output->crtc = NULL; - } - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "nv50_crtc_prepare is called for %s.\n", - nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - nv_crtc->crtc->active = TRUE; - nv_crtc->crtc->modeset_lock = TRUE; - - /* Detach any unused outputs. */ - for (output = pNv->output; output != NULL; output = output->next) { - if (!output->crtc) - output->ModeSet(output, NULL); - } -} - -static void -nv50_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode, int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - struct nouveau_bo *bo; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "nv50_crtc_mode_set is called for %s.\n", - nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - NVPtr pNv = NVPTR(pScrn); - - bo = pNv->scanout; - if (crtc->rotatedData) { - bo = nv_crtc->shadow; - x = 0; - y = 0; - } - - nv_crtc->crtc->SetFB(nv_crtc->crtc, bo); - nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, x, y); - nv_crtc->crtc->ModeSet(nv_crtc->crtc, mode); -} - -static void -nv50_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_gamma_set is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - nv_crtc->crtc->GammaSet(nv_crtc->crtc, (uint16_t *) red, (uint16_t *) green, (uint16_t *) blue, size); -} - -static void -nv50_crtc_commit(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_commit is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - NVPtr pNv = NVPTR(pScrn); - - /* Let's detect any outputs and connectors that have gone inactive. */ - uint8_t crtc_active_mask = 0; - int i, j; - nouveauOutputPtr output; - - for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) { - Bool connector_active = FALSE; - for (j = 0; j < MAX_OUTPUTS_PER_CONNECTOR; j++) { - output = pNv->connector[i]->outputs[j]; - if (output) { - if (output->crtc) { - crtc_active_mask |= 1 << output->crtc->index; - connector_active = TRUE; - } else { - output->active = FALSE; - } - } - } - - pNv->connector[i]->active = connector_active; - } - - /* Blank any crtc's that are inactive. */ - if (!(crtc_active_mask & (1 << 0))) - pNv->crtc[0]->Blank(pNv->crtc[0], TRUE); - - if (!(crtc_active_mask & (1 << 1))) - pNv->crtc[1]->Blank(pNv->crtc[1], TRUE); - - xf86_reload_cursors(pScrn->pScreen); - - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); - - nv_crtc->crtc->modeset_lock = FALSE; -} - -/* - * Cursor CRTC stuff. - */ - -static void -nv50_crtc_show_cursor(xf86CrtcPtr crtc) -{ - //ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_show_cursor is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - if (!nv_crtc->crtc->blanked) - nv_crtc->crtc->ShowCursor(nv_crtc->crtc, FALSE); -} - -static void -nv50_crtc_hide_cursor(xf86CrtcPtr crtc) -{ - //ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_hide_cursor is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - nv_crtc->crtc->HideCursor(nv_crtc->crtc, FALSE); -} - -static void -nv50_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) -{ - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - - nv_crtc->crtc->SetCursorPosition(nv_crtc->crtc, x, y); -} - -static void -nv50_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *src) -{ - //ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_load_cursor_argb is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0"); - - nv_crtc->crtc->LoadCursor(nv_crtc->crtc, TRUE, (uint32_t *) src); -} - -static void * -nv50_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - NVPtr pNv = NVPTR(pScrn); - int size, pitch; - - ErrorF("nv50_crtc_shadow_allocate\n"); - - pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8); - size = pitch * height; - - if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | - NOUVEAU_BO_MAP, 64, size, &nv_crtc->shadow)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for shadow buffer!\n"); - return NULL; - } - - if (nv_crtc->shadow && nouveau_bo_map(nv_crtc->shadow, NOUVEAU_BO_RDWR)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to map shadow buffer.\n"); - return NULL; - } - - pNv->shadow[nv_crtc->crtc->index] = nv_crtc->shadow; - - return nv_crtc->shadow->map; -} - -static PixmapPtr -nv50_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) -{ - ScrnInfoPtr pScrn = crtc->scrn; - uint32_t pitch; - PixmapPtr rotate_pixmap; - - ErrorF("nv50_crtc_shadow_create\n"); - - if (!data) - data = crtc->funcs->shadow_allocate (crtc, width, height); - - pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8); - - rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, - width, height, - pScrn->depth, - pScrn->bitsPerPixel, - pitch, - data); - - if (rotate_pixmap == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - } - - return rotate_pixmap; -} - -static void -nv50_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - NVPtr pNv = NVPTR(pScrn); - ScreenPtr pScreen = pScrn->pScreen; - - ErrorF("nv50_crtc_shadow_destroy\n"); - - if (rotate_pixmap) - pScreen->DestroyPixmap(rotate_pixmap); - - if (nv_crtc->shadow) - nouveau_bo_ref(NULL, &nv_crtc->shadow); - - nv_crtc->shadow = NULL; - /* for easy acces by exa */ - pNv->shadow[nv_crtc->crtc->index] = NULL; -} - -#if XF86_CRTC_VERSION >= 2 -static void -nv50_crtc_set_origin(xf86CrtcPtr crtc, int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NV50CrtcPrivatePtr nv_crtc = crtc->driver_private; - nouveauCrtcPtr nvcrtc = nv_crtc->crtc; /* sigh.. */ - NVPtr pNv = NVPTR(pScrn); - uint32_t fb; - - nvcrtc->SetFB(nvcrtc, pNv->scanout); - nvcrtc->SetFBOffset(nvcrtc, x, y); - nvcrtc->fb_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); - fb = nvcrtc->front_buffer->offset - pNv->dev->vm_vram_base; - - NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_OFFSET, fb >> 8); - NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_PITCH, nvcrtc->fb_pitch | (1<<20)); - NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_SIZE, (pScrn->virtualY << 16) | - pScrn->virtualX); - - NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0); -} -#endif - -static void -nv50_crtc_destroy(xf86CrtcPtr crtc) -{ - xfree(crtc->driver_private); -} - -static const xf86CrtcFuncsRec nv50_crtc_funcs = { - .dpms = nv50_crtc_dpms, - .save = NULL, - .restore = NULL, - .lock = nv50_crtc_lock, - .unlock = NULL, - .mode_fixup = nv50_crtc_mode_fixup, - .prepare = nv50_crtc_prepare, - .mode_set = nv50_crtc_mode_set, - .gamma_set = nv50_crtc_gamma_set, - .commit = nv50_crtc_commit, - .shadow_create = nv50_crtc_shadow_create, - .shadow_allocate = nv50_crtc_shadow_allocate, - .shadow_destroy = nv50_crtc_shadow_destroy, - .set_cursor_position = nv50_crtc_set_cursor_position, - .show_cursor = nv50_crtc_show_cursor, - .hide_cursor = nv50_crtc_hide_cursor, - .load_cursor_argb = nv50_crtc_load_cursor_argb, - .destroy = nv50_crtc_destroy, -#if XF86_CRTC_VERSION >= 2 - .set_origin = nv50_crtc_set_origin, -#endif -}; - -void -nv50_crtc_init(ScrnInfoPtr pScrn, int crtc_num) -{ - NVPtr pNv = NVPTR(pScrn); - xf86CrtcPtr crtc; - NV50CrtcPrivatePtr nv_crtc; - - crtc = xf86CrtcCreate(pScrn, &nv50_crtc_funcs); - if (crtc == NULL) - return; - - nv_crtc = xnfcalloc (sizeof (NV50CrtcPrivateRec), 1); - nv_crtc->crtc = pNv->crtc[crtc_num]; - - crtc->driver_private = nv_crtc; -} - - -/* - * "Output" stuff. - */ - -static void -nv50_output_dpms(xf86OutputPtr output, int mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_dpms is called with mode %d.\n", mode); - - NVPtr pNv = NVPTR(pScrn); - NV50OutputPrivatePtr nv_output = output->driver_private; - - /* Keep the crtc wiring consistent with randr-1.2 */ - if (output->crtc) { - NV50CrtcPrivatePtr nv_crtc = output->crtc->driver_private; - nv_output->output->crtc = nv_crtc->crtc; - } else { - nv_output->output->crtc = NULL; - } - - /* Our crtc's map 1:1 onto randr-1.2 crtc's. */ - switch (mode) { - case DPMSModeOn: - nv_output->output->active = TRUE; - break; - case DPMSModeSuspend: - case DPMSModeStandby: - case DPMSModeOff: - default: - nv_output->output->active = FALSE; - break; - } - - /* Set dpms on all outputs for ths connector, just to be safe. */ - nouveauConnectorPtr connector = - pNv->connector[nv_output->output->dcb->i2c_index]; - int i; - for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) { - if (connector->outputs[i]) - connector->outputs[i]->SetPowerMode(connector->outputs[i], mode); - } -} - -static int -nv50_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_mode_valid is called.\n"); - - NV50OutputPrivatePtr nv_output = output->driver_private; - - return nv_output->output->ModeValid(nv_output->output, mode); -} - -static Bool -nv50_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) -{ - return TRUE; -} - -static void -nv50_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_mode_set is called.\n"); - - NV50OutputPrivatePtr nv_output = output->driver_private; - - nv_output->output->ModeSet(nv_output->output, mode); -} - -static xf86OutputStatus -nv50_output_detect(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_detect is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - NV50OutputPrivatePtr nv_output = output->driver_private; - nouveauConnectorPtr connector = - pNv->connector[nv_output->output->dcb->i2c_index]; - - if (!connector) - return XF86OutputStatusDisconnected; - - Bool detect_present = FALSE; - Bool detect_digital = FALSE; - xf86MonPtr ddc_mon = connector->DDCDetect(connector); - int i; - - if (!ddc_mon) { - for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) { - if (connector->outputs[i] && connector->outputs[i]->Detect) { - detect_present = connector->outputs[i]->Detect(connector->outputs[i]); - if (detect_present) { - if (connector->outputs[i]->type == OUTPUT_TMDS || connector->outputs[i]->type == OUTPUT_LVDS) - detect_digital = TRUE; - break; - } - } - } - } - - /* HACK: assume that a connector only holds output in the case of a tv-out */ - if (nv_output->output->type == OUTPUT_TV) - return XF86OutputStatusUnknown; - - /* - * We abuse randr-1.2 outputs as connector, so here we have to determine what actual output is connected to the connector. - */ - if (ddc_mon || detect_present) { - Bool is_digital = FALSE; - Bool found = FALSE; - nouveauCrtcPtr crtc_backup = nv_output->output->crtc; - nv_output->output->crtc = NULL; - nv_output->output->connector = NULL; - - if (ddc_mon) - is_digital = ddc_mon->features.input_type; - else - is_digital = detect_digital; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected a %s output on %s\n", is_digital ? "Digital" : "Analog", connector->name); - - for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) { - if (!is_digital && (connector->outputs[i]->type == OUTPUT_ANALOG || connector->outputs[i]->type == OUTPUT_TV)) { - found = TRUE; - } else if (is_digital && (connector->outputs[i]->type == OUTPUT_TMDS || connector->outputs[i]->type == OUTPUT_LVDS)) { - found = TRUE; - } - if (found) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found a suitable output, index %d\n", i); - connector->connected_output = i; - connector->outputs[i]->connector = connector; - connector->outputs[i]->crtc = crtc_backup; - nv_output->output = connector->outputs[i]; - break; - } - } - } - - if (ddc_mon || detect_present) { - free(ddc_mon); - return XF86OutputStatusConnected; - } else { - return XF86OutputStatusDisconnected; - } -} - -static DisplayModePtr -nv50_output_get_modes(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_detect is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - NV50OutputPrivatePtr nv_output = output->driver_private; - nouveauConnectorPtr connector = - pNv->connector[nv_output->output->dcb->i2c_index]; - - xf86MonPtr ddc_mon = connector->DDCDetect(connector); - - xf86OutputSetEDID(output, ddc_mon); - - DisplayModePtr ddc_modes = connector->GetDDCModes(connector); - DisplayModePtr default_modes = NULL; - - xf86DeleteMode(&nv_output->output->native_mode, nv_output->output->native_mode); - nv_output->output->native_mode = NULL; - if (nv_output->output->crtc) - nv_output->output->crtc->native_mode = NULL; - - /* typically only LVDS will hit this code path. */ - if (!ddc_modes) { - DisplayModeRec mode = {}; - - if (nv_output->output->type == OUTPUT_LVDS && - nouveau_bios_fp_mode(pScrn, &mode)) { - mode.status = MODE_OK; - mode.type = M_T_DRIVER | M_T_PREFERRED; - xf86SetModeDefaultName(&mode); - - ddc_modes = xf86DuplicateMode(&mode); - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "LVDS: Using a bios mode, which should work, if it doesn't please report.\n"); - } - } - - if (!ddc_modes && nv_output->output->type == OUTPUT_LVDS) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "LVDS and no modes found, bailing out.\n"); - return NULL; - } - - /* NV5x hardware can also do scaling on analog connections. */ - if (ddc_modes) { - /* Use the first preferred mode as native mode. */ - DisplayModePtr mode; - - /* Find the preferred mode. */ - for (mode = ddc_modes; mode != NULL; mode = mode->next) { - if (mode->type & M_T_PREFERRED) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%s: preferred mode is %s\n", - output->name, mode->name); - break; - } - } - - /* TODO: Scaling needs a native mode, maybe fail in a better way. */ - if (!mode) { - mode = ddc_modes; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%s: no preferred mode found, using %s\n", - output->name, mode->name); - } - - nv_output->output->native_mode = xf86DuplicateMode(mode); - } - - /* No ddc means no native mode, so make one up to avoid crashes. */ - if (!nv_output->output->native_mode) - nv_output->output->native_mode = xf86CVTMode(1024, 768, 60.0, FALSE, FALSE); - - xf86SetModeCrtc(nv_output->output->native_mode, 0); - - if (nv_output->output->crtc) - nv_output->output->crtc->native_mode = nv_output->output->native_mode; - - if (nv_output->output->type == OUTPUT_LVDS && - (!ddc_mon ||!GTF_SUPPORTED(ddc_mon->features.msc))) { -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,6,99,1,0) - default_modes = xf86GetDefaultModes(output->interlaceAllowed, - output->doubleScanAllowed); -#else - default_modes = xf86GetDefaultModes(); -#endif - } - - xf86ModesAdd(ddc_modes, default_modes); - return ddc_modes; -} - -static void -nv50_output_destroy(xf86OutputPtr output) -{ - NV50OutputPrivatePtr nv_output = output->driver_private; - - xf86DeleteMode(&nv_output->output->native_mode, nv_output->output->native_mode); - - xfree(output->driver_private); - output->driver_private = NULL; -} - -void -nv50_output_prepare(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_prepare is called.\n"); - - NV50OutputPrivatePtr nv_output = output->driver_private; - NV50CrtcPrivatePtr nv_crtc = output->crtc->driver_private; - - /* Set the real crtc now. */ - nv_output->output->crtc = nv_crtc->crtc; - - /* Transfer some output properties to the crtc for easy access. */ - nv_output->output->crtc->scale_mode = nv_output->output->scale_mode; - nv_output->output->crtc->dithering = nv_output->output->dithering; - nv_output->output->crtc->native_mode = nv_output->output->native_mode; - - if (nv_output->output->scale_mode != SCALE_PANEL) - nv_output->output->crtc->use_native_mode = TRUE; - else - nv_output->output->crtc->use_native_mode = FALSE; -} - -static void -nv50_output_commit(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_commit is called.\n"); -} - -#ifdef RANDR_GET_CRTC_INTERFACE -static xf86CrtcPtr -nv50_output_get_crtc(xf86OutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_get_crtc is called.\n"); - - NV50OutputPrivatePtr nv_output = output->driver_private; - nouveauCrtcPtr crtc = nv_output->output->GetCurrentCrtc(nv_output->output); - - /* - * Match the internal crtc to the public crtc. - * Note that GetCurrentCrtc() retrieves hardware state. - * Otherwise we could have just used output->crtc. - */ - if (crtc) { - int i; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - for (i = 0; i < xf86_config->num_crtc; i++) { - NV50CrtcPrivatePtr nv_crtc = xf86_config->crtc[i]->driver_private; - if (nv_crtc->crtc == crtc) - return xf86_config->crtc[i]; - } - } - - return NULL; -} -#endif /* RANDR_GET_CRTC_INTERFACE */ - -/* - * Output properties. - */ - -/* - * Several scaling modes exist, let the user choose. - */ -#define SCALING_MODE_NAME "SCALING_MODE" -static const struct { - char *name; - enum scaling_modes mode; -} scaling_mode[] = { - { "panel", SCALE_PANEL }, - { "fullscreen", SCALE_FULLSCREEN }, - { "aspect", SCALE_ASPECT }, - { "noscale", SCALE_NOSCALE }, - { NULL, SCALE_INVALID} -}; -static Atom scaling_mode_atom; - -#define DITHERING_MODE_NAME "DITHERING" -static Atom dithering_atom; - -int -nv_scaling_mode_lookup(char *name, int size) -{ - int i; - - /* for when name is zero terminated */ - if (size < 0) - size = strlen(name); - - for (i = 0; scaling_mode[i].name; i++) - /* We're getting non-terminated strings */ - if (strlen(scaling_mode[i].name) >= size && - !strncasecmp(name, scaling_mode[i].name, size)) - break; - - return scaling_mode[i].mode; -} - -void -nv50_output_create_resources(xf86OutputPtr output) -{ - NV50OutputPrivatePtr nv_output = output->driver_private; - ScrnInfoPtr pScrn = output->scrn; - INT32 dithering_range[2] = { 0, 1 }; - int error, i; - - /* - * Setup scaling mode property. - */ - scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE); - - error = RRConfigureOutputProperty(output->randr_output, - scaling_mode_atom, TRUE, FALSE, FALSE, - 0, NULL); - - if (error != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", error); - } - - char *existing_scale_name = NULL; - for (i = 0; scaling_mode[i].name; i++) - if (scaling_mode[i].mode == nv_output->output->scale_mode) - existing_scale_name = scaling_mode[i].name; - - error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom, - XA_STRING, 8, PropModeReplace, - strlen(existing_scale_name), - existing_scale_name, FALSE, TRUE); - - if (error != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to set scaling mode, %d\n", error); - } - - if (nv_output->output->type == OUTPUT_TMDS || nv_output->output->type == OUTPUT_LVDS) { - /* - * Setup dithering property. - */ - dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE); - - error = RRConfigureOutputProperty(output->randr_output, - dithering_atom, TRUE, TRUE, FALSE, - 2, dithering_range); - - if (error != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "RRConfigureOutputProperty error, %d\n", error); - } - - error = RRChangeOutputProperty(output->randr_output, dithering_atom, - XA_INTEGER, 32, PropModeReplace, 1, &nv_output->output->dithering, - FALSE, TRUE); - - if (error != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to set dithering mode, %d\n", error); - } - } -} - -Bool -nv50_output_set_property(xf86OutputPtr output, Atom property, - RRPropertyValuePtr value) -{ - NV50OutputPrivatePtr nv_output = output->driver_private; - - if (property == scaling_mode_atom) { - int32_t ret; - char *name = NULL; - - if (value->type != XA_STRING || value->format != 8) - return FALSE; - - name = (char *) value->data; - - /* Match a string to a scaling mode */ - ret = nv_scaling_mode_lookup(name, value->size); - if (ret == SCALE_INVALID) - return FALSE; - - /* LVDS must always use gpu scaling. */ - if (ret == SCALE_PANEL && nv_output->output->type == OUTPUT_LVDS) - return FALSE; - - nv_output->output->scale_mode = ret; - if (nv_output->output->crtc) /* normally prepare sets all these things for the crtc. */ - nv_output->output->crtc->scale_mode = ret; - return TRUE; - } else if (property == dithering_atom) { - if (value->type != XA_INTEGER || value->format != 32) - return FALSE; - - int32_t val = *(int32_t *) value->data; - - if (val < 0 || val > 1) - return FALSE; - - nv_output->output->dithering = val; - if (nv_output->output->crtc) /* normally prepare sets all these things for the crtc. */ - nv_output->output->crtc->dithering = val; - return TRUE; - } - - return TRUE; -} - -static const xf86OutputFuncsRec nv50_output_funcs = { - .dpms = nv50_output_dpms, - .save = NULL, - .restore = NULL, - .mode_valid = nv50_output_mode_valid, - .mode_fixup = nv50_output_mode_fixup, - .mode_set = nv50_output_mode_set, - .detect = nv50_output_detect, - .get_modes = nv50_output_get_modes, - .destroy = nv50_output_destroy, - .prepare = nv50_output_prepare, - .commit = nv50_output_commit, -#ifdef RANDR_GET_CRTC_INTERFACE - .get_crtc = nv50_output_get_crtc, -#endif /*RANDR_GET_CRTC_INTERFACE */ - .create_resources = nv50_output_create_resources, - .set_property = nv50_output_set_property, -}; - -void -nv50_output_create(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - xf86OutputPtr output; - NV50OutputPrivatePtr nv_output; - int i; - - /* this is a 1:1 hookup of the connectors. */ - for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) { - if (!(pNv->connector[i]->outputs[0])) - continue; /* An empty connector is not useful. */ - - if (!(output = xf86OutputCreate(pScrn, &nv50_output_funcs, pNv->connector[i]->name))) - return; - - if (!(nv_output = xnfcalloc(sizeof(NV50OutputPrivateRec), 1))) - return; - - output->driver_private = nv_output; - - nv_output->output = pNv->connector[i]->outputs[0]; /* initially just wire up the first output available. */ - - output->possible_crtcs = nv_output->output->allowed_crtc; - output->possible_clones = 0; - - if (nv_output->output->type == OUTPUT_TMDS || nv_output->output->type == OUTPUT_LVDS) { - output->doubleScanAllowed = false; - output->interlaceAllowed = false; - } else { - output->doubleScanAllowed = true; - output->interlaceAllowed = true; - } - } -} diff --git a/src/nv50_randr.h b/src/nv50_randr.h deleted file mode 100644 index d71087a..0000000 --- a/src/nv50_randr.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __NV50_RANDR_H_ -#define __NV50_RANDR_H_ - -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -typedef struct NV50CrtcPrivate { - int head; - nouveauCrtcPtr crtc; - struct nouveau_bo *shadow; -} NV50CrtcPrivateRec, *NV50CrtcPrivatePtr; - -typedef struct NV50OutputPrivate { - nouveauOutputPtr output; -} NV50OutputPrivateRec, *NV50OutputPrivatePtr; - -#endif /* __NV50_RANDR_H_ */ diff --git a/src/nv50_sor.c b/src/nv50_sor.c deleted file mode 100644 index ea18e77..0000000 --- a/src/nv50_sor.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2007 NVIDIA, Corporation - * Copyright 2008 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nouveau_modeset.h" -#include "nouveau_crtc.h" -#include "nouveau_output.h" -#include "nouveau_connector.h" - -static int -NV50SorModeValid(nouveauOutputPtr output, DisplayModePtr mode) -{ - int high_limit; - - if (output->type == OUTPUT_LVDS) - high_limit = 400000; - else - high_limit = 165000; /* no dual link dvi until we figure it out completely */ - - if (mode->Clock > high_limit) - return MODE_CLOCK_HIGH; - - if (mode->Clock < 25000) - return MODE_CLOCK_LOW; - - if (mode->Flags & V_DBLSCAN) - return MODE_NO_DBLESCAN; - - if (mode->HDisplay > output->native_mode->HDisplay || mode->VDisplay > output->native_mode->VDisplay) - return MODE_PANEL; - - return MODE_OK; -} - -static void -NV50SorModeSet(nouveauOutputPtr output, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorModeSet is called.\n"); - - const int sorOff = 0x40 * NV50OrOffset(output); - uint32_t mode_ctl = NV50_SOR_MODE_CTRL_OFF; - - if (!mode) { - /* Disconnect the SOR */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting SOR.\n"); - NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl); - return; - } - - /* Anyone know a more appropriate name? */ - DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode; - - if (output->type == OUTPUT_LVDS) { - mode_ctl |= NV50_SOR_MODE_CTRL_LVDS; - } else { - mode_ctl |= NV50_SOR_MODE_CTRL_TMDS; - if (desired_mode->Clock > 165000) - mode_ctl |= NV50_SOR_MODE_CTRL_TMDS_DUAL_LINK; - } - - if (output->crtc) { - if (output->crtc->index == 1) - mode_ctl |= NV50_SOR_MODE_CTRL_CRTC1; - else - mode_ctl |= NV50_SOR_MODE_CTRL_CRTC0; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n"); - return; - } - - if (desired_mode->Flags & V_NHSYNC) - mode_ctl |= NV50_SOR_MODE_CTRL_NHSYNC; - - if (desired_mode->Flags & V_NVSYNC) - mode_ctl |= NV50_SOR_MODE_CTRL_NVSYNC; - - // This wouldn't be necessary, but the server is stupid and calls - // nv50_sor_dpms after the output is disconnected, even though the hardware - // turns it off automatically. - output->SetPowerMode(output, DPMSModeOn); - - NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl); - - output->crtc->SetScaleMode(output->crtc, output->scale_mode); -} - -static void -NV50SorSetClockMode(nouveauOutputPtr output, int clock) -{ - ScrnInfoPtr pScrn = output->scrn; - NVPtr pNv = NVPTR(pScrn); - const int limit = output->dcb->type == OUTPUT_LVDS ? 112000 : 165000; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "NV50SorSetClockMode is called.\n"); - -#if 0 - ret = nouveau_bios_run_display_table(pScrn, output->dcb, clock); - if (ret) - NV_WARN(pScrn, "failed to run output script, may hang!\n"); -#else - /* just to keep the original behaviour until we can reliably run - * the output scripts... - */ - if (output->dcb->type == OUTPUT_LVDS) - return; -#endif - - /* 0x70000 was a late addition to nv, mentioned as fixing tmds - * initialisation on certain gpu's. */ - /* I presume it's some kind of clock setting, but what precisely i - * do not know. - */ - NVWrite(pNv, NV50_SOR0_CLK_CTRL2 + NV50OrOffset(output) * 0x800, - 0x70000 | ((clock > limit) ? 0x101 : 0)); -} - -static int -NV50SorSense(nouveauOutputPtr output) -{ - switch (output->type) { - case OUTPUT_TMDS: - case OUTPUT_LVDS: - return output->type; - default: - return OUTPUT_NONE; - } -} - -static void -NV50SorSetPowerMode(nouveauOutputPtr output, int mode) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorSetPowerMode is called with mode %d.\n", mode); - - NVPtr pNv = NVPTR(pScrn); - uint32_t tmp; - - while ((NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_CTRL_PENDING)); - - tmp = NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800); - tmp |= NV50_SOR_DPMS_CTRL_PENDING; - - if (mode == DPMSModeOn) - tmp |= NV50_SOR_DPMS_CTRL_MODE_ON; - else - tmp &= ~NV50_SOR_DPMS_CTRL_MODE_ON; - - NVWrite(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp); - while ((NVRead(pNv, NV50_SOR0_DPMS_STATE + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_STATE_WAIT)); -} - -static Bool -NV50SorDetect(nouveauOutputPtr output) -{ - if (output->type == OUTPUT_LVDS) /* assume connected */ - return TRUE; - - return FALSE; -} - -static nouveauCrtcPtr -NV50SorGetCurrentCrtc(nouveauOutputPtr output) -{ - ScrnInfoPtr pScrn = output->scrn; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorGetCurrentCrtc is called.\n"); - - NVPtr pNv = NVPTR(pScrn); - uint32_t mode_ctrl = NVRead(pNv, NV50_SOR0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8); - - /* - * MODE_CTRL values only contain one instance of crtc0 and of crtc1. - * This is because we disconnect outputs upon modeset. - * Crtc might be off even if we get a positive return. - * But we are still associated with that crtc. - */ - if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC0) - return pNv->crtc[0]; - else if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC1) - return pNv->crtc[1]; - - return NULL; -} - -void -NV50SorSetFunctionPointers(nouveauOutputPtr output) -{ - output->ModeValid = NV50SorModeValid; - output->ModeSet = NV50SorModeSet; - output->SetClockMode = NV50SorSetClockMode; - output->Sense = NV50SorSense; - output->Detect = NV50SorDetect; - output->SetPowerMode = NV50SorSetPowerMode; - output->GetCurrentCrtc = NV50SorGetCurrentCrtc; -} - diff --git a/src/nv50reg.h b/src/nv50reg.h deleted file mode 100644 index 4e21220..0000000 --- a/src/nv50reg.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright 2007 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef __NV50REG_H_ -#define __NV50REG_H_ - -/* Bit 28 also does something, although i don't know what. */ -#define NV50_CONNECTOR_HOTPLUG_INTR 0x0000E050 - #define NV50_CONNECTOR_HOTPLUG_INTR_PLUG_I2C0 (1 << 0) - #define NV50_CONNECTOR_HOTPLUG_INTR_PLUG_I2C1 (2 << 0) - #define NV50_CONNECTOR_HOTPLUG_INTR_UNPLUG_I2C0 (1 << 16) - #define NV50_CONNECTOR_HOTPLUG_INTR_UNPLUG_I2C1 (2 << 16) - -/* Writing 0x7FFF7FFF seems to be the way to acknowledge an interrupt. */ -/* There is also bit 7 and bit 23, but i also don't know what they do. */ -#define NV50_CONNECTOR_HOTPLUG_CTRL 0x0000E054 - #define NV50_CONNECTOR_HOTPLUG_CTRL_PLUG_I2C0 (1 << 0) - #define NV50_CONNECTOR_HOTPLUG_CTRL_PLUG_I2C1 (2 << 0) - #define NV50_CONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C0 (1 << 16) - #define NV50_CONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C1 (2 << 16) - -/* This works for DVI->VGA adapters as well, providing the adapter supports it. */ -/* It's unknown if bits exist for i2c port > 1. */ -/* Renamed to avoid confusion with other instances of CONNECTED. */ -#define NV50_CONNECTOR_HOTPLUG_STATE 0x0000E104 - #define NV50_CONNECTOR_HOTPLUG_STATE_I2C0_DETECT_PIN (1 << 2) - #define NV50_CONNECTOR_HOTPLUG_STATE_I2C1_DETECT_PIN (1 << 6) - -#define NV50_PCONNECTOR_I2C_PORT_0 0x0000e138 -#define NV50_PCONNECTOR_I2C_PORT_1 0x0000e150 -#define NV50_PCONNECTOR_I2C_PORT_2 0x0000e168 -#define NV50_PCONNECTOR_I2C_PORT_3 0x0000e180 -#define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 -#define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 - -/* 0x00610024 is the state register to read, all it's bits also exist in 0x0061002C in the form of interrupt switches. */ -#define NV50_DISPLAY_SUPERVISOR 0x00610024 - #define NV50_DISPLAY_SUPERVISOR_CRTC0 (1 << 2) - #define NV50_DISPLAY_SUPERVISOR_CRTC1 (2 << 2) - #define NV50_DISPLAY_SUPERVISOR_CRTCn (3 << 2) - #define NV50_DISPLAY_SUPERVISOR_CLK_MASK (7 << 4) - #define NV50_DISPLAY_SUPERVISOR_CLK_UPDATE (2 << 4) - -/* Two vblank interrupts arrive per blanking period, it could be rise and fall, i do not know. */ -/* If a vblank interrupt arrives, check NV50_DISPLAY_SUPERVISOR, it will show for which crtc (or both) it is. */ -/* Note that one crtc bit will always show, maybe it's updated when a vblank occurs? */ -/* Once modesetting goes into the kernel, we can ditch NV50CheckWriteVClk() and do it with interrupts. */ -/* Up until then, realise that most interrupts are not handled properly yet (and will stall your machine). */ -/* Bit 8 and 9 also exist for sure, but their purpose is unknown. */ -#define NV50_DISPLAY_SUPERVISOR_INTR 0x0061002C - #define NV50_DISPLAY_INTR_VBLANK_CRTC0 (1 << 2) - #define NV50_DISPLAY_INTR_VBLANK_CRTC1 (1 << 3) - #define NV50_DISPLAY_INTR_UNK1 (1 << 4) - #define NV50_DISPLAY_INTR_CLK_UPDATE (2 << 4) - #define NV50_DISPLAY_INTR_UNK4 (4 << 4) - -#define NV50_DISPLAY_UNK30_CTRL 0x00610030 - #define NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK0 (1 << 9) - #define NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK1 (1 << 10) - #define NV50_DISPLAY_UNK30_CTRL_PENDING (1 << 31) - -#define NV50_DISPLAY_UNK50_CTRL 0x00610050 - #define NV50_DISPLAY_UNK50_CTRL_CRTC0_ACTIVE (2 << 0) - #define NV50_DISPLAY_UNK50_CTRL_CRTC0_MASK (3 << 0) - #define NV50_DISPLAY_UNK50_CTRL_CRTC1_ACTIVE (2 << 8) - #define NV50_DISPLAY_UNK50_CTRL_CRTC1_MASK (3 << 8) - -/* I really don't know what this does, except that it's only revelant at start. */ -#define NV50_DISPLAY_UNK200_CTRL 0x00610200 - -/* bit3 always activates itself, and bit 4 is some kind of switch. */ -#define NV50_CRTC0_CURSOR_CTRL2 0x00610270 - #define NV50_CRTC_CURSOR_CTRL2_ON (1 << 0) - #define NV50_CRTC_CURSOR_CTRL2_OFF (0 << 0) - #define NV50_CRTC_CURSOR_CTRL2_STATUS_MASK (3 << 16) - #define NV50_CRTC_CURSOR_CTRL2_STATUS_ACTIVE (1 << 16) -#define NV50_CRTC1_CURSOR_CTRL2 0x00610280 - -#define NV50_DISPLAY_CTRL_STATE 0x00610300 - #define NV50_DISPLAY_CTRL_STATE_DISABLE (0 << 0) - #define NV50_DISPLAY_CTRL_STATE_ENABLE (1 << 0) - #define NV50_DISPLAY_CTRL_STATE_PENDING (1 << 31) -#define NV50_DISPLAY_CTRL_VAL 0x00610304 - -#define NV50_DISPLAY_UNK_380 0x00610380 -/* Clamped to 256 MiB */ -#define NV50_DISPLAY_RAM_AMOUNT 0x00610384 -#define NV50_DISPLAY_UNK_388 0x00610388 -#define NV50_DISPLAY_UNK_38C 0x0061038C - -/* The registers in this range are normally accessed through display commands, with an offset of 0x540 for crtc1. */ -/* They also seem duplicated into the next register as well. */ -#define NV50_CRTC0_CLUT_MODE_VAL 0x00610A24 -#define NV50_CRTC0_SCALE_CTRL_VAL 0x00610A50 -#define NV50_CRTC0_CURSOR_CTRL_VAL 0x00610A58 -#define NV50_CRTC0_DEPTH_VAL 0x00610AC8 -#define NV50_CRTC0_CLOCK_VAL 0x00610AD0 -#define NV50_CRTC0_COLOR_CTRL_VAL 0x00610AE0 -#define NV50_CRTC0_SYNC_START_TO_BLANK_END_VAL 0x00610AE8 -#define NV50_CRTC0_MODE_UNK1_VAL 0x00610AF0 -#define NV50_CRTC0_DISPLAY_TOTAL_VAL 0x00610AF8 -#define NV50_CRTC0_SYNC_DURATION_VAL 0x00610B00 -/* For some reason this displayed the maximum framebuffer size for crtc0/dfp. */ -/* It was correct for crtc1/afp. */ -#define NV50_CRTC0_FB_SIZE_VAL 0x00610B18 -#define NV50_CRTC0_FB_PITCH_VAL 0x00610B20 -#define NV50_CRTC0_FB_POS_VAL 0x00610B28 -#define NV50_CRTC0_SCALE_CENTER_OFFSET_VAL 0x00610B38 -#define NV50_CRTC0_REAL_RES_VAL 0x00610B40 -/* I can't be 100% about the order of these two, as setting them differently locks up the card. */ -#define NV50_CRTC0_SCALE_RES1_VAL 0x00610B48 -#define NV50_CRTC0_SCALE_RES2_VAL 0x00610B50 - -/* Some registers are based on extrapolation. */ -#define NV50_DAC0_MODE_CTRL_VAL 0x00610B58 -#define NV50_DAC1_MODE_CTRL_VAL 0x00610B60 -#define NV50_DAC2_MODE_CTRL_VAL 0x00610B68 -#define NV50_SOR0_MODE_CTRL_VAL 0x00610B70 -#define NV50_SOR1_MODE_CTRL_VAL 0x00610B78 -#define NV50_SOR2_MODE_CTRL_VAL 0x00610B80 - -#define NV50_DAC0_MODE_CTRL2_VAL 0x00610BDC -#define NV50_DAC1_MODE_CTRL2_VAL 0x00610BE4 -#define NV50_DAC2_MODE_CTRL2_VAL 0x00610BEC - -#define NV50_CRTC1_CLUT_MODE_VAL 0x00610F64 -#define NV50_CRTC1_SCALE_CTRL_VAL 0x00610F90 -#define NV50_CRTC1_CURSOR_CTRL_VAL 0x00610F98 -#define NV50_CRTC1_DEPTH_VAL 0x00611008 -#define NV50_CRTC1_CLOCK_VAL 0x00611010 -#define NV50_CRTC1_COLOR_CTRL_VAL 0x00611020 -#define NV50_CRTC1_SYNC_START_TO_BLANK_END_VAL 0x00611028 -#define NV50_CRTC1_MODE_UNK1_VAL 0x00611030 -#define NV50_CRTC1_DISPLAY_TOTAL_VAL 0x00611038 -#define NV50_CRTC1_SYNC_DURATION_VAL 0x00611040 -#define NV50_CRTC1_FB_SIZE_VAL 0x00611058 -#define NV50_CRTC1_FB_PITCH_VAL 0x00611060 -#define NV50_CRTC1_FB_POS_VAL 0x00611068 -#define NV50_CRTC1_SCALE_CENTER_OFFSET_VAL 0x00611078 -#define NV50_CRTC1_REAL_RES_VAL 0x00611080 -/* I can't be 100% about the order of these two, as setting them differently locks up the card. */ -#define NV50_CRTC1_SCALE_RES1_VAL 0x00611088 -#define NV50_CRTC1_SCALE_RES2_VAL 0x00611090 - -/* These CLK_CTRL names are a bit of a guess, i do have my reasons though. */ -/* These connected indicators exist for crtc, dac and sor. */ -#define NV50_CRTC0_CLK_CTRL1 0x00614100 - #define NV50_CRTC_CLK_CTRL1_CONNECTED (3 << 9) -/* These are probably redrirected from 0x4000 range (very similar regs to nv40, maybe different order) */ -#define NV50_CRTC0_VPLL_A 0x00614104 -#define NV50_CRTC0_VPLL_B 0x00614108 -#define NV50_CRTC0_CLK_CTRL2 0x00614200 - -/* These control some special modes, like dual link dvi, maybe they need another name? */ -#define NV50_DAC0_CLK_CTRL2 0x00614280 -#define NV50_SOR0_CLK_CTRL2 0x00614300 - -#define NV50_CRTC1_CLK_CTRL1 0x00614900 -#define NV50_CRTC1_VPLL_A 0x00614904 -#define NV50_CRTC1_VPLL_B 0x00614908 -#define NV50_CRTC1_CLK_CTRL2 0x00614A00 - -#define NV50_DAC1_CLK_CTRL2 0x00614A80 -#define NV50_SOR1_CLK_CTRL2 0x00614B00 - -#define NV50_DAC2_CLK_CTRL2 0x00615280 -#define NV50_SOR2_CLK_CTRL2 0x00615300 - -#define NV50_DAC0_DPMS_CTRL 0x0061A004 - #define NV50_DAC_DPMS_CTRL_HSYNC_OFF (1 << 0) - #define NV50_DAC_DPMS_CTRL_VSYNC_OFF (1 << 2) - #define NV50_DAC_DPMS_CTRL_BLANKED (1 << 4) - #define NV50_DAC_DPMS_CTRL_OFF (1 << 6) - /* Some cards also use bit 22, why exactly is unknown. */ - /* It seems that 1, 4 and 5 are present at bit0. bit4. bit16, bit20. */ - /* No idea what the symmetry means precisely. */ - #define NV50_DAC_DPMS_CTRL_DEFAULT_STATE (21 << 16) - #define NV50_DAC_DPMS_CTRL_PENDING (1 << 31) -#define NV50_DAC0_LOAD_CTRL 0x0061A00C - #define NV50_DAC_LOAD_CTRL_ACTIVE (1 << 20) - #define NV50_DAC_LOAD_CTRL_PRESENT (7 << 27) - /* this a bit of a guess, as load detect is very fast */ - #define NV50_DAC_LOAD_CTRL_DONE (1 << 31) -/* These connected indicators exist for crtc, dac and sor. */ -/* The upper 4 bits seem to be some kind indicator. */ -/* The purpose of bit 1 is unknown, maybe some kind of reset? */ -#define NV50_DAC0_CLK_CTRL1 0x0061A010 - #define NV50_DAC_CLK_CTRL1_CONNECTED (3 << 9) -#define NV50_DAC1_DPMS_CTRL 0x0061A804 -#define NV50_DAC1_LOAD_CTRL 0x0061A80C -#define NV50_DAC1_CLK_CTRL1 0x0061A810 -#define NV50_DAC2_DPMS_CTRL 0x0061B004 -#define NV50_DAC2_LOAD_CTRL 0x0061B00C -#define NV50_DAC2_CLK_CTRL1 0x0061B010 - -/* both SOR_DPMS and DAC_DPMS have a bit28, whose purpose is unknown atm. */ -#define NV50_SOR0_DPMS_CTRL 0x0061C004 - #define NV50_SOR_DPMS_CTRL_MODE_ON (1 << 0) - #define NV50_SOR_DPMS_CTRL_PENDING (1 << 31) -/* These connected indicators exist for crtc, dac and sor. */ -/* I don't know what bit27 does, it doesn't seem extremely important. */ -#define NV50_SOR0_CLK_CTRL1 0x0061C008 - #define NV50_SOR_CLK_CTRL1_CONNECTED (3 << 9) -/* Seems to be a default state, nothing that can RE'd in great detail. */ -#define NV50_SOR0_UNK00C 0x0061C00C -#define NV50_SOR0_UNK010 0x0061C010 -#define NV50_SOR0_UNK014 0x0061C014 -#define NV50_SOR0_UNK018 0x0061C018 - -#define NV50_SOR0_DPMS_STATE 0x0061C030 - #define NV50_SOR_DPMS_STATE_ACTIVE (3 << 16) /* this does not show if DAC is active */ - #define NV50_SOR_DPMS_STATE_BLANKED (8 << 16) - #define NV50_SOR_DPMS_STATE_WAIT (1 << 28) - -#define NV50_SOR1_DPMS_CTRL 0x0061C804 -#define NV50_SOR1_CLK_CTRL1 0x0061C808 -/* Seems to be a default state, nothing that can RE'd in any great detail. */ -#define NV50_SOR1_UNK00C 0x0061C80C -#define NV50_SOR1_UNK010 0x0061C810 -#define NV50_SOR1_UNK014 0x0061C814 -#define NV50_SOR1_UNK018 0x0061C818 - -#define NV50_SOR1_DPMS_STATE 0x0061C830 - -#define NV50_SOR2_DPMS_CTRL 0x0061D004 -#define NV50_SOR2_CLK_CTRL1 0x0061D008 -/* Seems to be a default state, nothing that can RE'd in any great detail. */ -#define NV50_SOR2_UNK00C 0x0061D00C -#define NV50_SOR2_UNK010 0x0061D010 -#define NV50_SOR2_UNK014 0x0061D014 -#define NV50_SOR2_UNK018 0x0061D018 - -#define NV50_SOR2_DPMS_STATE 0x0061D030 - -/* A few things seem to exist in the 0x0064XXXX range, but not much. */ -/* Each of these corresponds to a range in 0x006102XX. */ -/* The blob writes zero to these regs. */ -/* 0x00610200-0x0061020C, 0x00610200 seems special from all the rest. */ -#define NV50_UNK_640000 0x00640000 -/* 0x00610210-0x0061021C */ -#define NV50_UNK_641000 0x00641000 -/* 0x00610220-0x0061022C */ -/* Seems tv-out related somehow, the other two show up always. */ -#define NV50_UNK_642000 0x00642000 -/* 0x00610230-0x0061023C and 0x00610240-0x0061024C seem to be similar. */ -/* I think the correlation goes for all 0x0064X000, up to and including 6. */ - -/* Write 0 to process the new position, seem to be write only registers. */ -#define NV50_CRTC0_CURSOR_POS_CTRL 0x00647080 -#define NV50_CRTC0_CURSOR_POS 0x00647084 -#define NV50_CRTC1_CURSOR_POS_CTRL 0x00648080 -#define NV50_CRTC1_CURSOR_POS 0x00648084 - -/* These things below are so called "commands" */ -#define NV50_UPDATE_DISPLAY 0x80 -#define NV50_UNK84 0x84 -#define NV50_UNK88 0x88 - -#define NV50_DAC0_MODE_CTRL 0x400 - #define NV50_DAC_MODE_CTRL_OFF (0 << 0) - #define NV50_DAC_MODE_CTRL_CRTC0 (1 << 0) - #define NV50_DAC_MODE_CTRL_CRTC1 (1 << 1) -#define NV50_DAC1_MODE_CTRL 0x480 -#define NV50_DAC2_MODE_CTRL 0x500 - -#define NV50_DAC0_MODE_CTRL2 0x404 - #define NV50_DAC_MODE_CTRL2_NHSYNC (1 << 0) - #define NV50_DAC_MODE_CTRL2_NVSYNC (2 << 0) -#define NV50_DAC1_MODE_CTRL2 0x484 -#define NV50_DAC2_MODE_CTRL2 0x504 - -#define NV50_SOR0_MODE_CTRL 0x600 - #define NV50_SOR_MODE_CTRL_OFF (0 << 0) - #define NV50_SOR_MODE_CTRL_CRTC0 (1 << 0) - #define NV50_SOR_MODE_CTRL_CRTC1 (1 << 1) - #define NV50_SOR_MODE_CTRL_LVDS (0 << 8) - #define NV50_SOR_MODE_CTRL_TMDS (1 << 8) - #define NV50_SOR_MODE_CTRL_TMDS_DUAL_LINK (4 << 8) - #define NV50_SOR_MODE_CTRL_NHSYNC (1 << 12) - #define NV50_SOR_MODE_CTRL_NVSYNC (2 << 12) -#define NV50_SOR1_MODE_CTRL 0x640 -#define NV50_SOR2_MODE_CTRL 0x680 - -#define NV50_CRTC0_UNK800 0x800 -#define NV50_CRTC0_CLOCK 0x804 -#define NV50_CRTC0_INTERLACE 0x808 - -/* 0x810 is a reasonable guess, nothing more. */ -#define NV50_CRTC0_DISPLAY_START 0x810 -#define NV50_CRTC0_DISPLAY_TOTAL 0x814 -#define NV50_CRTC0_SYNC_DURATION 0x818 -#define NV50_CRTC0_SYNC_START_TO_BLANK_END 0x81C -#define NV50_CRTC0_MODE_UNK1 0x820 -#define NV50_CRTC0_MODE_UNK2 0x824 - -#define NV50_CRTC0_UNK82C 0x82C - -/* You can't have a palette in 8 bit mode (=OFF) */ -#define NV50_CRTC0_CLUT_MODE 0x840 - #define NV50_CRTC0_CLUT_MODE_BLANK 0x00000000 - #define NV50_CRTC0_CLUT_MODE_OFF 0x80000000 - #define NV50_CRTC0_CLUT_MODE_ON 0xC0000000 -#define NV50_CRTC0_CLUT_OFFSET 0x844 - -/* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC0_BLANK_UNK1 0x85C - #define NV84_CRTC0_BLANK_UNK1_BLANK 0x0 - #define NV84_CRTC0_BLANK_UNK1_UNBLANK 0x1 - -#define NV50_CRTC0_FB_OFFSET 0x860 - -#define NV50_CRTC0_FB_SIZE 0x868 -#define NV50_CRTC0_FB_PITCH 0x86C - -#define NV50_CRTC0_DEPTH 0x870 - #define NV50_CRTC0_DEPTH_8BPP 0x1E00 - #define NV50_CRTC0_DEPTH_15BPP 0xE900 - #define NV50_CRTC0_DEPTH_16BPP 0xE800 - #define NV50_CRTC0_DEPTH_24BPP 0xCF00 - -/* I'm openminded to better interpretations. */ -/* This is an educated guess. */ -/* NV50 has RAMDAC and TMDS offchip, so it's unlikely to be that. */ -#define NV50_CRTC0_BLANK_CTRL 0x874 - #define NV50_CRTC0_BLANK_CTRL_BLANK 0x0 - #define NV50_CRTC0_BLANK_CTRL_UNBLANK 0x1 - -#define NV50_CRTC0_CURSOR_CTRL 0x880 - #define NV50_CRTC0_CURSOR_CTRL_SHOW 0x85000000 - #define NV50_CRTC0_CURSOR_CTRL_HIDE 0x05000000 - -#define NV50_CRTC0_CURSOR_OFFSET 0x884 - -/* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC0_BLANK_UNK2 0x89C - #define NV84_CRTC0_BLANK_UNK2_BLANK 0x0 - #define NV84_CRTC0_BLANK_UNK2_UNBLANK 0x1 - -#define NV50_CRTC0_DITHERING_CTRL 0x8A0 - #define NV50_CRTC0_DITHERING_CTRL_ON 0x11 - #define NV50_CRTC0_DITHERING_CTRL_OFF 0x0 - -#define NV50_CRTC0_SCALE_CTRL 0x8A4 - #define NV50_CRTC0_SCALE_CTRL_SCALER_INACTIVE (0 << 0) - /* It doesn't seem to be needed, hence i wonder what it does precisely. */ - #define NV50_CRTC0_SCALE_CTRL_SCALER_ACTIVE (9 << 0) -#define NV50_CRTC0_COLOR_CTRL 0x8A8 - #define NV50_CRTC_COLOR_CTRL_MODE_COLOR (4 << 16) - -#define NV50_CRTC0_FB_POS 0x8C0 -#define NV50_CRTC0_REAL_RES 0x8C8 - -/* Added a macro, because the signed stuff can cause you problems very quickly. */ -#define NV50_CRTC0_SCALE_CENTER_OFFSET 0x8D4 - #define NV50_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) ((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF)) -/* Both of these are needed, otherwise nothing happens. */ -#define NV50_CRTC0_SCALE_RES1 0x8D8 -#define NV50_CRTC0_SCALE_RES2 0x8DC - -#define NV50_CRTC1_UNK800 0xC00 -#define NV50_CRTC1_CLOCK 0xC04 -#define NV50_CRTC1_INTERLACE 0xC08 - -/* 0xC10 is a reasonable guess, nothing more. */ -#define NV50_CRTC1_DISPLAY_START 0xC10 -#define NV50_CRTC1_DISPLAY_TOTAL 0xC14 -#define NV50_CRTC1_SYNC_DURATION 0xC18 -#define NV50_CRTC1_SYNC_START_TO_BLANK_END 0xC1C -#define NV50_CRTC1_MODE_UNK1 0xC20 -#define NV50_CRTC1_MODE_UNK2 0xC24 - -#define NV50_CRTC1_CLUT_MODE 0xC40 - #define NV50_CRTC1_CLUT_MODE_BLANK 0x00000000 - #define NV50_CRTC1_CLUT_MODE_OFF 0x80000000 - #define NV50_CRTC1_CLUT_MODE_ON 0xC0000000 -#define NV50_CRTC1_CLUT_OFFSET 0xC44 - -/* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC1_BLANK_UNK1 0xC5C - #define NV84_CRTC1_BLANK_UNK1_BLANK 0x0 - #define NV84_CRTC1_BLANK_UNK1_UNBLANK 0x1 - -#define NV50_CRTC1_FB_OFFSET 0xC60 - -#define NV50_CRTC1_FB_SIZE 0xC68 -#define NV50_CRTC1_FB_PITCH 0xC6C - -#define NV50_CRTC1_DEPTH 0xC70 - #define NV50_CRTC1_DEPTH_8BPP 0x1E00 - #define NV50_CRTC1_DEPTH_15BPP 0xE900 - #define NV50_CRTC1_DEPTH_16BPP 0xE800 - #define NV50_CRTC1_DEPTH_24BPP 0xCF00 - -/* I'm openminded to better interpretations. */ -#define NV50_CRTC1_BLANK_CTRL 0xC74 - #define NV50_CRTC1_BLANK_CTRL_BLANK 0x0 - #define NV50_CRTC1_BLANK_CTRL_UNBLANK 0x1 - -#define NV50_CRTC1_CURSOR_CTRL 0xC80 - #define NV50_CRTC1_CURSOR_CTRL_SHOW 0x85000000 - #define NV50_CRTC1_CURSOR_CTRL_HIDE 0x05000000 - -#define NV50_CRTC1_CURSOR_OFFSET 0xC84 - -/* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC1_BLANK_UNK2 0xC9C - #define NV84_CRTC1_BLANK_UNK2_BLANK 0x0 - #define NV84_CRTC1_BLANK_UNK2_UNBLANK 0x1 - -#define NV50_CRTC1_DITHERING_CTRL 0xCA0 - #define NV50_CRTC1_DITHERING_CTRL_ON 0x11 - #define NV50_CRTC1_DITHERING_CTRL_OFF 0x0 - -#define NV50_CRTC1_SCALE_CTRL 0xCA4 -#define NV50_CRTC1_COLOR_CTRL 0xCA8 - -#define NV50_CRTC1_FB_POS 0xCC0 -#define NV50_CRTC1_REAL_RES 0xCC8 - -#define NV50_CRTC1_SCALE_CENTER_OFFSET 0xCD4 -/* Both of these are needed, otherwise nothing happens. */ -#define NV50_CRTC1_SCALE_RES1 0xCD8 -#define NV50_CRTC1_SCALE_RES2 0xCDC - -/* misc stuff */ -#define NV50_I2C_START 0x7 -#define NV50_I2C_STOP 0x3 - -#endif /* __NV50REG_H_ */ diff --git a/src/nv_accel_common.c b/src/nv_accel_common.c index 05fdeb9..4ddb89e 100644 --- a/src/nv_accel_common.c +++ b/src/nv_accel_common.c @@ -261,7 +261,7 @@ NVAccelInitImageBlit(ScrnInfoPtr pScrn) struct nouveau_grobj *blit; uint32_t class; - class = (pNv->WaitVSyncPossible) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT; + class = (pNv->NVArch > 0x11) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT; if (!pNv->NvImageBlit) { if (nouveau_grobj_alloc(chan, NvImageBlit, class, @@ -283,7 +283,7 @@ NVAccelInitImageBlit(ScrnInfoPtr pScrn) BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_OPERATION, 1); OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_ROP_AND); - if (pNv->WaitVSyncPossible) { + if (blit->grclass == NV12_IMAGE_BLIT) { BEGIN_RING(chan, blit, 0x0120, 3); OUT_RING (chan, 0); OUT_RING (chan, 1); diff --git a/src/nv_bios.c b/src/nv_bios.c deleted file mode 100644 index 218bf7d..0000000 --- a/src/nv_bios.c +++ /dev/null @@ -1,4810 +0,0 @@ -/* - * Copyright 2005-2006 Erik Waling - * Copyright 2006 Stephane Marchesin - * Copyright 2007-2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -#if defined(__FreeBSD__) || defined(__NetBSD__) -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#else -#include -#endif - -/* these defines are made up */ -#define NV_CIO_CRE_44_HEADA 0x0 -#define NV_CIO_CRE_44_HEADB 0x3 -#define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */ -#define LEGACY_I2C_CRT 0x80 -#define LEGACY_I2C_PANEL 0x81 - -#define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip, fmt, ##arg) -#define LOG_OLD_VALUE(x) //x - -#define BIOS_USLEEP(n) usleep(n) - -#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) -#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) - -static int crtchead = 0; - -/* this will need remembering across a suspend */ -static uint32_t saved_nv_pfb_cfg0; - -typedef struct { - bool execute; - bool repeat; -} init_exec_t; - -static inline uint16_t le16_to_cpu(const uint16_t x) -{ -#if X_BYTE_ORDER == X_BIG_ENDIAN - return bswap_16(x); -#else - return x; -#endif -} - -static inline uint32_t le32_to_cpu(const uint32_t x) -{ -#if X_BYTE_ORDER == X_BIG_ENDIAN - return bswap_32(x); -#else - return x; -#endif -} - -static bool nv_cksum(const uint8_t *data, unsigned int length) -{ - /* there's a few checksums in the BIOS, so here's a generic checking function */ - int i; - uint8_t sum = 0; - - for (i = 0; i < length; i++) - sum += data[i]; - - if (sum) - return true; - - return false; -} - -static int -score_vbios(ScrnInfoPtr pScrn, const uint8_t *data, const bool writeable) -{ - if (!(data[0] == 0x55 && data[1] == 0xAA)) { - NV_TRACEWARN(pScrn, "... BIOS signature not found\n"); - return 0; - } - - if (nv_cksum(data, data[2] * 512)) { - NV_TRACEWARN(pScrn, "... BIOS checksum invalid\n"); - /* if a ro image is somewhat bad, it's probably all rubbish */ - return writeable ? 2 : 1; - } else - NV_TRACE(pScrn, "... appears to be valid\n"); - - return 3; -} - -static void load_vbios_prom(NVPtr pNv, uint8_t *data) -{ - uint32_t pci_nv_20, save_pci_nv_20; - int pcir_ptr; - int i; - - if (pNv->Architecture >= NV_ARCH_50) - pci_nv_20 = 0x88050; - else - pci_nv_20 = NV_PBUS_PCI_NV_20; - - /* enable ROM access */ - save_pci_nv_20 = nvReadMC(pNv, pci_nv_20); - nvWriteMC(pNv, pci_nv_20, - save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); - - /* bail if no rom signature */ - if (NV_RD08(pNv->REGS, NV_PROM_OFFSET) != 0x55 || - NV_RD08(pNv->REGS, NV_PROM_OFFSET + 1) != 0xaa) - goto out; - - /* additional check (see note below) - read PCI record header */ - pcir_ptr = NV_RD08(pNv->REGS, NV_PROM_OFFSET + 0x18) | - NV_RD08(pNv->REGS, NV_PROM_OFFSET + 0x19) << 8; - if (NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr) != 'P' || - NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 1) != 'C' || - NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 2) != 'I' || - NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 3) != 'R') - goto out; - - /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a - * a good read may be obtained by waiting or re-reading (cargocult: 5x) - * each byte. we'll hope pramin has something usable instead - */ - for (i = 0; i < NV_PROM_SIZE; i++) - data[i] = NV_RD08(pNv->REGS, NV_PROM_OFFSET + i); - -out: - /* disable ROM access */ - nvWriteMC(pNv, pci_nv_20, - save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED); -} - -static void load_vbios_pramin(NVPtr pNv, uint8_t *data) -{ - uint32_t old_bar0_pramin = 0; - int i; - - if (pNv->Architecture >= NV_ARCH_50) { - uint32_t vbios_vram = (NV_RD32(pNv->REGS, 0x619f04) & ~0xff) << 8; - - if (!vbios_vram) - vbios_vram = (NV_RD32(pNv->REGS, 0x1700) << 16) + 0xf0000; - - old_bar0_pramin = NV_RD32(pNv->REGS, 0x1700); - NV_WR32(pNv->REGS, 0x1700, vbios_vram >> 16); - } - - /* bail if no rom signature */ - if (NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET) != 0x55 || - NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET + 1) != 0xaa) - goto out; - - for (i = 0; i < NV_PROM_SIZE; i++) - data[i] = NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET + i); - -out: - if (pNv->Architecture >= NV_ARCH_50) - NV_WR32(pNv->REGS, 0x1700, old_bar0_pramin); -} - -static void load_vbios_pci(NVPtr pNv, uint8_t *data) -{ - pci_device_read_rom(pNv->PciInfo, data); -} - -struct methods { - const char desc[8]; - void (*loadbios)(NVPtr, uint8_t *); - const bool rw; - int score; -}; - -static struct methods nv04_methods[] = { - { "PROM", load_vbios_prom, false }, - { "PRAMIN", load_vbios_pramin, true }, - { "PCI ROM", load_vbios_pci, true }, - { } -}; - -static struct methods nv50_methods[] = { - { "PRAMIN", load_vbios_pramin, true }, - { "PROM", load_vbios_prom, false }, - { "PCI ROM", load_vbios_pci, true }, - { } -}; - -static bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data) -{ - NVPtr pNv = NVPTR(pScrn); - struct methods *methods, *method; - int testscore = 3; - - if (pNv->Architecture < NV_ARCH_50) - methods = nv04_methods; - else - methods = nv50_methods; - - method = methods; - while (method->loadbios) { - NV_TRACE(pScrn, "Attempting to load BIOS image from %s\n", - method->desc); - data[0] = data[1] = 0; /* avoid reuse of previous image */ - method->loadbios(pNv, data); - method->score = score_vbios(pScrn, data, method->rw); - if (method->score == testscore) - return true; - method++; - } - - while (--testscore > 0) { - method = methods; - while (method->loadbios) { - if (method->score == testscore) { - NV_TRACE(pScrn, "Using BIOS image from %s\n", - method->desc); - method->loadbios(pNv, data); - return true; - } - method++; - } - } - - NV_ERROR(pScrn, "No valid BIOS image found\n"); - return false; -} - -typedef struct { - char* name; - uint8_t id; - int length; - int length_offset; - int length_multiplier; - bool (*handler)(ScrnInfoPtr pScrn, struct nvbios *, uint16_t, init_exec_t *); -} init_tbl_entry_t; - -typedef struct { - uint8_t id[2]; - uint16_t length; - uint16_t offset; -} bit_entry_t; - -static int parse_init_table(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset, init_exec_t *iexec); - -#define MACRO_INDEX_SIZE 2 -#define MACRO_SIZE 8 -#define CONDITION_SIZE 12 -#define IO_FLAG_CONDITION_SIZE 9 -#define IO_CONDITION_SIZE 5 -#define MEM_INIT_SIZE 66 - -static void still_alive(void) -{ -// sync(); -// BIOS_USLEEP(2000); -} - -static uint32_t -munge_reg(ScrnInfoPtr pScrn, uint32_t reg) -{ - NVPtr pNv = NVPTR(pScrn); - - if (pNv->Architecture < NV_ARCH_50) - return reg; - - if (reg & 0x40000000) - reg += pNv->VBIOS.display.head * 0x800; - - reg &= ~(0x40000000); - return reg; -} - -static int valid_reg(ScrnInfoPtr pScrn, uint32_t reg) -{ - NVPtr pNv = NVPTR(pScrn); - - /* C51 has misaligned regs on purpose. Marvellous */ - if (reg & 0x2 || (reg & 0x1 && pNv->VBIOS.pub.chip_version != 0x51)) { - NV_ERROR(pScrn, "========== misaligned reg 0x%08X ==========\n", - reg); - return 0; - } - /* warn on C51 regs that haven't been verified accessible in mmiotracing */ - if (reg & 0x1 && pNv->VBIOS.pub.chip_version == 0x51 && - reg != 0x130d && reg != 0x1311 && reg != 0x60081d) - NV_WARN(pScrn, "=== C51 misaligned reg 0x%08X not verified ===\n", - reg); - - #define WITHIN(x,y,z) ((x>=y)&&(x<=y+z)) - if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE)) - return 1; - if (WITHIN(reg,NV_PBUS_OFFSET,NV_PBUS_SIZE)) - return 1; - if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE)) - return 1; - /* maybe a little large, but it will do for the moment. */ - if (pNv->Architecture == NV_ARCH_50 && WITHIN(reg, 0x1000, 0xEFFF)) - return 1; - if (pNv->VBIOS.pub.chip_version >= 0x30 && WITHIN(reg,0x4000,0x600)) - return 1; - if (pNv->VBIOS.pub.chip_version >= 0x40 && WITHIN(reg,0xc000,0x48)) - return 1; - if (pNv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204) - return 1; - if (pNv->VBIOS.pub.chip_version >= 0x40) { - if (reg == 0x00011014 || reg == 0x00020328) - return 1; - if (WITHIN(reg,0x88000,NV_PBUS_SIZE)) /* new PBUS */ - return 1; - } - if (pNv->Architecture == NV_ARCH_50) { - /* No clue what they do, but because they are outside normal - * ranges we' better list them seperately. */ - if (reg == 0x00020018 || reg == 0x0002004C || - reg == 0x00020060 || reg == 0x00021218 || - reg == 0x0002130C || reg == 0x00089008 || - reg == 0x00089028) - return 1; - } - if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE)) - return 1; - if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE)) - return 1; - if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE * 2)) - return 1; - if (pNv->Architecture == NV_ARCH_50 && - WITHIN(reg, NV50_DISPLAY_OFFSET, NV50_DISPLAY_SIZE)) - return 1; - if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE * 2)) - return 1; - if (pNv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0) - return 1; - if (pNv->VBIOS.pub.chip_version == 0x51 && WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE)) - return 1; - #undef WITHIN - - NV_ERROR(pScrn, "========== unknown reg 0x%08X ==========\n", reg); - - return 0; -} - -static bool valid_idx_port(ScrnInfoPtr pScrn, uint16_t port) -{ - /* if adding more ports here, the read/write functions below will need - * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is - * used for the port in question - */ - if (port == NV_CIO_CRX__COLOR) - return true; - if (port == NV_VIO_SRX) - return true; - - NV_ERROR(pScrn, "========== unknown indexed io port 0x%04X ==========\n", - port); - - return false; -} - -static bool valid_port(ScrnInfoPtr pScrn, uint16_t port) -{ - /* if adding more ports here, the read/write functions below will need - * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is - * used for the port in question - */ - if (port == NV_VIO_VSE2) - return true; - - NV_ERROR(pScrn, "========== unknown io port 0x%04X ==========\n", port); - - return false; -} - -static uint32_t bios_rd32(ScrnInfoPtr pScrn, uint32_t reg) -{ - NVPtr pNv = NVPTR(pScrn); - uint32_t data; - - reg = munge_reg(pScrn, reg); - if (!valid_reg(pScrn, reg)) - return 0; - - /* C51 sometimes uses regs with bit0 set in the address. For these - * cases there should exist a translation in a BIOS table to an IO - * port address which the BIOS uses for accessing the reg - * - * These only seem to appear for the power control regs to a flat panel, - * and the GPIO regs at 0x60081*. In C51 mmio traces the normal regs - * for 0x1308 and 0x1310 are used - hence the mask below. An S3 - * suspend-resume mmio trace from a C51 will be required to see if this - * is true for the power microcode in 0x14.., or whether the direct IO - * port access method is needed - */ - if (reg & 0x1) - reg &= ~0x1; - - data = NV_RD32(pNv->REGS, reg); - - BIOSLOG(pScrn, " Read: Reg: 0x%08X, Data: 0x%08X\n", reg, data); - - return data; -} - -static void bios_wr32(ScrnInfoPtr pScrn, uint32_t reg, uint32_t data) -{ - NVPtr pNv = NVPTR(pScrn); - - reg = munge_reg(pScrn, reg); - if (!valid_reg(pScrn, reg)) - return; - - /* see note in bios_rd32 */ - if (reg & 0x1) - reg &= 0xfffffffe; - - LOG_OLD_VALUE(bios_rd32(pScrn, reg)); - BIOSLOG(pScrn, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data); - - if (pNv->VBIOS.execute) { - still_alive(); - NV_WR32(pNv->REGS, reg, data); - } -} - -static uint8_t bios_idxprt_rd(ScrnInfoPtr pScrn, uint16_t port, uint8_t index) -{ - NVPtr pNv = NVPTR(pScrn); - uint8_t data; - - if (!valid_idx_port(pScrn, port)) - return 0; - - if (port == NV_VIO_SRX) - data = NVReadVgaSeq(pNv, crtchead, index); - else /* assume NV_CIO_CRX__COLOR */ - data = NVReadVgaCrtc(pNv, crtchead, index); - - BIOSLOG(pScrn, " Indexed IO read: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n", - port, index, crtchead, data); - - return data; -} - -static void bios_idxprt_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t index, uint8_t data) -{ - NVPtr pNv = NVPTR(pScrn); - - if (!valid_idx_port(pScrn, port)) - return; - - /* The current head is maintained in a file scope variable crtchead. - * We trap changes to CR44 and update the head variable and hence the - * register set written. - * As CR44 only exists on CRTC0, we update crtchead to head0 in advance - * of the write, and to head1 after the write - */ - if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && data != NV_CIO_CRE_44_HEADB) - crtchead = 0; - - LOG_OLD_VALUE(bios_idxprt_rd(pScrn, port, index)); - BIOSLOG(pScrn, " Indexed IO write: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n", - port, index, crtchead, data); - - if (pNv->VBIOS.execute) { - still_alive(); - if (port == NV_VIO_SRX) - NVWriteVgaSeq(pNv, crtchead, index, data); - else /* assume NV_CIO_CRX__COLOR */ - NVWriteVgaCrtc(pNv, crtchead, index, data); - } - - if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && data == NV_CIO_CRE_44_HEADB) - crtchead = 1; -} - -static uint8_t bios_port_rd(ScrnInfoPtr pScrn, uint16_t port) -{ - NVPtr pNv = NVPTR(pScrn); - uint8_t data; - - if (!valid_port(pScrn, port)) - return 0; - - data = NVReadPRMVIO(pNv, crtchead, NV_PRMVIO0_OFFSET + port); - - BIOSLOG(pScrn, " IO read: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", - port, crtchead, data); - - return data; -} - -static void bios_port_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t data) -{ - NVPtr pNv = NVPTR(pScrn); - - if (!valid_port(pScrn, port)) - return; - - LOG_OLD_VALUE(bios_port_rd(pScrn, port)); - BIOSLOG(pScrn, " IO write: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n", - port, crtchead, data); - - if (pNv->VBIOS.execute) { - still_alive(); - NVWritePRMVIO(pNv, crtchead, NV_PRMVIO0_OFFSET + port, data); - } -} - -static bool io_flag_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* The IO flag condition entry has 2 bytes for the CRTC port; 1 byte - * for the CRTC index; 1 byte for the mask to apply to the value - * retrieved from the CRTC; 1 byte for the shift right to apply to the - * masked CRTC value; 2 bytes for the offset to the flag array, to - * which the shifted value is added; 1 byte for the mask applied to the - * value read from the flag array; and 1 byte for the value to compare - * against the masked byte from the flag table. - */ - - uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE; - uint16_t crtcport = ROM16(bios->data[condptr]); - uint8_t crtcindex = bios->data[condptr + 2]; - uint8_t mask = bios->data[condptr + 3]; - uint8_t shift = bios->data[condptr + 4]; - uint16_t flagarray = ROM16(bios->data[condptr + 5]); - uint8_t flagarraymask = bios->data[condptr + 7]; - uint8_t cmpval = bios->data[condptr + 8]; - uint8_t data; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, FlagArray: 0x%04X, FAMask: 0x%02X, Cmpval: 0x%02X\n", - offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval); - - data = bios_idxprt_rd(pScrn, crtcport, crtcindex); - - data = bios->data[flagarray + ((data & mask) >> shift)]; - data &= flagarraymask; - - BIOSLOG(pScrn, "0x%04X: Checking if 0x%02X equals 0x%02X\n", offset, data, cmpval); - - return (data == cmpval); -} - -static bool bios_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* The condition table entry has 4 bytes for the address of the - * register to check, 4 bytes for a mask to apply to the register and - * 4 for a test comparison value - */ - - uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE; - uint32_t reg = ROM32(bios->data[condptr]); - uint32_t mask = ROM32(bios->data[condptr + 4]); - uint32_t cmpval = ROM32(bios->data[condptr + 8]); - uint32_t data; - - BIOSLOG(pScrn, "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X\n", - offset, cond, reg, mask); - - data = bios_rd32(pScrn, reg) & mask; - - BIOSLOG(pScrn, "0x%04X: Checking if 0x%08X equals 0x%08X\n", - offset, data, cmpval); - - return (data == cmpval); -} - -static bool io_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond) -{ - /* The IO condition entry has 2 bytes for the IO port address; 1 byte - * for the index to write to io_port; 1 byte for the mask to apply to - * the byte read from io_port+1; and 1 byte for the value to compare - * against the masked byte. - */ - - uint16_t condptr = bios->io_condition_tbl_ptr + cond * IO_CONDITION_SIZE; - uint16_t io_port = ROM16(bios->data[condptr]); - uint8_t port_index = bios->data[condptr + 2]; - uint8_t mask = bios->data[condptr + 3]; - uint8_t cmpval = bios->data[condptr + 4]; - - uint8_t data = bios_idxprt_rd(pScrn, io_port, port_index) & mask; - - BIOSLOG(pScrn, "0x%04X: Checking if 0x%02X equals 0x%02X\n", - offset, data, cmpval); - - return (data == cmpval); -} - -static int setPLL(ScrnInfoPtr pScrn, struct nvbios *bios, uint32_t reg, uint32_t clk) -{ - /* clk in kHz */ - struct pll_lims pll_lim; - int ret; - struct nouveau_pll_vals pllvals; - - /* high regs (such as in the mac g5 table) are not -= 4 */ - if ((ret = get_pll_limits(pScrn, reg > 0x405c ? reg : reg - 4, &pll_lim))) - return ret; - - if (!(clk = nouveau_calc_pll_mnp(pScrn, &pll_lim, clk, &pllvals))) - return -ERANGE; - - if (bios->execute) { - still_alive(); - nouveau_hw_setpll(pScrn, reg, &pllvals); - } - - return 0; -} - -static int dcb_entry_idx_from_crtchead(ScrnInfoPtr pScrn) -{ - /* for the results of this function to be correct, CR44 must have been - * set (using bios_idxprt_wr to set crtchead), CR58 set for CR57 = 0, - * and the DCB table parsed, before the script calling the function is - * run. run_digital_op_script is example of how to do such setup - */ - - uint8_t dcb_entry = NVReadVgaCrtc5758(NVPTR(pScrn), crtchead, 0); - - if (dcb_entry > NVPTR(pScrn)->VBIOS.bdcb.dcb.entries) { - NV_ERROR(pScrn, "CR58 doesn't have a valid DCB entry currently " - "(%02X)\n", dcb_entry); - dcb_entry = 0x7f; /* unused / invalid marker */ - } - - return dcb_entry; -} - -static int init_dcb_i2c_entry(ScrnInfoPtr pScrn, struct nvbios *bios, int index); - -static int -create_i2c_device(ScrnInfoPtr pScrn, struct nvbios *bios, int i2c_index, int address, I2CDevRec *i2cdev) -{ - struct bios_parsed_dcb *bdcb = &bios->bdcb; - int ret; - - if (i2c_index == 0xff) { - /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ - int idx = dcb_entry_idx_from_crtchead(pScrn), shift = 0; - int default_indices = bdcb->i2c_default_indices; - - if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default) - shift = 4; - - i2c_index = (default_indices >> shift) & 0xf; - } - if (i2c_index == 0x80) /* g80+ */ - i2c_index = bdcb->i2c_default_indices & 0xf; - - if ((ret = init_dcb_i2c_entry(pScrn, bios, i2c_index))) - return ret; - - memset(i2cdev, 0, sizeof(I2CDevRec)); - i2cdev->DevName = "init script device"; - i2cdev->pI2CBus = bdcb->dcb.i2c[i2c_index].chan; - i2cdev->SlaveAddr = address; - if (!xf86I2CDevInit(i2cdev)) { - NV_ERROR(pScrn, "Couldn't add I2C device\n"); - return -EINVAL; - } - - return 0; -} - -static uint32_t get_tmds_index_reg(ScrnInfoPtr pScrn, uint8_t mlv) -{ - /* For mlv < 0x80, it is an index into a table of TMDS base addresses - * For mlv == 0x80 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0 - * to index a table of offsets to the basic 0x6808b0 address - * For mlv == 0x81 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0 - * to index a table of offsets to the basic 0x6808b0 address, and then flip the offset by 8 - */ - - NVPtr pNv = NVPTR(pScrn); - const int pramdac_offset[13] = {0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000}; - const uint32_t pramdac_table[4] = {0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8}; - - if (mlv >= 0x80) { - int dcb_entry, dacoffset; - - /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ - if ((dcb_entry = dcb_entry_idx_from_crtchead(pScrn)) == 0x7f) - return 0; - dacoffset = pramdac_offset[pNv->VBIOS.bdcb.dcb.entry[dcb_entry].or]; - if (mlv == 0x81) - dacoffset ^= 8; - return (0x6808b0 + dacoffset); - } else { - if (mlv > (sizeof(pramdac_table) / sizeof(uint32_t))) { - NV_ERROR(pScrn, "Magic Lookup Value too big (%02X)\n", mlv); - return 0; - } - return pramdac_table[mlv]; - } -} - -static bool init_io_restrict_prog(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO_RESTRICT_PROG opcode: 0x32 ('2') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): count - * offset + 7 (32 bit): register - * offset + 11 (32 bit): configuration 1 - * ... - * - * Starting at offset + 11 there are "count" 32 bit values. - * To find out which value to use read index "CRTC index" on "CRTC port", - * AND this value with "mask" and then bit shift right "shift" bits. - * Read the appropriate value using this index and write to "register" - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t reg = ROM32(bios->data[offset + 7]); - uint8_t config; - uint32_t configval; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, count, reg); - - config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(pScrn, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return false; - } - - configval = ROM32(bios->data[offset + 11 + config * 4]); - - BIOSLOG(pScrn, "0x%04X: Writing config %02X\n", offset, config); - - bios_wr32(pScrn, reg, configval); - - return true; -} - -static bool init_repeat(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_REPEAT opcode: 0x33 ('3') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): count - * - * Execute script following this opcode up to INIT_REPEAT_END - * "count" times - */ - - uint8_t count = bios->data[offset + 1]; - uint8_t i; - - /* no iexec->execute check by design */ - - BIOSLOG(pScrn, "0x%04X: Repeating following segment %d times\n", offset, count); - - iexec->repeat = true; - - /* count - 1, as the script block will execute once when we leave this - * opcode -- this is compatible with bios behaviour as: - * a) the block is always executed at least once, even if count == 0 - * b) the bios interpreter skips to the op following INIT_END_REPEAT, - * while we don't - */ - for (i = 0; i < count - 1; i++) - parse_init_table(pScrn, bios, offset + 2, iexec); - - iexec->repeat = false; - - return true; -} - -static bool init_io_restrict_pll(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO_RESTRICT_PLL opcode: 0x34 ('4') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): IO flag condition index - * offset + 7 (8 bit): count - * offset + 8 (32 bit): register - * offset + 12 (16 bit): frequency 1 - * ... - * - * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz). - * Set PLL register "register" to coefficients for frequency n, - * selected by reading index "CRTC index" of "CRTC port" ANDed with - * "mask" and shifted right by "shift". If "IO flag condition index" > 0, - * and condition met, double frequency before setting it. - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - int8_t io_flag_condition_idx = bios->data[offset + 6]; - uint8_t count = bios->data[offset + 7]; - uint32_t reg = ROM32(bios->data[offset + 8]); - uint8_t config; - uint16_t freq; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, IO Flag Condition: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, io_flag_condition_idx, count, reg); - - config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(pScrn, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return false; - } - - freq = ROM16(bios->data[offset + 12 + config * 2]); - - if (io_flag_condition_idx > 0) { - if (io_flag_condition_met(pScrn, bios, offset, io_flag_condition_idx)) { - BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- frequency doubled\n", offset); - freq *= 2; - } else - BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- frequency unchanged\n", offset); - } - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n", - offset, reg, config, freq); - - setPLL(pScrn, bios, reg, freq * 10); - - return true; -} - -static bool init_end_repeat(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_END_REPEAT opcode: 0x36 ('6') - * - * offset (8 bit): opcode - * - * Marks the end of the block for INIT_REPEAT to repeat - */ - - /* no iexec->execute check by design */ - - /* iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when - * we're not in repeat mode - */ - if (iexec->repeat) - return false; - - return true; -} - -static bool init_copy(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_COPY opcode: 0x37 ('7') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): srcmask - * offset + 7 (16 bit): CRTC port - * offset + 9 (8 bit): CRTC index - * offset + 10 (8 bit): mask - * - * Read index "CRTC index" on "CRTC port", AND with "mask", OR with - * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC port - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t shift = bios->data[offset + 5]; - uint8_t srcmask = bios->data[offset + 6]; - uint16_t crtcport = ROM16(bios->data[offset + 7]); - uint8_t crtcindex = bios->data[offset + 9]; - uint8_t mask = bios->data[offset + 10]; - uint32_t data; - uint8_t crtcdata; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n", - offset, reg, shift, srcmask, crtcport, crtcindex, mask); - - data = bios_rd32(pScrn, reg); - - if (shift < 0x80) - data >>= shift; - else - data <<= (0x100 - shift); - - data &= srcmask; - - crtcdata = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) | (uint8_t)data; - bios_idxprt_wr(pScrn, crtcport, crtcindex, crtcdata); - - return true; -} - -static bool init_not(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_NOT opcode: 0x38 ('8') - * - * offset (8 bit): opcode - * - * Invert the current execute / no-execute condition (i.e. "else") - */ - if (iexec->execute) - BIOSLOG(pScrn, "0x%04X: ------ Skipping following commands ------\n", offset); - else - BIOSLOG(pScrn, "0x%04X: ------ Executing following commands ------\n", offset); - - iexec->execute = !iexec->execute; - return true; -} - -static bool init_io_flag_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO_FLAG_CONDITION opcode: 0x39 ('9') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the IO flag condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return true; - - if (io_flag_condition_met(pScrn, bios, offset, cond)) - BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return true; -} - -static bool init_idx_addr_latched(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_INDEX_ADDRESS_LATCHED opcode: 0x49 ('I') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): control register - * offset + 5 (32 bit): data register - * offset + 9 (32 bit): mask - * offset + 13 (32 bit): data - * offset + 17 (8 bit): count - * offset + 18 (8 bit): address 1 - * offset + 19 (8 bit): data 1 - * ... - * - * For each of "count" address and data pairs, write "data n" to "data register", - * read the current value of "control register", and write it back once ANDed - * with "mask", ORed with "data", and ORed with "address n" - */ - - uint32_t controlreg = ROM32(bios->data[offset + 1]); - uint32_t datareg = ROM32(bios->data[offset + 5]); - uint32_t mask = ROM32(bios->data[offset + 9]); - uint32_t data = ROM32(bios->data[offset + 13]); - uint8_t count = bios->data[offset + 17]; - uint32_t value; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n", - offset, controlreg, datareg, mask, data, count); - - for (i = 0; i < count; i++) { - uint8_t instaddress = bios->data[offset + 18 + i * 2]; - uint8_t instdata = bios->data[offset + 19 + i * 2]; - - BIOSLOG(pScrn, "0x%04X: Address: 0x%02X, Data: 0x%02X\n", offset, instaddress, instdata); - - bios_wr32(pScrn, datareg, instdata); - value = (bios_rd32(pScrn, controlreg) & mask) | data | instaddress; - bios_wr32(pScrn, controlreg, value); - } - - return true; -} - -static bool init_io_restrict_pll2(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO_RESTRICT_PLL2 opcode: 0x4A ('J') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): shift - * offset + 6 (8 bit): count - * offset + 7 (32 bit): register - * offset + 11 (32 bit): frequency 1 - * ... - * - * Starting at offset + 11 there are "count" 32 bit frequencies (kHz). - * Set PLL register "register" to coefficients for frequency n, - * selected by reading index "CRTC index" of "CRTC port" ANDed with - * "mask" and shifted right by "shift". - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t shift = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t reg = ROM32(bios->data[offset + 7]); - uint8_t config; - uint32_t freq; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", - offset, crtcport, crtcindex, mask, shift, count, reg); - - if (!reg) - return true; - - config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift; - if (config > count) { - NV_ERROR(pScrn, - "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", - offset, config, count); - return false; - } - - freq = ROM32(bios->data[offset + 11 + config * 4]); - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n", - offset, reg, config, freq); - - setPLL(pScrn, bios, reg, freq); - - return true; -} - -static bool init_pll2(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_PLL2 opcode: 0x4B ('K') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): freq - * - * Set PLL register "register" to coefficients for frequency "freq" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t freq = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", - offset, reg, freq); - - setPLL(pScrn, bios, reg, freq); - - return true; -} - -static bool init_i2c_byte(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_I2C_BYTE opcode: 0x4C ('L') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): I2C register 1 - * offset + 5 (8 bit): mask 1 - * offset + 6 (8 bit): data 1 - * ... - * - * For each of "count" registers given by "I2C register n" on the device - * addressed by "I2C slave address" on the I2C bus given by - * "DCB I2C table entry index", read the register, AND the result with - * "mask n" and OR it with "data n" before writing it back to the device - */ - - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2]; - uint8_t count = bios->data[offset + 3]; - I2CDevRec i2cdev; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev)) - return false; - - for (i = 0; i < count; i++) { - uint8_t i2c_reg = bios->data[offset + 4 + i * 3]; - uint8_t mask = bios->data[offset + 5 + i * 3]; - uint8_t data = bios->data[offset + 6 + i * 3]; - uint8_t value; - - xf86I2CReadByte(&i2cdev, i2c_reg, &value); - - BIOSLOG(pScrn, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", - offset, i2c_reg, value, mask, data); - - value = (value & mask) | data; - - if (bios->execute) - xf86I2CWriteByte(&i2cdev, i2c_reg, value); - } - - xf86DestroyI2CDevRec(&i2cdev, FALSE); - - return true; -} - -static bool init_zm_i2c_byte(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_I2C_BYTE opcode: 0x4D ('M') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): I2C register 1 - * offset + 5 (8 bit): data 1 - * ... - * - * For each of "count" registers given by "I2C register n" on the device - * addressed by "I2C slave address" on the I2C bus given by - * "DCB I2C table entry index", set the register to "data n" - */ - - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2]; - uint8_t count = bios->data[offset + 3]; - I2CDevRec i2cdev; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev)) - return false; - - for (i = 0; i < count; i++) { - uint8_t i2c_reg = bios->data[offset + 4 + i * 2]; - uint8_t data = bios->data[offset + 5 + i * 2]; - - BIOSLOG(pScrn, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n", - offset, i2c_reg, data); - - if (bios->execute) - if (!xf86I2CWriteByte(&i2cdev, i2c_reg, data)) - break; - } - - xf86DestroyI2CDevRec(&i2cdev, FALSE); - - return true; -} - -static bool init_zm_i2c(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_I2C opcode: 0x4E ('N') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): DCB I2C table entry index - * offset + 2 (8 bit): I2C slave address - * offset + 3 (8 bit): count - * offset + 4 (8 bit): data 1 - * ... - * - * Send "count" bytes ("data n") to the device addressed by "I2C slave - * address" on the I2C bus given by "DCB I2C table entry index" - */ - - uint8_t i2c_index = bios->data[offset + 1]; - uint8_t i2c_address = bios->data[offset + 2]; - uint8_t count = bios->data[offset + 3]; - I2CDevRec i2cdev; - uint8_t data[256]; /* 256 is max "count" could specify */ - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n", - offset, i2c_index, i2c_address, count); - - if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev)) - return false; - - for (i = 0; i < count; i++) { - data[i] = bios->data[offset + 4 + i]; - - BIOSLOG(pScrn, "0x%04X: Data: 0x%02X\n", offset, data[i]); - } - - if (bios->execute) - xf86I2CWrite(&i2cdev, data, count); - - xf86DestroyI2CDevRec(&i2cdev, FALSE); - - return true; -} - -static bool init_tmds(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_TMDS opcode: 0x4F ('O') (non-canon name) - * - * offset (8 bit): opcode - * offset + 1 (8 bit): magic lookup value - * offset + 2 (8 bit): TMDS address - * offset + 3 (8 bit): mask - * offset + 4 (8 bit): data - * - * Read the data reg for TMDS address "TMDS address", AND it with mask - * and OR it with data, then write it back - * "magic lookup value" determines which TMDS base address register is used -- - * see get_tmds_index_reg() - */ - - uint8_t mlv = bios->data[offset + 1]; - uint32_t tmdsaddr = bios->data[offset + 2]; - uint8_t mask = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - uint32_t reg, value; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", - offset, mlv, tmdsaddr, mask, data); - - if (!(reg = get_tmds_index_reg(pScrn, mlv))) - return false; - - bios_wr32(pScrn, reg, tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); - value = (bios_rd32(pScrn, reg + 4) & mask) | data; - bios_wr32(pScrn, reg + 4, value); - bios_wr32(pScrn, reg, tmdsaddr); - - return true; -} - -static bool init_zm_tmds_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_TMDS_GROUP opcode: 0x50 ('P') (non-canon name) - * - * offset (8 bit): opcode - * offset + 1 (8 bit): magic lookup value - * offset + 2 (8 bit): count - * offset + 3 (8 bit): addr 1 - * offset + 4 (8 bit): data 1 - * ... - * - * For each of "count" TMDS address and data pairs write "data n" to "addr n" - * "magic lookup value" determines which TMDS base address register is used -- - * see get_tmds_index_reg() - */ - - uint8_t mlv = bios->data[offset + 1]; - uint8_t count = bios->data[offset + 2]; - uint32_t reg; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n", - offset, mlv, count); - - if (!(reg = get_tmds_index_reg(pScrn, mlv))) - return false; - - for (i = 0; i < count; i++) { - uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; - uint8_t tmdsdata = bios->data[offset + 4 + i * 2]; - - bios_wr32(pScrn, reg + 4, tmdsdata); - bios_wr32(pScrn, reg, tmdsaddr); - } - - return true; -} - -static bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CR_INDEX_ADDRESS_LATCHED opcode: 0x51 ('Q') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index1 - * offset + 2 (8 bit): CRTC index2 - * offset + 3 (8 bit): baseaddr - * offset + 4 (8 bit): count - * offset + 5 (8 bit): data 1 - * ... - * - * For each of "count" address and data pairs, write "baseaddr + n" to - * "CRTC index1" and "data n" to "CRTC index2" - * Once complete, restore initial value read from "CRTC index1" - */ - uint8_t crtcindex1 = bios->data[offset + 1]; - uint8_t crtcindex2 = bios->data[offset + 2]; - uint8_t baseaddr = bios->data[offset + 3]; - uint8_t count = bios->data[offset + 4]; - uint8_t oldaddr, data; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, BaseAddr: 0x%02X, Count: 0x%02X\n", - offset, crtcindex1, crtcindex2, baseaddr, count); - - oldaddr = bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, crtcindex1); - - for (i = 0; i < count; i++) { - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex1, baseaddr + i); - - data = bios->data[offset + 5 + i]; - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex2, data); - } - - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex1, oldaddr); - - return true; -} - -static bool init_cr(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CR opcode: 0x52 ('R') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index - * offset + 2 (8 bit): mask - * offset + 3 (8 bit): data - * - * Assign the value of at "CRTC index" ANDed with mask and ORed with data - * back to "CRTC index" - */ - - uint8_t crtcindex = bios->data[offset + 1]; - uint8_t mask = bios->data[offset + 2]; - uint8_t data = bios->data[offset + 3]; - uint8_t value; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", - offset, crtcindex, mask, data); - - value = (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, crtcindex) & mask) | data; - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex, value); - - return true; -} - -static bool init_zm_cr(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_CR opcode: 0x53 ('S') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): CRTC index - * offset + 2 (8 bit): value - * - * Assign "value" to CRTC register with index "CRTC index". - */ - - uint8_t crtcindex = ROM32(bios->data[offset + 1]); - uint8_t data = bios->data[offset + 2]; - - if (!iexec->execute) - return true; - - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex, data); - - return true; -} - -static bool init_zm_cr_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_CR_GROUP opcode: 0x54 ('T') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): count - * offset + 2 (8 bit): CRTC index 1 - * offset + 3 (8 bit): value 1 - * ... - * - * For "count", assign "value n" to CRTC register with index "CRTC index n". - */ - - uint8_t count = bios->data[offset + 1]; - int i; - - if (!iexec->execute) - return true; - - for (i = 0; i < count; i++) - init_zm_cr(pScrn, bios, offset + 2 + 2 * i - 1, iexec); - - return true; -} - -static bool init_condition_time(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CONDITION_TIME opcode: 0x56 ('V') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * offset + 2 (8 bit): retries / 50 - * - * Check condition "condition number" in the condition table. - * Bios code then sleeps for 2ms if the condition is not met, and - * repeats up to "retries" times, but on one C51 this has proved - * insufficient. In mmiotraces the driver sleeps for 20ms, so we do - * this, and bail after "retries" times, or 2s, whichever is less. - * If still not met after retries, clear execution flag for this table. - */ - - uint8_t cond = bios->data[offset + 1]; - uint16_t retries = bios->data[offset + 2] * 50; - - if (!iexec->execute) - return true; - - if (retries > 100) - retries = 100; - - BIOSLOG(pScrn, "0x%04X: Condition: 0x%02X, Retries: 0x%02X\n", offset, cond, retries); - - for (; retries > 0; retries--) - if (bios_condition_met(pScrn, bios, offset, cond)) { - BIOSLOG(pScrn, "0x%04X: Condition met, continuing\n", offset); - break; - } else { - BIOSLOG(pScrn, "0x%04X: Condition not met, sleeping for 20ms\n", offset); - BIOS_USLEEP(20000); - } - - if (!bios_condition_met(pScrn, bios, offset, cond)) { - NV_WARN(pScrn, "0x%04X: Condition still not met after %dms, " - "skiping following opcodes\n", offset, 20 * retries); - iexec->execute = false; - } - - return true; -} - -static bool init_zm_reg_sequence(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_REG_SEQUENCE opcode: 0x58 ('X') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): base register - * offset + 5 (8 bit): count - * offset + 6 (32 bit): value 1 - * ... - * - * Starting at offset + 6 there are "count" 32 bit values. - * For "count" iterations set "base register" + 4 * current_iteration - * to "value current_iteration" - */ - - uint32_t basereg = ROM32(bios->data[offset + 1]); - uint32_t count = bios->data[offset + 5]; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n", offset, basereg, count); - - for (i = 0; i < count; i++) { - uint32_t reg = basereg + i * 4; - uint32_t data = ROM32(bios->data[offset + 6 + i * 4]); - - bios_wr32(pScrn, reg, data); - } - - return true; -} - -static bool init_sub_direct(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_SUB_DIRECT opcode: 0x5B ('[') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): subroutine offset (in bios) - * - * Calls a subroutine that will execute commands until INIT_DONE - * is found. - */ - - uint16_t sub_offset = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Executing subroutine at 0x%04X\n", offset, sub_offset); - - parse_init_table(pScrn, bios, sub_offset, iexec); - - BIOSLOG(pScrn, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset); - - return true; -} - -static bool init_copy_nv_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_COPY_NV_REG opcode: 0x5F ('_') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): src reg - * offset + 5 (8 bit): shift - * offset + 6 (32 bit): src mask - * offset + 10 (32 bit): xor - * offset + 14 (32 bit): dst reg - * offset + 18 (32 bit): dst mask - * - * Shift REGVAL("src reg") right by (signed) "shift", AND result with - * "src mask", then XOR with "xor". Write this OR'd with - * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg" - */ - - uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1])); - uint8_t shift = bios->data[offset + 5]; - uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6])); - uint32_t xor = *((uint32_t *)(&bios->data[offset + 10])); - uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14])); - uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18])); - uint32_t srcvalue, dstvalue; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n", - offset, srcreg, shift, srcmask, xor, dstreg, dstmask); - - srcvalue = bios_rd32(pScrn, srcreg); - - if (shift < 0x80) - srcvalue >>= shift; - else - srcvalue <<= (0x100 - shift); - - srcvalue = (srcvalue & srcmask) ^ xor; - - dstvalue = bios_rd32(pScrn, dstreg) & dstmask; - - bios_wr32(pScrn, dstreg, dstvalue | srcvalue); - - return true; -} - -static bool init_zm_index_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_INDEX_IO opcode: 0x62 ('b') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): data - * - * Write "data" to index "CRTC index" of "CRTC port" - */ - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - - if (!iexec->execute) - return true; - - bios_idxprt_wr(pScrn, crtcport, crtcindex, data); - - return true; -} - -static bool init_compute_mem(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_COMPUTE_MEM opcode: 0x63 ('c') - * - * offset (8 bit): opcode - * - * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so - * that the hardware can correctly calculate how much VRAM it has - * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C)) - * - * The implementation of this opcode in general consists of two parts: - * 1) determination of the memory bus width - * 2) determination of how many of the card's RAM pads have ICs attached - * - * 1) is done by a cunning combination of writes to offsets 0x1c and - * 0x3c in the framebuffer, and seeing whether the written values are - * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0 - * - * 2) is done by a cunning combination of writes to an offset slightly - * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing - * if the test pattern can be read back. This then affects bits 12-15 of - * NV_PFB_CFG0 - * - * In this context a "cunning combination" may include multiple reads - * and writes to varying locations, often alternating the test pattern - * and 0, doubtless to make sure buffers are filled, residual charges - * on tracks are removed etc. - * - * Unfortunately, the "cunning combination"s mentioned above, and the - * changes to the bits in NV_PFB_CFG0 differ with nearly every bios - * trace I have. - * - * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which - * we started was correct, and use that instead - */ - - /* no iexec->execute check by design */ - - /* on every card I've seen, this step gets done for us earlier in the init scripts - uint8_t crdata = bios_idxprt_rd(pScrn, NV_VIO_SRX, 0x01); - bios_idxprt_wr(pScrn, NV_VIO_SRX, 0x01, crdata | 0x20); - */ - - /* this also has probably been done in the scripts, but an mmio trace of - * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write) - */ - bios_wr32(pScrn, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1); - - /* write back the saved configuration value */ - bios_wr32(pScrn, NV_PFB_CFG0, saved_nv_pfb_cfg0); - - return true; -} - -static bool init_reset(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_RESET opcode: 0x65 ('e') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): value1 - * offset + 9 (32 bit): value2 - * - * Assign "value1" to "register", then assign "value2" to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t value1 = ROM32(bios->data[offset + 5]); - uint32_t value2 = ROM32(bios->data[offset + 9]); - uint32_t pci_nv_19, pci_nv_20; - - /* no iexec->execute check by design */ - - pci_nv_19 = bios_rd32(pScrn, NV_PBUS_PCI_NV_19); - bios_wr32(pScrn, NV_PBUS_PCI_NV_19, 0); - bios_wr32(pScrn, reg, value1); - - BIOS_USLEEP(10); - - bios_wr32(pScrn, reg, value2); - bios_wr32(pScrn, NV_PBUS_PCI_NV_19, pci_nv_19); - - pci_nv_20 = bios_rd32(pScrn, NV_PBUS_PCI_NV_20); - pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; /* 0xfffffffe */ - bios_wr32(pScrn, NV_PBUS_PCI_NV_20, pci_nv_20); - - return true; -} - -static bool init_configure_mem(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CONFIGURE_MEM opcode: 0x66 ('f') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, sets up the memory registers, using values - * taken from the memory init table - */ - - /* no iexec->execute check by design */ - - uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); - uint16_t seqtbloffs = bios->legacy.sdr_seq_tbl_ptr, meminitdata = meminitoffs + 6; - uint32_t reg, data; - - if (bios->major_version > 2) - return false; - - bios_idxprt_wr(pScrn, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, - bios_idxprt_rd(pScrn, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); - - if (bios->data[meminitoffs] & 1) - seqtbloffs = bios->legacy.ddr_seq_tbl_ptr; - - for (reg = ROM32(bios->data[seqtbloffs]); - reg != 0xffffffff; - reg = ROM32(bios->data[seqtbloffs += 4])) { - - switch (reg) { - case NV_PFB_PRE: - data = NV_PFB_PRE_CMD_PRECHARGE; - break; - case NV_PFB_PAD: - data = NV_PFB_PAD_CKE_NORMAL; - break; - case NV_PFB_REF: - data = NV_PFB_REF_CMD_REFRESH; - break; - default: - data = ROM32(bios->data[meminitdata]); - meminitdata += 4; - if (data == 0xffffffff) - continue; - } - - bios_wr32(pScrn, reg, data); - } - - return true; -} - -static bool init_configure_clk(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CONFIGURE_CLK opcode: 0x67 ('g') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, sets up the NVClk and MClk PLLs, using - * values taken from the memory init table - */ - - /* no iexec->execute check by design */ - - uint16_t meminitoffs = bios->legacy.mem_init_tbl_ptr + MEM_INIT_SIZE * (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX) >> 4); - int clock; - - if (bios->major_version > 2) - return false; - - clock = ROM16(bios->data[meminitoffs + 4]) * 10; - setPLL(pScrn, bios, NV_PRAMDAC_NVPLL_COEFF, clock); - - clock = ROM16(bios->data[meminitoffs + 2]) * 10; - if (bios->data[meminitoffs] & 1) /* DDR */ - clock *= 2; - setPLL(pScrn, bios, NV_PRAMDAC_MPLL_COEFF, clock); - - return true; -} - -static bool init_configure_preinit(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CONFIGURE_PREINIT opcode: 0x68 ('h') - * - * offset (8 bit): opcode - * - * Equivalent to INIT_DONE on bios version 3 or greater. - * For early bios versions, does early init, loading ram and crystal - * configuration from straps into CR3C - */ - - /* no iexec->execute check by design */ - - uint32_t straps = bios_rd32(pScrn, NV_PEXTDEV_BOOT_0); - uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); - - if (bios->major_version > 2) - return false; - - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX, cr3c); - - return true; -} - -static bool init_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO opcode: 0x69 ('i') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): mask - * offset + 4 (8 bit): data - * - * Assign ((IOVAL("crtc port") & "mask") | "data") to "crtc port" - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t mask = bios->data[offset + 3]; - uint8_t data = bios->data[offset + 4]; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n", - offset, crtcport, mask, data); - - bios_port_wr(pScrn, crtcport, (bios_port_rd(pScrn, crtcport) & mask) | data); - - return true; -} - -static bool init_sub(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_SUB opcode: 0x6B ('k') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): script number - * - * Execute script number "script number", as a subroutine - */ - - uint8_t sub = bios->data[offset + 1]; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Calling script %d\n", offset, sub); - - parse_init_table(pScrn, bios, - ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]), - iexec); - - BIOSLOG(pScrn, "0x%04X: End of script %d\n", offset, sub); - - return true; -} - -static bool init_ram_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_RAM_CONDITION opcode: 0x6D ('m') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): mask - * offset + 2 (8 bit): cmpval - * - * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval". - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t mask = bios->data[offset + 1]; - uint8_t cmpval = bios->data[offset + 2]; - uint8_t data; - - if (!iexec->execute) - return true; - - data = bios_rd32(pScrn, NV_PFB_BOOT_0) & mask; - - BIOSLOG(pScrn, "0x%04X: Checking if 0x%08X equals 0x%08X\n", offset, data, cmpval); - - if (data == cmpval) - BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return true; -} - -static bool init_nv_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_NV_REG opcode: 0x6E ('n') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): mask - * offset + 9 (32 bit): data - * - * Assign ((REGVAL("register") & "mask") | "data") to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t mask = ROM32(bios->data[offset + 5]); - uint32_t data = ROM32(bios->data[offset + 9]); - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n", offset, reg, mask, data); - - bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data); - - return true; -} - -static bool init_macro(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_MACRO opcode: 0x6F ('o') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): macro number - * - * Look up macro index "macro number" in the macro index table. - * The macro index table entry has 1 byte for the index in the macro table, - * and 1 byte for the number of times to repeat the macro. - * The macro table entry has 4 bytes for the register address and - * 4 bytes for the value to write to that register - */ - - uint8_t macro_index_tbl_idx = bios->data[offset + 1]; - uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE); - uint8_t macro_tbl_idx = bios->data[tmp]; - uint8_t count = bios->data[tmp + 1]; - uint32_t reg, data; - int i; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, Count: 0x%02X\n", - offset, macro_index_tbl_idx, macro_tbl_idx, count); - - for (i = 0; i < count; i++) { - uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE; - - reg = ROM32(bios->data[macroentryptr]); - data = ROM32(bios->data[macroentryptr + 4]); - - bios_wr32(pScrn, reg, data); - } - - return true; -} - -static bool init_done(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_DONE opcode: 0x71 ('q') - * - * offset (8 bit): opcode - * - * End the current script - */ - - /* mild retval abuse to stop parsing this table */ - return false; -} - -static bool init_resume(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_RESUME opcode: 0x72 ('r') - * - * offset (8 bit): opcode - * - * End the current execute / no-execute condition - */ - - if (iexec->execute) - return true; - - iexec->execute = true; - BIOSLOG(pScrn, "0x%04X: ---- Executing following commands ----\n", offset); - - return true; -} - -static bool init_time(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_TIME opcode: 0x74 ('t') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): time - * - * Sleep for "time" microseconds. - */ - - uint16_t time = ROM16(bios->data[offset + 1]); - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Sleeping for 0x%04X microseconds\n", offset, time); - - BIOS_USLEEP(time); - - return true; -} - -static bool init_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_CONDITION opcode: 0x75 ('u') - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Condition: 0x%02X\n", offset, cond); - - if (bios_condition_met(pScrn, bios, offset, cond)) - BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return true; -} - -static bool init_io_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_IO_CONDITION opcode: 0x76 - * - * offset (8 bit): opcode - * offset + 1 (8 bit): condition number - * - * Check condition "condition number" in the io condition table. - * If condition not met skip subsequent opcodes until condition is - * inverted (INIT_NOT), or we hit INIT_RESUME - */ - - uint8_t cond = bios->data[offset + 1]; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: IO condition: 0x%02X\n", offset, cond); - - if (io_condition_met(pScrn, bios, offset, cond)) - BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); - else { - BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset); - iexec->execute = false; - } - - return true; -} - -static bool init_index_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_INDEX_IO opcode: 0x78 ('x') - * - * offset (8 bit): opcode - * offset + 1 (16 bit): CRTC port - * offset + 3 (8 bit): CRTC index - * offset + 4 (8 bit): mask - * offset + 5 (8 bit): data - * - * Read value at index "CRTC index" on "CRTC port", AND with "mask", OR with "data", write-back - */ - - uint16_t crtcport = ROM16(bios->data[offset + 1]); - uint8_t crtcindex = bios->data[offset + 3]; - uint8_t mask = bios->data[offset + 4]; - uint8_t data = bios->data[offset + 5]; - uint8_t value; - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", - offset, crtcport, crtcindex, mask, data); - - value = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) | data; - bios_idxprt_wr(pScrn, crtcport, crtcindex, value); - - return true; -} - -static bool init_pll(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_PLL opcode: 0x79 ('y') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (16 bit): freq - * - * Set PLL register "register" to coefficients for frequency (10kHz) "freq" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint16_t freq = ROM16(bios->data[offset + 5]); - - if (!iexec->execute) - return true; - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); - - setPLL(pScrn, bios, reg, freq * 10); - - return true; -} - -static bool init_zm_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_REG opcode: 0x7A ('z') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): register - * offset + 5 (32 bit): value - * - * Assign "value" to "register" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint32_t value = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return true; - - bios_wr32(pScrn, reg, value); - - return true; -} - -static bool init_8e(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_8E opcode: 0x8E ('') - * - * offset (8 bit): opcode - * - * The purpose of this opcode is unclear (being for nv50 cards), and - * the literal functionality can be seen in the code below. - * - * A brief synopsis is that for each entry in a table pointed to by the - * DCB table header, depending on the settings of various bits, various - * other bits in registers 0xe100, 0xe104, and 0xe108, are set or - * cleared. - */ - - uint8_t headerlen = bios->data[bios->bdcb.init8e_table_ptr + 1]; - uint8_t entries = bios->data[bios->bdcb.init8e_table_ptr + 2]; - uint8_t recordlen = bios->data[bios->bdcb.init8e_table_ptr + 3]; - int i; - - if (bios->bdcb.version != 0x40) { - NV_ERROR(pScrn, "DCB table not version 4.0\n"); - return false; - } - if (!bios->bdcb.init8e_table_ptr) { - NV_WARN(pScrn, "Invalid pointer to INIT_8E table\n"); - return false; - } - - for (i = 0; i < entries; i++) { - uint32_t entry = ROM32(bios->data[bios->bdcb.init8e_table_ptr + headerlen + recordlen * i]); - int shift = (entry & 0x1f) * 4; - uint32_t mask; - uint32_t reg = 0xe104; - uint32_t data; - - if ((entry & 0xff00) == 0xff00) - continue; - - if (shift >= 32) { - reg += 4; - shift -= 32; - } - shift %= 32; - - mask = ~(3 << shift); - if (entry & (1 << 24)) - data = (entry >> 21); - else - data = (entry >> 19); - data = ((data & 3) ^ 2) << shift; - - BIOSLOG(pScrn, "0x%04X: Entry: 0x%08X, Reg: 0x%08X, Shift: 0x%02X, Mask: 0x%08X, Data: 0x%08X\n", - offset, entry, reg, shift, mask, data); - - bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data); - - reg = 0xe100; - shift = entry & 0x1f; - - mask = ~(1 << 16 | 1); - mask = mask << shift | mask >> (32 - shift); - data = 0; - if ((entry & (3 << 25)) == (1 << 25)) - data |= 1; - if ((entry & (3 << 25)) == (2 << 25)) - data |= 0x10000; - data <<= shift; - - BIOSLOG(pScrn, "0x%04X: Entry: 0x%08X, Reg: 0x%08X, Shift: 0x%02X, Mask: 0x%08X, Data: 0x%08X\n", - offset, entry, reg, shift, mask, data); - - bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data); - } - - return true; -} - -/* hack to avoid moving the itbl_entry array before this function */ -int init_ram_restrict_zm_reg_group_blocklen = 0; - -static bool init_ram_restrict_zm_reg_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_RAM_RESTRICT_ZM_REG_GROUP opcode: 0x8F ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): reg - * offset + 5 (8 bit): regincrement - * offset + 6 (8 bit): count - * offset + 7 (32 bit): value 1,1 - * ... - * - * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at - * ram_restrict_table_ptr. The value read from here is 'n', and - * "value 1,n" gets written to "reg". This repeats "count" times and on - * each iteration 'm', "reg" increases by "regincrement" and - * "value m,n" is used. The extent of n is limited by a number read - * from the 'M' BIT table, herein called "blocklen" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t regincrement = bios->data[offset + 5]; - uint8_t count = bios->data[offset + 6]; - uint32_t strap_ramcfg, data; - uint16_t blocklen; - uint8_t index; - int i; - - /* previously set by 'M' BIT table */ - blocklen = init_ram_restrict_zm_reg_group_blocklen; - - if (!iexec->execute) - return true; - - if (!blocklen) { - NV_ERROR(pScrn, "0x%04X: Zero block length - has the M table " - "been parsed?\n", offset); - return false; - } - - strap_ramcfg = (bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; - index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg]; - - BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n", - offset, reg, regincrement, count, strap_ramcfg, index); - - for (i = 0; i < count; i++) { - data = ROM32(bios->data[offset + 7 + index * 4 + blocklen * i]); - - bios_wr32(pScrn, reg, data); - - reg += regincrement; - } - - return true; -} - -static bool init_copy_zm_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_COPY_ZM_REG opcode: 0x90 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): src reg - * offset + 5 (32 bit): dst reg - * - * Put contents of "src reg" into "dst reg" - */ - - uint32_t srcreg = ROM32(bios->data[offset + 1]); - uint32_t dstreg = ROM32(bios->data[offset + 5]); - - if (!iexec->execute) - return true; - - bios_wr32(pScrn, dstreg, bios_rd32(pScrn, srcreg)); - - return true; -} - -static bool init_zm_reg_group_addr_latched(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_ZM_REG_GROUP_ADDRESS_LATCHED opcode: 0x91 ('') - * - * offset (8 bit): opcode - * offset + 1 (32 bit): dst reg - * offset + 5 (8 bit): count - * offset + 6 (32 bit): data 1 - * ... - * - * For each of "count" values write "data n" to "dst reg" - */ - - uint32_t reg = ROM32(bios->data[offset + 1]); - uint8_t count = bios->data[offset + 5]; - int i; - - if (!iexec->execute) - return true; - - for (i = 0; i < count; i++) { - uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]); - bios_wr32(pScrn, reg, data); - } - - return true; -} - -static bool init_reserved(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec) -{ - /* INIT_RESERVED opcode: 0x92 ('') - * - * offset (8 bit): opcode - * - * Seemingly does nothing - */ - - return true; -} - -static init_tbl_entry_t itbl_entry[] = { - /* command name , id , length , offset , mult , command handler */ - /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ - { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog }, - { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat }, - { "INIT_IO_RESTRICT_PLL" , 0x34, 12 , 7 , 2 , init_io_restrict_pll }, - { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat }, - { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy }, - { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not }, - { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition }, - { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, 18 , 17 , 2 , init_idx_addr_latched }, - { "INIT_IO_RESTRICT_PLL2" , 0x4A, 11 , 6 , 4 , init_io_restrict_pll2 }, - { "INIT_PLL2" , 0x4B, 9 , 0 , 0 , init_pll2 }, - { "INIT_I2C_BYTE" , 0x4C, 4 , 3 , 3 , init_i2c_byte }, - { "INIT_ZM_I2C_BYTE" , 0x4D, 4 , 3 , 2 , init_zm_i2c_byte }, - { "INIT_ZM_I2C" , 0x4E, 4 , 3 , 1 , init_zm_i2c }, - { "INIT_TMDS" , 0x4F, 5 , 0 , 0 , init_tmds }, - { "INIT_ZM_TMDS_GROUP" , 0x50, 3 , 2 , 2 , init_zm_tmds_group }, - { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch }, - { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr }, - { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr }, - { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group }, - { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time }, - { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence }, - /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ - { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct }, - { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg }, - { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io }, - { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem }, - { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset }, - { "INIT_CONFIGURE_MEM" , 0x66, 1 , 0 , 0 , init_configure_mem }, - { "INIT_CONFIGURE_CLK" , 0x67, 1 , 0 , 0 , init_configure_clk }, - { "INIT_CONFIGURE_PREINIT" , 0x68, 1 , 0 , 0 , init_configure_preinit }, - { "INIT_IO" , 0x69, 5 , 0 , 0 , init_io }, - { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub }, - { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition }, - { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg }, - { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro }, - { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done }, - { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume }, - /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */ - { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time }, - { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition }, - { "INIT_IO_CONDITION" , 0x76, 2 , 0 , 0 , init_io_condition }, - { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io }, - { "INIT_PLL" , 0x79, 7 , 0 , 0 , init_pll }, - { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg }, - { "INIT_8E" , 0x8E, 1 , 0 , 0 , init_8e }, - /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */ - { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, 7 , 6 , 0 , init_ram_restrict_zm_reg_group }, - { "INIT_COPY_ZM_REG" , 0x90, 9 , 0 , 0 , init_copy_zm_reg }, - { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6 , 5 , 4 , init_zm_reg_group_addr_latched }, - { "INIT_RESERVED" , 0x92, 1 , 0 , 0 , init_reserved }, - { 0 , 0 , 0 , 0 , 0 , 0 } -}; - -static unsigned int get_init_table_entry_length(struct nvbios *bios, unsigned int offset, int i) -{ - /* Calculates the length of a given init table entry. */ - return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier; -} - -#define MAX_TABLE_OPS 1000 - -static int parse_init_table(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset, init_exec_t *iexec) -{ - /* Parses all commands in an init table. - * - * We start out executing all commands found in the init table. Some - * opcodes may change the status of iexec->execute to SKIP, which will - * cause the following opcodes to perform no operation until the value - * is changed back to EXECUTE. - */ - - int count = 0, i; - uint8_t id; - - /* Loop until INIT_DONE causes us to break out of the loop - * (or until offset > bios length just in case... ) - * (and no more than MAX_TABLE_OPS iterations, just in case... ) */ - while ((offset < bios->length) && (count++ < MAX_TABLE_OPS)) { - id = bios->data[offset]; - - /* Find matching id in itbl_entry */ - for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++) - ; - - if (itbl_entry[i].name) { - BIOSLOG(pScrn, "0x%04X: [ (0x%02X) - %s ]\n", - offset, itbl_entry[i].id, itbl_entry[i].name); - - /* execute eventual command handler */ - if (itbl_entry[i].handler) - if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec)) - break; - } else { - NV_ERROR(pScrn, "0x%04X: Init table command not found: " - "0x%02X\n", offset, id); - return -ENOENT; - } - - /* Add the offset of the current command including all data - * of that command. The offset will then be pointing on the - * next op code. - */ - offset += get_init_table_entry_length(bios, offset, i); - } - - if (offset >= bios->length) - NV_WARN(pScrn, - "Offset 0x%04X greater than known bios image length. " - "Corrupt image?\n", offset); - if (count >= MAX_TABLE_OPS) - NV_WARN(pScrn, "More than %d opcodes to a table is unlikely, " - "is the bios image corrupt?\n", MAX_TABLE_OPS); - - return 0; -} - -static void parse_init_tables(ScrnInfoPtr pScrn, struct nvbios *bios) -{ - /* Loops and calls parse_init_table() for each present table. */ - - int i = 0; - uint16_t table; - init_exec_t iexec = {true, false}; - - if (bios->old_style_init) { - if (bios->init_script_tbls_ptr) - parse_init_table(pScrn, bios, bios->init_script_tbls_ptr, &iexec); - if (bios->extra_init_script_tbl_ptr) - parse_init_table(pScrn, bios, bios->extra_init_script_tbl_ptr, &iexec); - - return; - } - - while ((table = ROM16(bios->data[bios->init_script_tbls_ptr + i]))) { - NV_INFO(pScrn, "Parsing VBIOS init table %d at offset 0x%04X\n", - i / 2, table); - BIOSLOG(pScrn, "0x%04X: ------ Executing following commands ------\n", table); - - parse_init_table(pScrn, bios, table, &iexec); - i += 2; - } -} - -static void link_head_and_output(NVPtr pNv, struct dcb_entry *dcbent, int head, bool dl) -{ - /* The BIOS scripts don't do this for us, sadly - * Luckily we do know the values ;-) - * - * head < 0 indicates we wish to force a setting with the overrideval - * (for VT restore etc.) - */ - - int ramdac = (dcbent->or & OUTPUT_C) >> 2; - uint8_t tmds04 = 0x80; - - if (head != ramdac) - tmds04 = 0x88; - - if (dcbent->type == OUTPUT_LVDS) - tmds04 |= 0x01; - - nv_write_tmds(pNv, dcbent->or, 0, 0x04, tmds04); - - if (dl) /* dual link */ - nv_write_tmds(pNv, dcbent->or, 1, 0x04, tmds04 ^ 0x08); -} - -static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk) -{ - int compare_record_len, i = 0; - uint16_t compareclk, scriptptr = 0; - - if (bios->major_version < 5) /* pre BIT */ - compare_record_len = 3; - else - compare_record_len = 4; - - do { - compareclk = ROM16(bios->data[clktable + compare_record_len * i]); - if (pxclk >= compareclk * 10) { - if (bios->major_version < 5) { - uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i]; - scriptptr = ROM16(bios->data[bios->init_script_tbls_ptr + tmdssub * 2]); - } else - scriptptr = ROM16(bios->data[clktable + 2 + compare_record_len * i]); - break; - } - i++; - } while (compareclk); - - return scriptptr; -} - -static void run_digital_op_script(ScrnInfoPtr pScrn, uint16_t scriptptr, struct dcb_entry *dcbent, int head, bool dl) -{ - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - init_exec_t iexec = {true, false}; - - NV_TRACE(pScrn, "0x%04X: Parsing digital output script table\n", - scriptptr); - bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_44, - head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA); - /* note: if dcb entries have been merged, index may be misleading */ - NVWriteVgaCrtc5758(NVPTR(pScrn), head, 0, dcbent->index); - parse_init_table(pScrn, bios, scriptptr, &iexec); - - link_head_and_output(NVPTR(pScrn), dcbent, head, dl); -} - -static int call_lvds_manufacturer_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script) -{ - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0); - uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]); - - if (!bios->fp.xlated_entry || !sub || !scriptofs) - return -EINVAL; - - run_digital_op_script(pScrn, scriptofs, dcbent, head, bios->fp.dual_link); - - if (script == LVDS_PANEL_OFF) - /* off-on delay in ms */ - BIOS_USLEEP(ROM16(bios->data[bios->fp.xlated_entry + 7])); -#ifdef __powerpc__ - /* Powerbook specific quirks */ - if (script == LVDS_RESET && ((pNv->Chipset & 0xffff) == 0x0179 || (pNv->Chipset & 0xffff) == 0x0329)) - nv_write_tmds(pNv, dcbent->or, 0, 0x02, 0x72); - if ((pNv->Chipset & 0xffff) == 0x0179 || (pNv->Chipset & 0xffff) == 0x0189 || (pNv->Chipset & 0xffff) == 0x0329) { - if (script == LVDS_PANEL_ON) { - bios_wr32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31)); - bios_wr32(pScrn, NV_PCRTC_GPIO_EXT, bios_rd32(pScrn, NV_PCRTC_GPIO_EXT) | 1); - } - if (script == LVDS_PANEL_OFF) { - bios_wr32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31)); - bios_wr32(pScrn, NV_PCRTC_GPIO_EXT, bios_rd32(pScrn, NV_PCRTC_GPIO_EXT) & ~3); - } - } -#endif - - return 0; -} - -static int run_lvds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) -{ - /* The BIT LVDS table's header has the information to setup the - * necessary registers. Following the standard 4 byte header are: - * A bitmask byte and a dual-link transition pxclk value for use in - * selecting the init script when not using straps; 4 script pointers - * for panel power, selected by output and on/off; and 8 table pointers - * for panel init, the needed one determined by output, and bits in the - * conf byte. These tables are similar to the TMDS tables, consisting - * of a list of pxclks and script pointers. - */ - - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - unsigned int outputset = (dcbent->or == 4) ? 1 : 0; - uint16_t scriptptr = 0, clktable; - uint8_t clktableptr = 0; - - /* for now we assume version 3.0 table - g80 support will need some changes */ - - switch (script) { - case LVDS_INIT: - return -ENOSYS; - case LVDS_BACKLIGHT_ON: - case LVDS_PANEL_ON: - scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]); - break; - case LVDS_BACKLIGHT_OFF: - case LVDS_PANEL_OFF: - scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]); - break; - case LVDS_RESET: - if (dcbent->lvdsconf.use_straps_for_mode) { - if (bios->fp.dual_link) - clktableptr += 2; - if (bios->fp.BITbit1) - clktableptr++; - } else { - /* using EDID */ - uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4]; - int fallbackcmpval = (dcbent->or == 4) ? 4 : 1; - - if (bios->fp.dual_link) { - clktableptr += 2; - fallbackcmpval *= 2; - } - if (fallbackcmpval & fallback) - clktableptr++; - } - - /* adding outputset * 8 may not be correct */ - clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]); - if (!clktable) { - NV_ERROR(pScrn, "Pixel clock comparison table not found\n"); - return -ENOENT; - } - scriptptr = clkcmptable(bios, clktable, pxclk); - } - - if (!scriptptr) { - NV_ERROR(pScrn, "LVDS output init script not found\n"); - return -ENOENT; - } - run_digital_op_script(pScrn, scriptptr, dcbent, head, bios->fp.dual_link); - - return 0; -} - -int call_lvds_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk) -{ - /* LVDS operations are multiplexed in an effort to present a single API - * which works with two vastly differing underlying structures. - * This acts as the demux - */ - - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; - uint32_t sel_clk_binding, sel_clk; - int ret; - - if (bios->fp.last_script_invoc == (script << 1 | head) || !lvds_ver || - (lvds_ver >= 0x30 && script == LVDS_INIT)) - return 0; - - if (!bios->fp.lvds_init_run) { - bios->fp.lvds_init_run = true; - call_lvds_script(pScrn, dcbent, head, LVDS_INIT, pxclk); - } - - if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change) - call_lvds_script(pScrn, dcbent, head, LVDS_RESET, pxclk); - if (script == LVDS_RESET && bios->fp.power_off_for_reset) - call_lvds_script(pScrn, dcbent, head, LVDS_PANEL_OFF, pxclk); - - NV_TRACE(pScrn, "Calling LVDS script %d:\n", script); - - /* don't let script change pll->head binding */ - sel_clk_binding = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK) & 0x50000; - - if (lvds_ver < 0x30) - ret = call_lvds_manufacturer_script(pScrn, dcbent, head, script); - else - ret = run_lvds_table(pScrn, dcbent, head, script, pxclk); - - bios->fp.last_script_invoc = (script << 1 | head); - - sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); - /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */ - nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0); - - return ret; -} - -struct lvdstableheader { - uint8_t lvds_ver, headerlen, recordlen; -}; - -static int parse_lvds_manufacturer_table_header(ScrnInfoPtr pScrn, struct nvbios *bios, struct lvdstableheader *lth) -{ - /* BMP version (0xa) LVDS table has a simple header of version and - * record length. The BIT LVDS table has the typical BIT table header: - * version byte, header length byte, record length byte, and a byte for - * the maximum number of records that can be held in the table */ - - uint8_t lvds_ver, headerlen, recordlen; - - memset(lth, 0, sizeof(struct lvdstableheader)); - - if (bios->fp.lvdsmanufacturerpointer == 0x0) { - NV_ERROR(pScrn, "Pointer to LVDS manufacturer table invalid\n"); - return -EINVAL; - } - - lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; - - switch (lvds_ver) { - case 0x0a: /* pre NV40 */ - headerlen = 2; - recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; - break; - case 0x30: /* NV4x */ - headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; - if (headerlen < 0x1f) { - NV_ERROR(pScrn, "LVDS table header not understood\n"); - return -EINVAL; - } - recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; - break; - case 0x40: /* G80/G90 */ - headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; - if (headerlen < 0x7) { - NV_ERROR(pScrn, "LVDS table header not understood\n"); - return -EINVAL; - } - recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; - break; - default: - NV_ERROR(pScrn, - "LVDS table revision %d.%d not currently supported\n", - lvds_ver >> 4, lvds_ver & 0xf); - return -ENOSYS; - } - - lth->lvds_ver = lvds_ver; - lth->headerlen = headerlen; - lth->recordlen = recordlen; - - return 0; -} - -static int get_fp_strap(ScrnInfoPtr pScrn, struct nvbios *bios) -{ - /* the fp strap is normally dictated by the "User Strap" in - * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the - * Internal_Flags struct at 0x48 is set, the user strap gets overriden - * by the PCI subsystem ID during POST, but not before the previous user - * strap has been committed to CR58 for CR57=0xf on head A, which may be - * read and used instead - */ - NVPtr pNv = NVPTR(pScrn); - - if (bios->major_version < 5 && bios->data[0x48] & 0x4) - return (NVReadVgaCrtc5758(NVPTR(pScrn), 0, 0xf) & 0xf); - - if (pNv->Architecture >= NV_ARCH_50) - return ((bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 24) & 0xf); - else - return ((bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 16) & 0xf); -} - -static int parse_fp_mode_table(ScrnInfoPtr pScrn, struct nvbios *bios) -{ - uint8_t *fptable; - uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex; - int ret, ofs, fpstrapping; - struct lvdstableheader lth; - - if (bios->fp.fptablepointer == 0x0) { - /* Apple cards don't have the fp table; the laptops use DDC */ - /* The table is also missing on some x86 IGPs */ -#ifndef __powerpc__ - NV_WARN(pScrn, "Pointer to flat panel table invalid\n"); -#endif - bios->pub.digital_min_front_porch = 0x4b; - return 0; - } - - fptable = &bios->data[bios->fp.fptablepointer]; - fptable_ver = fptable[0]; - - switch (fptable_ver) { - /* BMP version 0x5.0x11 BIOSen have version 1 like tables, but no version field, - * and miss one of the spread spectrum/PWM bytes. - * This could affect early GF2Go parts (not seen any appropriate ROMs though). - * Here we assume that a version of 0x05 matches this case (combining with a - * BMP version check would be better), as the common case for the panel type - * field is 0x0005, and that is in fact what we are reading the first byte of. */ - case 0x05: /* some NV10, 11, 15, 16 */ - recordlen = 42; - ofs = -1; - break; - case 0x10: /* some NV15/16, and NV11+ */ - recordlen = 44; - ofs = 0; - break; - case 0x20: /* NV40+ */ - headerlen = fptable[1]; - recordlen = fptable[2]; - fpentries = fptable[3]; - /* fptable[4] is the minimum RAMDAC_FP_HCRTC->RAMDAC_FP_HSYNC_START gap */ - bios->pub.digital_min_front_porch = fptable[4]; - ofs = -7; - break; - default: - NV_ERROR(pScrn, - "FP table revision %d.%d not currently supported\n", - fptable_ver >> 4, fptable_ver & 0xf); - return -ENOSYS; - } - - if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */ - return 0; - - if ((ret = parse_lvds_manufacturer_table_header(pScrn, bios, <h))) - return ret; - - if (lth.lvds_ver == 0x30 || lth.lvds_ver == 0x40) { - bios->fp.fpxlatetableptr = bios->fp.lvdsmanufacturerpointer + lth.headerlen + 1; - bios->fp.xlatwidth = lth.recordlen; - } - if (bios->fp.fpxlatetableptr == 0x0) { - NV_ERROR(pScrn, "Pointer to flat panel xlat table invalid\n"); - return -EINVAL; - } - - fpstrapping = get_fp_strap(pScrn, bios); - - fpindex = bios->data[bios->fp.fpxlatetableptr + fpstrapping * bios->fp.xlatwidth]; - - if (fpindex > fpentries) { - NV_ERROR(pScrn, "Bad flat panel table index\n"); - return -ENOENT; - } - - /* nv4x cards need both a strap value and fpindex of 0xf to use DDC */ - if (lth.lvds_ver > 0x10) - bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf; - - /* if either the strap or xlated fpindex value are 0xf there is no - * panel using a strap-derived bios mode present. this condition - * includes, but is different from, the DDC panel indicator above - */ - if (fpstrapping == 0xf || fpindex == 0xf) - return 0; - - bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen + - recordlen * fpindex + ofs; - - NV_TRACE(pScrn, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", - ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1, - ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1, - ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10); - - return 0; -} - -bool nouveau_bios_fp_mode(ScrnInfoPtr pScrn, DisplayModeRec *mode) -{ - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr]; - - if (!mode) /* just checking whether we can produce a mode */ - return bios->fp.mode_ptr; - - memset(mode, 0, sizeof(DisplayModeRec)); - /* for version 1.0 (version in byte 0): - * bytes 1-2 are "panel type", including bits on whether Colour/mono, - * single/dual link, and type (TFT etc.) - * bytes 3-6 are bits per colour in RGBX */ - mode->Clock = ROM16(mode_entry[7]) * 10; - /* bytes 9-10 is HActive */ - mode->HDisplay = ROM16(mode_entry[11]) + 1; - /* bytes 13-14 is HValid Start - * bytes 15-16 is HValid End */ - mode->HSyncStart = ROM16(mode_entry[17]) + 1; - mode->HSyncEnd = ROM16(mode_entry[19]) + 1; - mode->HTotal = ROM16(mode_entry[21]) + 1; - /* bytes 23-24, 27-30 similarly, but vertical */ - mode->VDisplay = ROM16(mode_entry[25]) + 1; - mode->VSyncStart = ROM16(mode_entry[31]) + 1; - mode->VSyncEnd = ROM16(mode_entry[33]) + 1; - mode->VTotal = ROM16(mode_entry[35]) + 1; - mode->Flags |= (mode_entry[37] & 0x10) ? V_PHSYNC : V_NHSYNC; - mode->Flags |= (mode_entry[37] & 0x1) ? V_PVSYNC : V_NVSYNC; - /* bytes 38-39 relate to spread spectrum settings - * bytes 40-43 are something to do with PWM */ - - return bios->fp.mode_ptr; -} - -int nouveau_bios_parse_lvds_table(ScrnInfoPtr pScrn, int pxclk, bool *dl, bool *if_is_24bit) -{ - /* The LVDS table header is (mostly) described in - * parse_lvds_manufacturer_table_header(): the BIT header additionally - * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if - * straps are not being used for the panel, this specifies the frequency - * at which modes should be set up in the dual link style. - * - * Following the header, the BMP (ver 0xa) table has several records, - * indexed by a seperate xlat table, indexed in turn by the fp strap in - * EXTDEV_BOOT. Each record had a config byte, followed by 6 script - * numbers for use by INIT_SUB which controlled panel init and power, - * and finally a dword of ms to sleep between power off and on - * operations. - * - * In the BIT versions, the table following the header serves as an - * integrated config and xlat table: the records in the table are - * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has - * two bytes - the first as a config byte, the second for indexing the - * fp mode table pointed to by the BIT 'D' table - * - * DDC is not used until after card init, so selecting the correct table - * entry and setting the dual link flag for EDID equipped panels, - * requiring tests against the native-mode pixel clock, cannot be done - * until later, when this function should be called with non-zero pxclk - */ - - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - int fpstrapping = get_fp_strap(pScrn, bios), lvdsmanufacturerindex = 0; - struct lvdstableheader lth; - uint16_t lvdsofs; - int ret, chip_version = bios->pub.chip_version; - - if ((ret = parse_lvds_manufacturer_table_header(pScrn, bios, <h))) - return ret; - - switch (lth.lvds_ver) { - case 0x0a: /* pre NV40 */ - lvdsmanufacturerindex = bios->data[bios->fp.fpxlatemanufacturertableptr + fpstrapping]; - - /* we're done if this isn't the EDID panel case */ - if (!pxclk) - break; - - if (chip_version < 0x25) { - /* nv17 behaviour */ - /* it seems the old style lvds script pointer is reused - * to select 18/24 bit colour depth for EDID panels */ - lvdsmanufacturerindex = (bios->legacy.lvds_single_a_script_ptr & 1) ? 2 : 0; - if (pxclk >= bios->fp.duallink_transition_clk) - lvdsmanufacturerindex++; - } else if (chip_version < 0x30) { - /* nv28 behaviour (off-chip encoder) */ - /* nv28 does a complex dance of first using byte 121 of - * the EDID to choose the lvdsmanufacturerindex, then - * later attempting to match the EDID manufacturer and - * product IDs in a table (signature 'pidt' (panel id - * table?)), setting an lvdsmanufacturerindex of 0 and - * an fp strap of the match index (or 0xf if none) - */ - lvdsmanufacturerindex = 0; - } else { - /* nv31, nv34 behaviour */ - lvdsmanufacturerindex = 0; - if (pxclk >= bios->fp.duallink_transition_clk) - lvdsmanufacturerindex = 2; - if (pxclk >= 140000) - lvdsmanufacturerindex = 3; - } - - /* nvidia set the high nibble of (cr57=f, cr58) to - * lvdsmanufacturerindex in this case; we don't */ - break; - case 0x30: /* NV4x */ - case 0x40: /* G80/G90 */ - lvdsmanufacturerindex = fpstrapping; - break; - default: - NV_ERROR(pScrn, "LVDS table revision not currently supported\n"); - return -ENOSYS; - } - - lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex; - switch (lth.lvds_ver) { - case 0x0a: - bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1; - bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2; - bios->fp.dual_link = bios->data[lvdsofs] & 4; - bios->fp.link_c_increment = bios->data[lvdsofs] & 8; - *if_is_24bit = bios->data[lvdsofs] & 16; - break; - case 0x30: - /* My money would be on there being a 24 bit interface bit in this table, - * but I have no example of a laptop bios with a 24 bit panel to confirm that. - * Hence we shout loudly if any bit other than bit 0 is set (I've not even - * seen bit 1) - */ - if (bios->data[lvdsofs] > 1) - NV_ERROR(pScrn, - "You have a very unusual laptop display; please report it\n"); - /* no sign of the "power off for reset" or "reset for panel on" bits, but it's safer to assume we should */ - bios->fp.power_off_for_reset = true; - bios->fp.reset_after_pclk_change = true; - /* it's ok lvdsofs is wrong for nv4x edid case; dual_link is - * over-written, and BITbit1 isn't used */ - bios->fp.dual_link = bios->data[lvdsofs] & 1; - bios->fp.BITbit1 = bios->data[lvdsofs] & 2; - bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; -#if 0 // currently unused - break; - case 0x40: - /* fairly sure, but not 100% */ - bios->fp.dual_link = bios->data[lvdsofs] & 1; - bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10; - break; -#endif - } - - /* set dual_link flag for EDID case */ - if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) - bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk); - - *dl = bios->fp.dual_link; - - return 0; -} - -static int -find_script_pointers(ScrnInfoPtr pScrn, uint8_t *table, uint16_t *script0, - uint16_t *script1, uint16_t headerlen, int pxclk) -{ - /* The output script tables describing a particular output type - * look as follows: - * - * offset + 0 (32 bits): output this table matches (hash of DCB) - * offset + 4 ( 8 bits): unknown - * offset + 5 ( 8 bits): number of configurations - * offset + 6 (16 bits): pointer to some script - * offset + 8 (16 bits): pointer to some script - * - * headerlen == 10 - * offset + 10 : configuration 0 - * - * headerlen == 12 - * offset + 10 : pointer to some script - * offset + 12 : configuration 0 - * - * Each config entry is as follows: - * - * offset + 0 (16 bits): unknown, assumed to be a match value - * offset + 2 (16 bits): pointer to script table (clock set?) - * offset + 4 (16 bits): pointer to script table (reset?) - * - * There doesn't appear to be a count value to say how many - * entries exist in each script table, instead, a 0 value in - * the first 16-bit word seems to indicate both the end of the - * list and the default entry. The second 16-bit word in the - * script tables is a pointer to the script to execute. - */ - - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - int i, cmpval = 0x0100; - - *script0 = *script1 = 0; - for (i = 0; i < table[5]; i++) { - uint16_t offset; - - if (ROM16(table[headerlen + i*6 + 0]) != cmpval) - continue; - - offset = ROM16(table[headerlen + i*6 + 2]); - if (offset) - *script0 = clkcmptable(bios, offset, pxclk); - - if (!*script0) - NV_WARN(pScrn, "script0 missing!\n"); - - offset = ROM16(table[headerlen + i*6 + 4]); - if (offset) - *script1 = clkcmptable(bios, offset, pxclk); - - return 0; - } - - NV_ERROR(pScrn, "couldn't find suitable output scripts\n"); - return 1; -} - -int -nouveau_bios_run_display_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, - int pxclk) -{ - /* The display script table is located by the BIT 'U' table. - * - * It contains an array of pointers to various tables describing - * a particular output type. The first 32-bits of the output - * tables contains similar information to a DCB entry, and is - * used to decide whether that particular table is suitable for - * the output you want to access. - * - * The "record header length" field here seems to indicate the - * offset of the first configuration entry in the output tables. - * This is 10 on most cards I've seen, but 12 has been witnessed - * on DP cards, and there's another script pointer within the - * header. - * - * offset + 0 ( 8 bits): version - * offset + 1 ( 8 bits): header length - * offset + 2 ( 8 bits): record length - * offset + 3 ( 8 bits): number of records - * offset + 4 ( 8 bits): record header length - * offset + 5 (16 bits): pointer to first output script table - */ - - NVPtr pNv = NVPTR(pScrn); - init_exec_t iexec = {true, false}; - struct nvbios *bios = &pNv->VBIOS; - uint8_t *table = &bios->data[bios->display.script_table_ptr]; - uint8_t *entry, *otable = NULL; - uint16_t script0, script1; - int i; - bool run_scripts = false; - - if (!bios->display.script_table_ptr) { - NV_ERROR(pScrn, "No pointer to output script table\n"); - return 1; - } - - if (table[0] != 0x20) { - NV_ERROR(pScrn, "Output script table version 0x%02x unknown\n", table[0]); - return 1; - } - - NV_DEBUG(pScrn, "Searching for output entry for %d %d %d\n", - dcbent->type, dcbent->location, dcbent->or); - entry = table + table[1]; - for (i = 0; i < table[3]; i++, entry += table[2]) { - uint32_t match; - - if (ROM16(entry[0]) == 0) - continue; - otable = &bios->data[ROM16(entry[0])]; - match = ROM32(otable[0]); - - NV_DEBUG(pScrn, " %d: 0x%08x\n", i, match); - if ((((match & 0x000f0000) >> 16) & dcbent->or) && - ((match & 0x0000000f) >> 0) == dcbent->type && - ((match & 0x000000f0) >> 4) == dcbent->location) - break; - } - - if (i == table[3]) { - NV_ERROR(pScrn, "Couldn't find matching output script table\n"); - return 1; - } - - if (find_script_pointers(pScrn, otable, &script0, &script1, table[4], pxclk)) - return 1; - bios->display.head = ffs(dcbent->or) - 1; - - if (script0) { - NV_TRACE(pScrn, "0x%04X: Parsing output Script0\n", script0); - if (run_scripts) - parse_init_table(pScrn, bios, script0, &iexec); - } - - if (script1) { - NV_TRACE(pScrn, "0x%04X: Parsing output Script1\n", script1); - if (run_scripts) - parse_init_table(pScrn, bios, script1, &iexec); - } - - return run_scripts ? 0 : 1; -} - -int run_tmds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, int pxclk) -{ - /* the pxclk parameter is in kHz - * - * This runs the TMDS regs setting code found on BIT bios cards - * - * For ffs(or) == 1 use the first table, for ffs(or) == 2 and - * ffs(or) == 3, use the second. - */ - - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - int cv = bios->pub.chip_version; - uint16_t clktable = 0, scriptptr; - uint32_t sel_clk_binding, sel_clk; - - /* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */ - if (cv >= 0x17 && cv != 0x1a && cv != 0x20 && - dcbent->location != DCB_LOC_ON_CHIP) - return 0; - - switch (ffs(dcbent->or)) { - case 1: - clktable = bios->tmds.output0_script_ptr; - break; - case 2: - case 3: - clktable = bios->tmds.output1_script_ptr; - break; - } - - if (!clktable) { - NV_ERROR(pScrn, "Pixel clock comparison table not found\n"); - return -EINVAL; - } - - scriptptr = clkcmptable(bios, clktable, pxclk); - - if (!scriptptr) { - NV_ERROR(pScrn, "TMDS output init script not found\n"); - return -ENOENT; - } - - /* don't let script change pll->head binding */ - sel_clk_binding = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK) & 0x50000; - run_digital_op_script(pScrn, scriptptr, dcbent, head, pxclk >= 165000); - sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); - - return 0; -} - -int get_pll_limits(ScrnInfoPtr pScrn, uint32_t limit_match, struct pll_lims *pll_lim) -{ - /* PLL limits table - * - * Version 0x10: NV30, NV31 - * One byte header (version), one record of 24 bytes - * Version 0x11: NV36 - Not implemented - * Seems to have same record style as 0x10, but 3 records rather than 1 - * Version 0x20: Found on Geforce 6 cards - * Trivial 4 byte BIT header. 31 (0x1f) byte record length - * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards - * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record - * length in general, some (integrated) have an extra configuration byte - * Version 0x30: Found on Geforce 8, separates the register mapping - * from the limits tables. - */ - - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - int cv = bios->pub.chip_version, pllindex = 0; - uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0; - uint32_t crystal_strap_mask, crystal_straps; - - if (!bios->pll_limit_tbl_ptr) { - if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 || - cv >= 0x40) { - NV_ERROR(pScrn, "Pointer to PLL limits table invalid\n"); - return -EINVAL; - } - } else - pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr]; - - crystal_strap_mask = 1 << 6; - /* open coded pNv->twoHeads test */ - if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20) - crystal_strap_mask |= 1 << 22; - crystal_straps = nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & crystal_strap_mask; - - switch (pll_lim_ver) { - /* we use version 0 to indicate a pre limit table bios (single stage pll) - * and load the hard coded limits instead */ - case 0: - break; - case 0x10: - case 0x11: /* strictly v0x11 has 3 entries, but the last two don't seem to get used */ - headerlen = 1; - recordlen = 0x18; - entries = 1; - pllindex = 0; - break; - case 0x20: - case 0x21: - case 0x30: - headerlen = bios->data[bios->pll_limit_tbl_ptr + 1]; - recordlen = bios->data[bios->pll_limit_tbl_ptr + 2]; - entries = bios->data[bios->pll_limit_tbl_ptr + 3]; - break; - default: - NV_ERROR(pScrn, "PLL limits table revision 0x%X not currently " - "supported\n", pll_lim_ver); - return -ENOSYS; - } - - /* initialize all members to zero */ - memset(pll_lim, 0, sizeof(struct pll_lims)); - - if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) { - uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex]; - - pll_lim->vco1.minfreq = ROM32(pll_rec[0]); - pll_lim->vco1.maxfreq = ROM32(pll_rec[4]); - pll_lim->vco2.minfreq = ROM32(pll_rec[8]); - pll_lim->vco2.maxfreq = ROM32(pll_rec[12]); - pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]); - pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]); - pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX; - - /* these values taken from nv30/31/36 */ - pll_lim->vco1.min_n = 0x1; - if (cv == 0x36) - pll_lim->vco1.min_n = 0x5; - pll_lim->vco1.max_n = 0xff; - pll_lim->vco1.min_m = 0x1; - pll_lim->vco1.max_m = 0xd; - pll_lim->vco2.min_n = 0x4; - /* on nv30, 31, 36 (i.e. all cards with two stage PLLs with this - * table version (apart from nv35)), N2 is compared to - * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and - * save a comparison - */ - pll_lim->vco2.max_n = 0x28; - if (cv == 0x30 || cv == 0x35) - /* only 5 bits available for N2 on nv30/35 */ - pll_lim->vco2.max_n = 0x1f; - pll_lim->vco2.min_m = 0x1; - pll_lim->vco2.max_m = 0x4; - pll_lim->max_log2p = 0x7; - pll_lim->max_usable_log2p = 0x6; - } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) { - uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen; - uint32_t reg = 0; /* default match */ - uint8_t *pll_rec; - int i; - - /* first entry is default match, if nothing better. warn if reg field nonzero */ - if (ROM32(bios->data[plloffs])) - NV_WARN(pScrn, "Default PLL limit entry has non-zero " - "register field\n"); - - if (limit_match > MAX_PLL_TYPES) - /* we've been passed a reg as the match */ - reg = limit_match; - else /* limit match is a pll type */ - for (i = 1; i < entries && !reg; i++) { - uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]); - - if (limit_match == NVPLL && - (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000)) - reg = cmpreg; - if (limit_match == MPLL && - (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020)) - reg = cmpreg; - if (limit_match == VPLL1 && - (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010)) - reg = cmpreg; - if (limit_match == VPLL2 && - (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018)) - reg = cmpreg; - } - - for (i = 1; i < entries; i++) - if (ROM32(bios->data[plloffs + recordlen * i]) == reg) { - pllindex = i; - break; - } - - pll_rec = &bios->data[plloffs + recordlen * pllindex]; - - BIOSLOG(pScrn, "Loading PLL limits for reg 0x%08x\n", pllindex ? reg : 0); - - /* frequencies are stored in tables in MHz, kHz are more useful, so we convert */ - - /* What output frequencies can each VCO generate? */ - pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000; - pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000; - pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000; - pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000; - - /* What input frequencies do they accept (past the m-divider)? */ - pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000; - pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000; - pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000; - pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000; - - /* What values are accepted as multiplier and divider? */ - pll_lim->vco1.min_n = pll_rec[20]; - pll_lim->vco1.max_n = pll_rec[21]; - pll_lim->vco1.min_m = pll_rec[22]; - pll_lim->vco1.max_m = pll_rec[23]; - pll_lim->vco2.min_n = pll_rec[24]; - pll_lim->vco2.max_n = pll_rec[25]; - pll_lim->vco2.min_m = pll_rec[26]; - pll_lim->vco2.max_m = pll_rec[27]; - - pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29]; - if (pll_lim->max_log2p > 0x7) - /* pll decoding in nv_hw.c assumes never > 7 */ - NV_WARN(pScrn, "Max log2 P value greater than 7 (%d)\n", - pll_lim->max_log2p); - if (cv < 0x60) - pll_lim->max_usable_log2p = 0x6; - pll_lim->log2p_bias = pll_rec[30]; - - if (recordlen > 0x22) - pll_lim->refclk = ROM32(pll_rec[31]); - - if (recordlen > 0x23 && pll_rec[35]) - NV_WARN(pScrn, - "Bits set in PLL configuration byte (%x)\n", - pll_rec[35]); - - /* C51 special not seen elsewhere */ - if (cv == 0x51 && !pll_lim->refclk) { - uint32_t sel_clk = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK); - - if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) || - ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) { - if (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3) - pll_lim->refclk = 200000; - else - pll_lim->refclk = 25000; - } - } - } else if (pll_lim_ver) { /* ver 0x30 */ - uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen]; - uint8_t *record = NULL; - int i; - - BIOSLOG(pScrn, "Loading PLL limits for register 0x%08x\n", - limit_match); - - for (i = 0; i < entries; i++, entry += recordlen) { - if (ROM32(entry[3]) == limit_match) { - record = &bios->data[ROM16(entry[1])]; - break; - } - } - - if (!record) { - NV_ERROR(pScrn, "Register 0x%08x not found in PLL " - "limits table", limit_match); - return -ENOENT; - } - - pll_lim->vco1.minfreq = ROM16(record[0]) * 1000; - pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000; - pll_lim->vco2.minfreq = ROM16(record[4]) * 1000; - pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000; - pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000; - pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000; - pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000; - pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000; - pll_lim->vco1.min_n = record[16]; - pll_lim->vco1.max_n = record[17]; - pll_lim->vco1.min_m = record[18]; - pll_lim->vco1.max_m = record[19]; - pll_lim->vco2.min_n = record[20]; - pll_lim->vco2.max_n = record[21]; - pll_lim->vco2.min_m = record[22]; - pll_lim->vco2.max_m = record[23]; - pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25]; - pll_lim->log2p_bias = record[27]; - pll_lim->refclk = ROM32(record[28]); - } - - /* By now any valid limit table ought to have set a max frequency for - * vco1, so if it's zero it's either a pre limit table bios, or one - * with an empty limit table (seen on nv18) - */ - if (!pll_lim->vco1.maxfreq) { - pll_lim->vco1.minfreq = bios->fminvco; - pll_lim->vco1.maxfreq = bios->fmaxvco; - pll_lim->vco1.min_inputfreq = 0; - pll_lim->vco1.max_inputfreq = INT_MAX; - pll_lim->vco1.min_n = 0x1; - pll_lim->vco1.max_n = 0xff; - pll_lim->vco1.min_m = 0x1; - if (crystal_straps == 0) { - /* nv05 does this, nv11 doesn't, nv10 unknown */ - if (cv < 0x11) - pll_lim->vco1.min_m = 0x7; - pll_lim->vco1.max_m = 0xd; - } else { - if (cv < 0x11) - pll_lim->vco1.min_m = 0x8; - pll_lim->vco1.max_m = 0xe; - } - if (cv < 0x17 || cv == 0x1a || cv == 0x20) - pll_lim->max_log2p = 4; - else - pll_lim->max_log2p = 5; - pll_lim->max_usable_log2p = pll_lim->max_log2p; - } - - if (!pll_lim->refclk) - switch (crystal_straps) { - case 0: - pll_lim->refclk = 13500; - break; - case (1 << 6): - pll_lim->refclk = 14318; - break; - case (1 << 22): - pll_lim->refclk = 27000; - break; - case (1 << 22 | 1 << 6): - pll_lim->refclk = 25000; - break; - } - -#if 0 /* for easy debugging */ - ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq); - ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq); - ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq); - ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq); - - ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq); - ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq); - ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq); - ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq); - - ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n); - ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n); - ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m); - ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m); - ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n); - ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n); - ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m); - ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m); - - ErrorF("pll.max_log2p: %d\n", pll_lim->max_log2p); - ErrorF("pll.log2p_bias: %d\n", pll_lim->log2p_bias); - - ErrorF("pll.refclk: %d\n", pll_lim->refclk); -#endif - - return 0; -} - -static void parse_bios_version(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset) -{ - /* offset + 0 (8 bits): Micro version - * offset + 1 (8 bits): Minor version - * offset + 2 (8 bits): Chip version - * offset + 3 (8 bits): Major version - */ - - bios->major_version = bios->data[offset + 3]; - bios->pub.chip_version = bios->data[offset + 2]; - NV_TRACE(pScrn, "Bios version %02x.%02x.%02x.%02x\n", - bios->data[offset + 3], bios->data[offset + 2], - bios->data[offset + 1], bios->data[offset]); -} - -static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) -{ - /* Parses the init table segment for pointers used in script execution. - * - * offset + 0 (16 bits): init script tables pointer - * offset + 2 (16 bits): macro index table pointer - * offset + 4 (16 bits): macro table pointer - * offset + 6 (16 bits): condition table pointer - * offset + 8 (16 bits): io condition table pointer - * offset + 10 (16 bits): io flag condition table pointer - * offset + 12 (16 bits): init function table pointer - */ - - bios->init_script_tbls_ptr = ROM16(bios->data[offset]); - bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]); - bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]); - bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]); - bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]); - bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]); - bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]); -} - -static int parse_bit_A_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* Parses the load detect values for g80 cards. - * - * offset + 0 (16 bits): loadval table pointer - */ - - uint16_t load_table_ptr; - uint8_t version, headerlen, entrylen, num_entries; - - if (bitentry->length != 3) { - NV_ERROR(pScrn, "Do not understand BIT A table\n"); - return -EINVAL; - } - - load_table_ptr = ROM16(bios->data[bitentry->offset]); - - if (load_table_ptr == 0x0) { - NV_ERROR(pScrn, "Pointer to BIT loadval table invalid\n"); - return -EINVAL; - } - - version = bios->data[load_table_ptr]; - - if (version != 0x10) { - NV_ERROR(pScrn, "BIT loadval table version %d.%d not supported\n", - version >> 4, version & 0xF); - return -ENOSYS; - } - - headerlen = bios->data[load_table_ptr + 1]; - entrylen = bios->data[load_table_ptr + 2]; - num_entries = bios->data[load_table_ptr + 3]; - - if (headerlen != 4 || entrylen != 4 || num_entries != 2) { - NV_ERROR(pScrn, "Do not understand BIT loadval table\n"); - return -EINVAL; - } - - /* First entry is normal dac, 2nd tv-out perhaps? */ - bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff; - - return 0; -} - -static int parse_bit_C_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* offset + 8 (16 bits): PLL limits table pointer - * - * There's more in here, but that's unknown. - */ - - if (bitentry->length < 10) { - NV_ERROR(pScrn, "Do not understand BIT C table\n"); - return -EINVAL; - } - - bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]); - - return 0; -} - -static int parse_bit_display_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* Parses the flat panel table segment that the bit entry points to. - * Starting at bitentry->offset: - * - * offset + 0 (16 bits): ??? table pointer - seems to have 18 byte records beginning with a freq - * offset + 2 (16 bits): mode table pointer - */ - - if (bitentry->length != 4) { - NV_ERROR(pScrn, "Do not understand BIT display table\n"); - return -EINVAL; - } - - bios->fp.fptablepointer = ROM16(bios->data[bitentry->offset + 2]); - - return 0; -} - -static int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* Parses the init table segment that the bit entry points to. - * - * See parse_script_table_pointers for layout - */ - - if (bitentry->length < 14) { - NV_ERROR(pScrn, "Do not understand init table\n"); - return -EINVAL; - } - - parse_script_table_pointers(bios, bitentry->offset); - - return 0; -} - -static int parse_bit_i_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* BIT 'i' (info?) table - * - * offset + 0 (32 bits): BIOS version dword (as in B table) - * offset + 5 (8 bits): BIOS feature byte (same as for BMP?) - * offset + 13 (16 bits): pointer to table containing DAC load detection comparison values - * - * There's other things in the table, purpose unknown - */ - - uint16_t daccmpoffset; - uint8_t dacver, dacheaderlen; - - if (bitentry->length < 6) { - NV_ERROR(pScrn, "BIT i table too short for needed information\n"); - return -EINVAL; - } - - parse_bios_version(pScrn, bios, bitentry->offset); - - /* bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's - * Quadro identity crisis), other bits possibly as for BMP feature byte - */ - bios->feature_byte = bios->data[bitentry->offset + 5]; - bios->is_mobile = bios->feature_byte & FEATURE_MOBILE; - - if (bitentry->length < 15) { - NV_WARN(pScrn, "BIT i table not long enough for DAC load " - "detection comparison table\n"); - return -EINVAL; - } - - daccmpoffset = ROM16(bios->data[bitentry->offset + 13]); - - /* doesn't exist on g80 */ - if (!daccmpoffset) - return 0; - - /* The first value in the table, following the header, is the comparison value - * Purpose of subsequent values unknown -- TV load detection? - */ - - dacver = bios->data[daccmpoffset]; - dacheaderlen = bios->data[daccmpoffset + 1]; - - if (dacver != 0x00 && dacver != 0x10) { - NV_WARN(pScrn, "DAC load detection comparison table version " - "%d.%d not known\n", dacver >> 4, dacver & 0xf); - return -ENOSYS; - } - - bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]); - - return 0; -} - -static int parse_bit_lvds_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* Parses the LVDS table segment that the bit entry points to. - * Starting at bitentry->offset: - * - * offset + 0 (16 bits): LVDS strap xlate table pointer - */ - - if (bitentry->length != 2) { - NV_ERROR(pScrn, "Do not understand BIT LVDS table\n"); - return -EINVAL; - } - - /* no idea if it's still called the LVDS manufacturer table, but the concept's close enough */ - bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]); - - return 0; -} - -static int parse_bit_M_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* offset + 2 (8 bits): number of options in an INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set - * offset + 3 (16 bits): pointer to strap xlate table for RAM restrict option selection - * - * There's a bunch of bits in this table other than the RAM restrict - * stuff that we don't use - their use currently unknown - */ - - int i; - - /* Older bios versions don't have a sufficiently long table for what we want */ - if (bitentry->length < 0x5) - return 0; - - /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */ - for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++) - ; - itbl_entry[i].length_multiplier = bios->data[bitentry->offset + 2] * 4; - init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier; - - bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]); - - return 0; -} - -static int parse_bit_tmds_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry) -{ - /* Parses the pointer to the TMDS table - * - * Starting at bitentry->offset: - * - * offset + 0 (16 bits): TMDS table pointer - * - * The TMDS table is typically found just before the DCB table, with a - * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being - * length?) - * - * At offsets +7 and +9 are pointers to scripts, which (when not - * stubbed) seem to be called from the main init tables at POST - * Offset +11 has a pointer to a table where the first word is a pxclk - * frequency and the second word a pointer to a script, which should be - * run if the comparison pxclk frequency is less than the pxclk desired. - * This repeats for decreasing comparison frequencies - * Offset +13 has a pointer to a similar table - * The selection of table (and possibly +7/+9 script) is dictated by - * "or" from the DCB. - */ - - uint16_t tmdstableptr; - - if (bitentry->length != 2) { - NV_ERROR(pScrn, "Do not understand BIT TMDS table\n"); - return -EINVAL; - } - - tmdstableptr = ROM16(bios->data[bitentry->offset]); - - if (tmdstableptr == 0x0) { - NV_ERROR(pScrn, "Pointer to TMDS table invalid\n"); - return -EINVAL; - } - - /* nv50+ has v2.0, but we don't parse it atm */ - if (bios->data[tmdstableptr] != 0x11) { - NV_WARN(pScrn, - "TMDS table revision %d.%d not currently supported\n", - bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); - return -ENOSYS; - } - - bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]); - bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]); - - return 0; -} - -static int -parse_bit_U_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, - bit_entry_t *bitentry) -{ - /* Parses the pointer to the G80 output script tables - * - * Starting at bitentry->offset: - * - * offset + 0 (16 bits): output script table pointer - */ - - uint16_t outputscripttableptr; - - if (bitentry->length != 3) { - NV_ERROR(pScrn, "Do not understand BIT U table\n"); - return -EINVAL; - } - - outputscripttableptr = ROM16(bios->data[bitentry->offset]); - bios->display.script_table_ptr = outputscripttableptr; - return 0; -} - -struct bit_table { - const char id; - int (* const parse_fn)(ScrnInfoPtr, struct nvbios *, bit_entry_t *); -}; - -#define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry }) - -static int parse_bit_table(ScrnInfoPtr pScrn, struct nvbios *bios, const uint16_t bitoffset, struct bit_table *table) -{ - uint8_t maxentries = bios->data[bitoffset + 4]; - int i, offset; - bit_entry_t bitentry; - - for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) { - bitentry.id[0] = bios->data[offset]; - - if (bitentry.id[0] != table->id) - continue; - - bitentry.id[1] = bios->data[offset + 1]; - bitentry.length = ROM16(bios->data[offset + 2]); - bitentry.offset = ROM16(bios->data[offset + 4]); - - return table->parse_fn(pScrn, bios, &bitentry); - } - - NV_ERROR(pScrn, "BIT table '%c' not found\n", table->id); - - return -ENOSYS; -} - -static int parse_bit_structure(ScrnInfoPtr pScrn, struct nvbios *bios, const uint16_t bitoffset) -{ - int ret; - - /* the only restriction on parsing order currently is having 'i' first - * for use of bios->*_version or bios->feature_byte while parsing; - * functions shouldn't be actually *doing* anything apart from pulling - * data from the image into the bios struct, thus no interdependencies - */ - if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('i', i)))) /* info? */ - return ret; - if (bios->major_version >= 0x60) /* g80+ */ - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('A', A)); - if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('C', C)))) - return ret; - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('D', display)); - if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('I', init)))) - return ret; - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */ - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('L', lvds)); - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('T', tmds)); - parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('U', U)); - - return 0; -} - -static int parse_bmp_structure(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset) -{ - /* Parses the BMP structure for useful things, but does not act on them - * - * offset + 5: BMP major version - * offset + 6: BMP minor version - * offset + 9: BMP feature byte - * offset + 10: BCD encoded BIOS version - * - * offset + 18: init script table pointer (for bios versions < 5.10h) - * offset + 20: extra init script table pointer (for bios versions < 5.10h) - * - * offset + 24: memory init table pointer (used on early bios versions) - * offset + 26: SDR memory sequencing setup data table - * offset + 28: DDR memory sequencing setup data table - * - * offset + 54: index of I2C CRTC pair to use for CRT output - * offset + 55: index of I2C CRTC pair to use for TV output - * offset + 56: index of I2C CRTC pair to use for flat panel output - * offset + 58: write CRTC index for I2C pair 0 - * offset + 59: read CRTC index for I2C pair 0 - * offset + 60: write CRTC index for I2C pair 1 - * offset + 61: read CRTC index for I2C pair 1 - * - * offset + 67: maximum internal PLL frequency (single stage PLL) - * offset + 71: minimum internal PLL frequency (single stage PLL) - * - * offset + 75: script table pointers, as described in parse_script_table_pointers - * - * offset + 89: TMDS single link output A table pointer - * offset + 91: TMDS single link output B table pointer - * offset + 95: LVDS single link output A table pointer - * offset + 105: flat panel timings table pointer - * offset + 107: flat panel strapping translation table pointer - * offset + 117: LVDS manufacturer panel config table pointer - * offset + 119: LVDS manufacturer strapping translation table pointer - * - * offset + 142: PLL limits table pointer - * - * offset + 156: minimum pixel clock for LVDS dual link - */ - - uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor; - uint16_t bmplength; - uint16_t legacy_scripts_offset, legacy_i2c_offset; - - /* load needed defaults in case we can't parse this info */ - bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX; - bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX; - bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX; - bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX; - bios->pub.digital_min_front_porch = 0x4b; - bios->fmaxvco = 256000; - bios->fminvco = 128000; - bios->fp.duallink_transition_clk = 90000; - - bmp_version_major = bmp[5]; - bmp_version_minor = bmp[6]; - - NV_TRACE(pScrn, "BMP version %d.%d\n", - bmp_version_major, bmp_version_minor); - - /* Make sure that 0x36 is blank and can't be mistaken for a DCB pointer on early versions */ - if (bmp_version_major < 5) - *(uint16_t *)&bios->data[0x36] = 0; - - /* Seems that the minor version was 1 for all major versions prior to 5 */ - /* Version 6 could theoretically exist, but I suspect BIT happened instead */ - if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) { - NV_ERROR(pScrn, "You have an unsupported BMP version. " - "Please send in your bios\n"); - return -ENOSYS; - } - - if (bmp_version_major == 0) /* nothing that's currently useful in this version */ - return 0; - else if (bmp_version_major == 1) - bmplength = 44; /* exact for 1.01 */ - else if (bmp_version_major == 2) - bmplength = 48; /* exact for 2.01 */ - else if (bmp_version_major == 3) - bmplength = 54; /* guessed - mem init tables added in this version */ - else if (bmp_version_major == 4 || bmp_version_minor < 0x1) /* don't know if 5.0 exists... */ - bmplength = 62; /* guessed - BMP I2C indices added in version 4*/ - else if (bmp_version_minor < 0x6) - bmplength = 67; /* exact for 5.01 */ - else if (bmp_version_minor < 0x10) - bmplength = 75; /* exact for 5.06 */ - else if (bmp_version_minor == 0x10) - bmplength = 89; /* exact for 5.10h */ - else if (bmp_version_minor < 0x14) - bmplength = 118; /* exact for 5.11h */ - else if (bmp_version_minor < 0x24) /* not sure of version where pll limits came in; - * certainly exist by 0x24 though */ - /* length not exact: this is long enough to get lvds members */ - bmplength = 123; - else if (bmp_version_minor < 0x27) - /* length not exact: this is long enough to get pll limit member */ - bmplength = 144; - else - /* length not exact: this is long enough to get dual link transition clock */ - bmplength = 158; - - /* checksum */ - if (nv_cksum(bmp, 8)) { - NV_ERROR(pScrn, "Bad BMP checksum\n"); - return -EINVAL; - } - - /* bit 4 seems to indicate either a mobile bios or a quadro card -- - * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl - * (not nv10gl), bit 5 that the flat panel tables are present, and - * bit 6 a tv bios */ - bios->feature_byte = bmp[9]; - - parse_bios_version(pScrn, bios, offset + 10); - - if (bmp_version_major < 5 || bmp_version_minor < 0x10) - bios->old_style_init = true; - legacy_scripts_offset = 18; - if (bmp_version_major < 2) - legacy_scripts_offset -= 4; - bios->init_script_tbls_ptr = ROM16(bmp[legacy_scripts_offset]); - bios->extra_init_script_tbl_ptr = ROM16(bmp[legacy_scripts_offset + 2]); - - if (bmp_version_major > 2) { /* appears in BMP 3 */ - bios->legacy.mem_init_tbl_ptr = ROM16(bmp[24]); - bios->legacy.sdr_seq_tbl_ptr = ROM16(bmp[26]); - bios->legacy.ddr_seq_tbl_ptr = ROM16(bmp[28]); - } - - legacy_i2c_offset = 0x48; /* BMP version 2 & 3 */ - if (bmplength > 61) - legacy_i2c_offset = offset + 54; - bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; - bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; - bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; - /* don't overwrite defaults with zero (mac braindamage) */ - if (bios->data[legacy_i2c_offset + 4]) - bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; - if (bios->data[legacy_i2c_offset + 5]) - bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; - if (bios->data[legacy_i2c_offset + 6]) - bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; - if (bios->data[legacy_i2c_offset + 7]) - bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; - - if (bmplength > 74) { - bios->fmaxvco = ROM32(bmp[67]); - bios->fminvco = ROM32(bmp[71]); - } - if (bmplength > 88) - parse_script_table_pointers(bios, offset + 75); - if (bmplength > 94) { - bios->tmds.output0_script_ptr = ROM16(bmp[89]); - bios->tmds.output1_script_ptr = ROM16(bmp[91]); - /* never observed in use with lvds scripts, but is reused for - * 18/24 bit panel interface default for EDID equipped panels - * (if_is_24bit not set directly to avoid any oscillation) */ - bios->legacy.lvds_single_a_script_ptr = ROM16(bmp[95]); - } - if (bmplength > 108) { - bios->fp.fptablepointer = ROM16(bmp[105]); - bios->fp.fpxlatetableptr = ROM16(bmp[107]); - bios->fp.xlatwidth = 1; - } - if (bmplength > 120) { - bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]); - bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]); - } - if (bmplength > 143) - bios->pll_limit_tbl_ptr = ROM16(bmp[142]); - - if (bmplength > 157) - bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10; - - return 0; -} - -static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) -{ - int i, j; - - for (i = 0; i <= (n - len); i++) { - for (j = 0; j < len; j++) - if (data[i + j] != str[j]) - break; - if (j == len) - return i; - } - - return 0; -} - -static int -read_dcb_i2c_entry(ScrnInfoPtr pScrn, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c) -{ - uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4; - int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES; - int recordoffset = 0, rdofs = 1, wrofs = 0; - uint8_t port_type = 0; - - if (!i2ctable) - return -EINVAL; - - if (dcb_version >= 0x30) { - if (i2ctable[0] != dcb_version) /* necessary? */ - NV_WARN(pScrn, - "DCB I2C table version mismatch (%02X vs %02X)\n", - i2ctable[0], dcb_version); - dcb_i2c_ver = i2ctable[0]; - headerlen = i2ctable[1]; - if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES) - i2c_entries = i2ctable[2]; - else - NV_WARN(pScrn, - "DCB I2C table has more entries than indexable " - "(%d entries, max index 15)\n", i2ctable[2]); - entry_len = i2ctable[3]; - /* [4] is i2c_default_indices, read in parse_dcb_table() */ - } - /* it's your own fault if you call this function on a DCB 1.1 BIOS -- - * the test below is for DCB 1.2 - */ - if (dcb_version < 0x14) { - recordoffset = 2; - rdofs = 0; - wrofs = 1; - } - - if (index == 0xf) - return 0; - if (index > i2c_entries) { - NV_ERROR(pScrn, "DCB I2C index too big (%d > %d)\n", - index, i2ctable[2]); - return -ENOENT; - } - if (i2ctable[headerlen + entry_len * index + 3] == 0xff) { - NV_ERROR(pScrn, "DCB I2C entry invalid\n"); - return -EINVAL; - } - - if (dcb_i2c_ver >= 0x30) { - port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index]; - - /* fixup for chips using same address offset for read and write */ - if (port_type == 4) /* seen on C51 */ - rdofs = wrofs = 1; - if (port_type == 5) /* G80+ */ - rdofs = wrofs = 0; - } - if (dcb_i2c_ver >= 0x40 && port_type != 5) - NV_WARN(pScrn, "DCB I2C table has port type %d\n", port_type); - - i2c->port_type = port_type; - i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index]; - i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index]; - - return 0; -} - -static int init_dcb_i2c_entry(ScrnInfoPtr pScrn, struct nvbios *bios, int index) -{ - struct dcb_i2c_entry *i2c = &bios->bdcb.dcb.i2c[index]; - int ret; - char adaptorname[11]; - - if (i2c->chan) - return 0; - - if (bios->bdcb.version < 0x15) { - NV_ERROR(pScrn, "DCB table not version 1.5 or greater\n"); - return -ENOSYS; - } - if (!bios->bdcb.i2c_table) { - NV_ERROR(pScrn, "No parsed DCB I2C port table\n"); - return -EINVAL; - } - - if ((ret = read_dcb_i2c_entry(pScrn, bios->bdcb.version, bios->bdcb.i2c_table, index, i2c))) - return ret; - - snprintf(adaptorname, 11, "DCB-I2C-%d", index); - - return NV_I2CInit(pScrn, &i2c->chan, i2c, xstrdup(adaptorname)); -} - -static struct dcb_entry * new_dcb_entry(struct parsed_dcb *dcb) -{ - struct dcb_entry *entry = &dcb->entry[dcb->entries]; - - memset(entry, 0, sizeof (struct dcb_entry)); - entry->index = dcb->entries++; - - return entry; -} - -static void -fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads, int or) -{ - struct dcb_entry *entry = new_dcb_entry(dcb); - - entry->type = 0; - entry->i2c_index = i2c; - entry->heads = heads; - entry->location = DCB_LOC_ON_CHIP; - /* setting "or" to 0 for early gen crt modesetting is fine (unused) */ - entry->or = or; -} - -static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads) -{ - struct dcb_entry *entry = new_dcb_entry(dcb); - - entry->type = 2; - entry->i2c_index = LEGACY_I2C_PANEL; - entry->heads = twoHeads ? 3 : 1; - entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ - entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */ - entry->duallink_possible = false; /* SiI164 and co. are single link */ - -#if 0 - /* for dvi-a either crtc probably works, but my card appears to only - * support dvi-d. "nvidia" still attempts to program it for dvi-a, - * doing the full fp output setup (program 0x6808.. fp dimension regs, - * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880); - * the monitor picks up the mode res ok and lights up, but no pixel - * data appears, so the board manufacturer probably connected up the - * sync lines, but missed the video traces / components - * - * with this introduction, dvi-a left as an exercise for the reader. - */ - fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads, 0); -#endif -} - -static bool -parse_dcb20_entry(ScrnInfoPtr pScrn, struct bios_parsed_dcb *bdcb, - uint32_t conn, uint32_t conf, struct dcb_entry *entry) -{ - entry->type = conn & 0xf; - entry->i2c_index = (conn >> 4) & 0xf; - entry->heads = (conn >> 8) & 0xf; - entry->bus = (conn >> 16) & 0xf; - entry->location = (conn >> 20) & 0x3; - entry->or = (conn >> 24) & 0xf; - /* Normal entries consist of a single bit, but dual link has the - * next most significant bit set too - */ - entry->duallink_possible = - ((1 << (ffs(entry->or) - 1)) * 3 == entry->or); - - switch (entry->type) { - case OUTPUT_ANALOG: - /* although the rest of a CRT conf dword is usually - * zeros, mac biosen have stuff there so we must mask - */ - entry->crtconf.maxfreq = (bdcb->version < 0x30) ? - (conf & 0xffff) * 10 : - (conf & 0xff) * 10000; - break; - case OUTPUT_LVDS: - { - uint32_t mask; - if (conf & 0x1) - entry->lvdsconf.use_straps_for_mode = true; - if (bdcb->version < 0x22) { - mask = ~0xd; - /* the laptop in bug 14567 lies and claims to not use - * straps when it does, so assume all DCB 2.0 laptops - * use straps, until a broken EDID using one is produced - */ - entry->lvdsconf.use_straps_for_mode = true; - /* both 0x4 and 0x8 show up in v2.0 tables; assume they - * mean the same thing (probably wrong, but might work) - */ - if (conf & 0x4 || conf & 0x8) - entry->lvdsconf.use_power_scripts = true; - } else { - mask = ~0x5; - if (conf & 0x4) - entry->lvdsconf.use_power_scripts = true; - } - if (conf & mask) { - /* I'm bored of getting this reported; left as a reminder for someone to fix it */ - if (bdcb->version >= 0x40) { - NV_WARN(pScrn, "G80+ LVDS not initialized by driver; ignoring conf bits\n"); - break; - } - NV_ERROR(pScrn, "Unknown LVDS configuration bits, " - "please report\n"); - /* cause output setting to fail, so message is seen */ - bdcb->dcb.entries = 0; - return false; - } - break; - } - case 0xe: - /* weird g80 mobile type that "nv" treats as a terminator */ - bdcb->dcb.entries--; - return false; - } - /* unsure what DCB version introduces this, 3.0? */ - if (conf & 0x100000) - entry->i2c_upper_default = true; - - return true; -} - -static bool -parse_dcb15_entry(ScrnInfoPtr pScrn, struct parsed_dcb *dcb, - uint32_t conn, uint32_t conf, struct dcb_entry *entry) -{ - if (conn != 0xf0003f00 && conn != 0xf2247f10 && - conn != 0xf2204001 && conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 && conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 && conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 && - conn != 0xf2045ff2 && - conn != 0xf2045f14 && conn != 0xf207df14 && conn != 0xf2205004) { - NV_ERROR(pScrn, "Unknown DCB 1.5 entry, please report\n"); - - /* cause output setting to fail for !TV, so message is seen */ - if ((conn & 0xf) != 0x1) - dcb->entries = 0; - - return false; - } - /* most of the below is a "best guess" atm */ - entry->type = conn & 0xf; - if (entry->type == 2) - /* another way of specifying straps based lvds... */ - entry->type = OUTPUT_LVDS; - if (entry->type == 4) { /* digital */ - if (conn & 0x10) - entry->type = OUTPUT_LVDS; - else - entry->type = OUTPUT_TMDS; - } - /* what's in bits 5-13? could be some encoder maker thing, in tv case */ - entry->i2c_index = (conn >> 14) & 0xf; - /* raw heads field is in range 0-1, so move to 1-2 */ - entry->heads = ((conn >> 18) & 0x7) + 1; - entry->location = (conn >> 21) & 0xf; - /* unused: entry->bus = (conn >> 25) & 0x7; */ - /* set or to be same as heads -- hopefully safe enough */ - entry->or = entry->heads; - entry->duallink_possible = false; - - switch (entry->type) { - case OUTPUT_ANALOG: - entry->crtconf.maxfreq = (conf & 0xffff) * 10; - break; - case OUTPUT_LVDS: - /* this is probably buried in conn's unknown bits */ - /* this will upset EDID-ful models, if they exist */ - entry->lvdsconf.use_straps_for_mode = true; - entry->lvdsconf.use_power_scripts = true; - break; - case OUTPUT_TMDS: - /* invent a DVI-A output, by copying the fields of the DVI-D - * output; reported to work by math_b on an NV20(!) */ - fabricate_vga_output(dcb, entry->i2c_index, entry->heads, 0); - } - - return true; -} - -static bool parse_dcb_entry(ScrnInfoPtr pScrn, struct bios_parsed_dcb *bdcb, - uint32_t conn, uint32_t conf) -{ - struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb); - bool ret; - - if (bdcb->version >= 0x20) - ret = parse_dcb20_entry(pScrn, bdcb, conn, conf, entry); - else - ret = parse_dcb15_entry(pScrn, &bdcb->dcb, conn, conf, entry); - if (!ret) - return ret; - - read_dcb_i2c_entry(pScrn, bdcb->version, bdcb->i2c_table, - entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]); - - return true; -} - -void merge_like_dcb_entries(ScrnInfoPtr pScrn, struct parsed_dcb *dcb) -{ - /* DCB v2.0 lists each output combination separately. - * Here we merge compatible entries to have fewer outputs, with more options - */ - - int i, newentries = 0; - - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *ient = &dcb->entry[i]; - int j; - - for (j = i + 1; j < dcb->entries; j++) { - struct dcb_entry *jent = &dcb->entry[j]; - - if (jent->type == 100) /* already merged entry */ - continue; - - /* merge heads field when all other fields the same */ - if (jent->i2c_index == ient->i2c_index && - jent->type == ient->type && - jent->location == ient->location && - jent->or == ient->or) { - NV_TRACE(pScrn, "Merging DCB entries %d and %d\n", - i, j); - ient->heads |= jent->heads; - jent->type = 100; /* dummy value */ - } - } - } - - /* Compact entries merged into others out of dcb */ - for (i = 0; i < dcb->entries; i++) { - if (dcb->entry[i].type == 100) - continue; - - if (newentries != i) { - dcb->entry[newentries] = dcb->entry[i]; - dcb->entry[newentries].index = newentries; - } - newentries++; - } - - dcb->entries = newentries; -} - -static int parse_dcb_table(ScrnInfoPtr pScrn, struct nvbios *bios, bool twoHeads) -{ - struct bios_parsed_dcb *bdcb = &bios->bdcb; - struct parsed_dcb *dcb; - uint16_t dcbptr, i2ctabptr = 0; - uint8_t *dcbtable; - uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; - bool configblock = true; - int recordlength = 8, confofs = 4; - int i; - - dcb = bios->pub.dcb = &bdcb->dcb; - dcb->entries = 0; - - /* get the offset from 0x36 */ - dcbptr = ROM16(bios->data[0x36]); - - if (dcbptr == 0x0) { -#ifdef __powerpc__ - if ((NVPTR(pScrn)->Chipset & 0xffff) == 0x0172) { - /* retarded PowerMac G4 has DVI and ADC (#21273) */ - NV_WARN(pScrn, "Working around missing output tables\n"); - /* this is the dvi-a */ - fabricate_vga_output(dcb, LEGACY_I2C_PANEL, 0x3, 2); - return 0; - } -#endif - NV_WARN(pScrn, "No output data (DCB) found in BIOS, " - "assuming a CRT output exists\n"); - /* this situation likely means a really old card, pre DCB */ - fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1, 0); - return 0; - } - - dcbtable = &bios->data[dcbptr]; - - /* get DCB version */ - bdcb->version = dcbtable[0]; - NV_TRACE(pScrn, "Found Display Configuration Block version %d.%d\n", - bdcb->version >> 4, bdcb->version & 0xf); - - if (bdcb->version >= 0x20) { /* NV17+ */ - uint32_t sig; - - if (bdcb->version >= 0x30) { /* NV40+ */ - headerlen = dcbtable[1]; - entries = dcbtable[2]; - recordlength = dcbtable[3]; - i2ctabptr = ROM16(dcbtable[4]); - sig = ROM32(dcbtable[6]); - if (bdcb->version == 0x40) /* G80 */ - bdcb->init8e_table_ptr = - ROM16(dcbtable[10]); - } else { - i2ctabptr = ROM16(dcbtable[2]); - sig = ROM32(dcbtable[4]); - headerlen = 8; - } - - if (sig != 0x4edcbdcb) { - NV_ERROR(pScrn, "Bad Display Configuration Block " - "signature (%08X)\n", sig); - return -EINVAL; - } - } else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */ - char sig[8] = { 0 }; - - strncpy(sig, (char *)&dcbtable[-7], 7); - i2ctabptr = ROM16(dcbtable[2]); - recordlength = 10; - confofs = 6; - - if (strcmp(sig, "DEV_REC")) { - NV_ERROR(pScrn, "Bad Display Configuration Block " - "signature (%s)\n", sig); - return -EINVAL; - } - } else { - /* v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always - * has the same single (crt) entry, even when tv-out present, so - * the conclusion is this version cannot really be used. - * v1.2 tables (some NV6/10, and NV15+) normally have the same - * 5 entries, which are not specific to the card and so no use. - * v1.2 does have an I2C table that read_dcb_i2c_table can - * handle, but cards exist (nv11 in #14821) with a bad i2c table - * pointer, so use the indices parsed in parse_bmp_structure. - * v1.1 (NV5+, maybe some NV4) is entirely unhelpful - */ - NV_TRACEWARN(pScrn, "No useful information in BIOS output table; " - "adding all possible outputs\n"); - fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1, 0); - if (bios->tmds.output0_script_ptr || - bios->tmds.output1_script_ptr) - fabricate_dvi_i_output(dcb, twoHeads); - return 0; - } - - if (!i2ctabptr) - NV_WARN(pScrn, "No pointer to DCB I2C port table\n"); - else { - bdcb->i2c_table = &bios->data[i2ctabptr]; - if (bdcb->version >= 0x30) - bdcb->i2c_default_indices = bdcb->i2c_table[4]; - } - - if (entries > DCB_MAX_NUM_ENTRIES) - entries = DCB_MAX_NUM_ENTRIES; - - for (i = 0; i < entries; i++) { - uint32_t connection, config = 0; - - connection = ROM32(dcbtable[headerlen + recordlength * i]); - if (configblock) - config = ROM32(dcbtable[headerlen + confofs + recordlength * i]); - - /* Should we allow discontinuous DCBs? Certainly DCB I2C tables can be discontinuous */ - if ((connection & 0x0000000f) == 0x0000000f) /* end of records */ - break; - if (connection == 0x00000000) /* seen on an NV11 with DCB v1.5 */ - break; - - NV_TRACEWARN(pScrn, "Raw DCB entry %d: %08x %08x\n", - dcb->entries, connection, config); - - if (!parse_dcb_entry(pScrn, bdcb, connection, config)) - break; - } - - /* apart for v2.1+ not being known for requiring merging, this - * guarantees dcbent->index is the index of the entry in the rom image - */ - if (bdcb->version < 0x21) - merge_like_dcb_entries(pScrn, dcb); - - return (dcb->entries ? 0 : -ENXIO); -} - -static void fixup_legacy_i2c(struct nvbios *bios) -{ - struct parsed_dcb *dcb = &bios->bdcb.dcb; - int i; - - for (i = 0; i < dcb->entries; i++) { - if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT) - dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt; - if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL) - dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel; - } -} - -static int load_nv17_hwsq_ucode_entry(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t hwsq_offset, int entry) -{ - /* The header following the "HWSQ" signature has the number of entries, - * and the entry size - * - * An entry consists of a dword to write to the sequencer control reg - * (0x00001304), followed by the ucode bytes, written sequentially, - * starting at reg 0x00001400 - */ - - uint8_t bytes_to_write; - uint16_t hwsq_entry_offset; - int i; - - if (bios->data[hwsq_offset] <= entry) { - NV_ERROR(pScrn, "Too few entries in HW sequencer table for " - "requested entry\n"); - return -ENOENT; - } - - bytes_to_write = bios->data[hwsq_offset + 1]; - - if (bytes_to_write != 36) { - NV_ERROR(pScrn, "Unknown HW sequencer entry size\n"); - return -EINVAL; - } - - NV_TRACE(pScrn, "Loading NV17 power sequencing microcode\n"); - - hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; - - /* set sequencer control */ - bios_wr32(pScrn, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); - bytes_to_write -= 4; - - /* write ucode */ - for (i = 0; i < bytes_to_write; i += 4) - bios_wr32(pScrn, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); - - /* twiddle NV_PBUS_DEBUG_4 */ - bios_wr32(pScrn, NV_PBUS_DEBUG_4, bios_rd32(pScrn, NV_PBUS_DEBUG_4) | 0x18); - - return 0; -} - -static int load_nv17_hw_sequencer_ucode(ScrnInfoPtr pScrn, struct nvbios *bios) -{ - /* BMP based cards, from NV17, need a microcode loading to correctly - * control the GPIO etc for LVDS panels - * - * BIT based cards seem to do this directly in the init scripts - * - * The microcode entries are found by the "HWSQ" signature. - */ - - const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' }; - int hwsq_offset; - - if (!(hwsq_offset = findstr(bios->data, bios->length, hwsq_signature, - sizeof(hwsq_signature)))) - return 0; - - /* always use entry 0? */ - return load_nv17_hwsq_ucode_entry(pScrn, bios, - hwsq_offset + sizeof(hwsq_signature), 0); -} - -uint8_t * nouveau_bios_embedded_edid(ScrnInfoPtr pScrn) -{ - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - const uint8_t edid_sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; - uint16_t offset = 0, newoffset; - int searchlen = NV_PROM_SIZE; - - if (bios->fp.edid) - return bios->fp.edid; - - while (searchlen) { - if (!(newoffset = findstr(&bios->data[offset], searchlen, edid_sig, 8))) - return NULL; - offset += newoffset; - if (!nv_cksum(&bios->data[offset], EDID1_LEN)) - break; - - searchlen -= offset; - offset++; - } - - NV_TRACE(pScrn, "Found EDID in BIOS\n"); - - return (bios->fp.edid = &bios->data[offset]); -} - -bool NVInitVBIOS(ScrnInfoPtr pScrn) -{ - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - - memset(bios, 0, sizeof(struct nvbios)); - - if (!NVShadowVBIOS(pScrn, bios->data)) - return false; - - bios->length = bios->data[2] * 512; - if (bios->length > NV_PROM_SIZE) - bios->length = NV_PROM_SIZE; - - return true; -} - -int nouveau_parse_vbios_struct(ScrnInfoPtr pScrn) -{ - struct nvbios *bios = &NVPTR(pScrn)->VBIOS; - const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; - const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; - int offset; - - if ((offset = findstr(bios->data, bios->length, bit_signature, sizeof(bit_signature)))) { - NV_TRACE(pScrn, "BIT BIOS found\n"); - return parse_bit_structure(pScrn, bios, offset + 6); - } - if ((offset = findstr(bios->data, bios->length, bmp_signature, sizeof(bmp_signature)))) { - NV_TRACE(pScrn, "BMP BIOS found\n"); - return parse_bmp_structure(pScrn, bios, offset); - } - - NV_ERROR(pScrn, "No known BIOS signature found\n"); - - return -ENODEV; -} - -int nouveau_run_vbios_init(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - int ret = 0; - - NVLockVgaCrtcs(pNv, false); - if (pNv->twoHeads) - NVSetOwner(pNv, crtchead); - - if (bios->major_version < 5) /* BMP only */ - load_nv17_hw_sequencer_ucode(pScrn, bios); - - parse_init_tables(pScrn, bios); - - if (bios->major_version < 5) - /* feature_byte on BMP is poor, but init always sets CR4B */ - bios->is_mobile = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_4B) & 0x40; - - /* all BIT systems need p_f_m_t for digital_min_front_porch */ - if (bios->is_mobile || bios->major_version >= 5) - ret = parse_fp_mode_table(pScrn, bios); - - NVLockVgaCrtcs(pNv, true); - - return ret; -} - -int NVParseBios(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - struct nvbios *bios = &pNv->VBIOS; - uint32_t saved_nv_pextdev_boot_0; - int ret; - - if (!NVInitVBIOS(pScrn)) - return -ENODEV; - if ((ret = nouveau_parse_vbios_struct(pScrn))) - return ret; - if ((ret = parse_dcb_table(pScrn, bios, pNv->twoHeads))) - return ret; - fixup_legacy_i2c(bios); - - if (!bios->major_version) /* we don't run version 0 bios */ - return 0; - - /* these will need remembering across a suspend */ - saved_nv_pextdev_boot_0 = bios_rd32(pScrn, NV_PEXTDEV_BOOT_0); - saved_nv_pfb_cfg0 = bios_rd32(pScrn, NV_PFB_CFG0); - - /* init script execution disabled */ - bios->execute = false; - - bios_wr32(pScrn, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0); - - pNv->vbios = &bios->pub; - - if ((ret = nouveau_run_vbios_init(pScrn))) { - pNv->vbios = NULL; - return ret; - } - - /* allow subsequent scripts to execute */ - bios->execute = true; - - return 0; -} diff --git a/src/nv_const.h b/src/nv_const.h index 3217af6..767344c 100644 --- a/src/nv_const.h +++ b/src/nv_const.h @@ -13,11 +13,6 @@ typedef enum { OPTION_NOACCEL, OPTION_SHADOW_FB, OPTION_VIDEO_KEY, - OPTION_FP_DITHER, - OPTION_FP_SCALE, - OPTION_CMDBUF_LOCATION, - OPTION_CMDBUF_SIZE, - OPTION_SCALING_MODE, OPTION_EXA_PIXMAPS } NVOpts; @@ -28,9 +23,6 @@ static const OptionInfoRec NVOptions[] = { { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, - { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_FP_SCALE, "FPScale", OPTV_BOOLEAN, {0}, FALSE }, - { OPTION_SCALING_MODE, "ScalingMode", OPTV_STRING, {0}, FALSE }, { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; diff --git a/src/nv_crtc.c b/src/nv_crtc.c deleted file mode 100644 index 9708741..0000000 --- a/src/nv_crtc.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* - * Copyright 1993-2003 NVIDIA, Corporation - * Copyright 2006 Dave Airlie - * Copyright 2007 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "nv_include.h" - -static void crtc_wr_cio_state(xf86CrtcPtr crtc, int index) -{ - NVWriteVgaCrtc(NVPTR(crtc->scrn), to_nouveau_crtc(crtc)->head, index, - to_nouveau_crtc(crtc)->state->CRTC[index]); -} - -void nv_crtc_set_digital_vibrance(xf86CrtcPtr crtc, int level) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - NVPtr pNv = NVPTR(crtc->scrn); - - regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level; - if (nv_crtc->saturation && pNv->gf4_disp_arch) { - regp->CRTC[NV_CIO_CRE_CSB] = 0x80; - regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2; - crtc_wr_cio_state(crtc, NV_CIO_CRE_5B); - } - crtc_wr_cio_state(crtc, NV_CIO_CRE_CSB); -} - -void nv_crtc_set_image_sharpening(xf86CrtcPtr crtc, int level) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - NVPtr pNv = NVPTR(crtc->scrn); - - nv_crtc->sharpness = level; - if (level < 0) /* blur is in hw range 0x3f -> 0x20 */ - level += 0x40; - regp->ramdac_634 = level; - NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_634, regp->ramdac_634); -} - -/* NV4x 0x40.. pll notes: - * gpu pll: 0x4000 + 0x4004 - * ?gpu? pll: 0x4008 + 0x400c - * vpll1: 0x4010 + 0x4014 - * vpll2: 0x4018 + 0x401c - * mpll: 0x4020 + 0x4024 - * mpll: 0x4038 + 0x403c - * - * the first register of each pair has some unknown details: - * bits 0-7: redirected values from elsewhere? (similar to PLL_SETUP_CONTROL?) - * bits 20-23: (mpll) something to do with post divider? - * bits 28-31: related to single stage mode? (bit 8/12) - */ - -static void nv_crtc_cursor_set(xf86CrtcPtr crtc) -{ - NVPtr pNv = NVPTR(crtc->scrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - uint32_t cursor_start = nv_crtc->head ? pNv->Cursor2->offset : - pNv->Cursor->offset; - - regp->CRTC[NV_CIO_CRE_HCUR_ADDR0_INDEX] = MASK(NV_CIO_CRE_HCUR_ASI) | - XLATE(cursor_start, 17, - NV_CIO_CRE_HCUR_ADDR0_ADR); - regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] = XLATE(cursor_start, 11, - NV_CIO_CRE_HCUR_ADDR1_ADR); - if (crtc->mode.Flags & V_DBLSCAN) - regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] |= MASK(NV_CIO_CRE_HCUR_ADDR1_CUR_DBL); - regp->CRTC[NV_CIO_CRE_HCUR_ADDR2_INDEX] = cursor_start >> 24; - - crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR0_INDEX); - crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR1_INDEX); - crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR2_INDEX); - if (pNv->Architecture == NV_ARCH_40) - nv_fix_nv40_hw_cursor(pNv, nv_crtc->head); -} - -static void nv_crtc_calc_state_ext(xf86CrtcPtr crtc, DisplayModePtr mode, int dot_clock) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_mode_state *state = &pNv->set_state; - struct nouveau_crtc_state *regp = &state->head[nv_crtc->head]; - struct nouveau_pll_vals *pv = ®p->pllvals; - struct pll_lims pll_lim; - int vclk, arb_burst, arb_fifo_lwm; - - if (get_pll_limits(pScrn, nv_crtc->head ? VPLL2 : VPLL1, &pll_lim)) - return; - - /* NM2 == 0 is used to determine single stage mode on two stage plls */ - pv->NM2 = 0; - - /* for newer nv4x the blob uses only the first stage of the vpll below a - * certain clock. for a certain nv4b this is 150MHz. since the max - * output frequency of the first stage for this card is 300MHz, it is - * assumed the threshold is given by vco1 maxfreq/2 - */ - /* for early nv4x, specifically nv40 and *some* nv43 (devids 0 and 6, - * not 8, others unknown), the blob always uses both plls. no problem - * has yet been observed in allowing the use a single stage pll on all - * nv43 however. the behaviour of single stage use is untested on nv40 - */ - if (pNv->NVArch > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2)) - memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); - - if (!(vclk = nouveau_calc_pll_mnp(pScrn, &pll_lim, dot_clock, pv))) - return; - - /* The blob uses this always, so let's do the same */ - if (pNv->Architecture == NV_ARCH_40) - state->pllsel |= NV_RAMDAC_PLL_SELECT_USE_VPLL2_TRUE; - /* again nv40 and some nv43 act more like nv3x as described above */ - if (pNv->NVArch < 0x41) - state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL | - NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL; - state->pllsel |= (nv_crtc->head ? NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2 | - NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2 : - NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL | - NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2); - - if (pv->NM2) - NV_TRACE(pScrn, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", - pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); - else - NV_TRACE(pScrn, "vpll: n %d m %d log2p %d\n", - pv->N1, pv->M1, pv->log2P); - - nouveau_calc_arb(pScrn, vclk, pScrn->bitsPerPixel, &arb_burst, &arb_fifo_lwm); - - regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst; - regp->CRTC[NV_CIO_CRE_FFLWM__INDEX] = arb_fifo_lwm & 0xff; - if (pNv->Architecture >= NV_ARCH_30) - regp->CRTC[NV_CIO_CRE_47] = arb_fifo_lwm >> 8; - - nv_crtc_cursor_set(crtc); -} - -static void -nv_crtc_dpms(xf86CrtcPtr crtc, int mode) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - unsigned char seq1 = 0, crtc17 = 0; - unsigned char crtc1A; - - NV_TRACE(pScrn, "Setting dpms mode %d on CRTC %d\n", mode, nv_crtc->head); - - if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */ - return; - - nv_crtc->last_dpms = mode; - - if (pNv->twoHeads) - NVSetOwner(pNv, nv_crtc->head); - - /* nv4ref indicates these two RPC1 bits inhibit h/v sync */ - crtc1A = NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RPC1_INDEX) & ~0xC0; - switch(mode) { - case DPMSModeStandby: - /* Screen: Off; HSync: Off, VSync: On -- Not Supported */ - seq1 = 0x20; - crtc17 = 0x80; - crtc1A |= 0x80; - break; - case DPMSModeSuspend: - /* Screen: Off; HSync: On, VSync: Off -- Not Supported */ - seq1 = 0x20; - crtc17 = 0x80; - crtc1A |= 0x40; - break; - case DPMSModeOff: - /* Screen: Off; HSync: Off, VSync: Off */ - seq1 = 0x20; - crtc17 = 0x00; - crtc1A |= 0xC0; - break; - case DPMSModeOn: - default: - /* Screen: On; HSync: On, VSync: On */ - seq1 = 0x00; - crtc17 = 0x80; - break; - } - - NVVgaSeqReset(pNv, nv_crtc->head, true); - /* Each head has it's own sequencer, so we can turn it off when we want */ - seq1 |= (NVReadVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX) & ~0x20); - NVWriteVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX, seq1); - crtc17 |= (NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX) & ~0x80); - usleep(10000); - NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX, crtc17); - NVVgaSeqReset(pNv, nv_crtc->head, false); - - NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RPC1_INDEX, crtc1A); -} - -static Bool -nv_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - return TRUE; -} - -static void -nv_crtc_mode_set_vga(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - - /* Calculate our timings */ - int horizDisplay = (mode->CrtcHDisplay >> 3) - 1; - int horizStart = (mode->CrtcHSyncStart >> 3) - 1; - int horizEnd = (mode->CrtcHSyncEnd >> 3) - 1; - int horizTotal = (mode->CrtcHTotal >> 3) - 5; - int horizBlankStart = (mode->CrtcHDisplay >> 3) - 1; - int horizBlankEnd = (mode->CrtcHTotal >> 3) - 1; - int vertDisplay = mode->CrtcVDisplay - 1; - int vertStart = mode->CrtcVSyncStart - 1; - int vertEnd = mode->CrtcVSyncEnd - 1; - int vertTotal = mode->CrtcVTotal - 2; - int vertBlankStart = mode->CrtcVDisplay - 1; - int vertBlankEnd = mode->CrtcVTotal - 1; - - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - bool fp_output = false; - int i; - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - - if (output->crtc == crtc && IS_DFP(nv_encoder->dcb->type)) - fp_output = true; - } - - if (fp_output) { - vertStart = vertTotal - 3; - vertEnd = vertTotal - 2; - vertBlankStart = vertStart; - horizStart = horizTotal - 5; - horizEnd = horizTotal - 2; - horizBlankEnd = horizTotal + 4; - if (pNv->overlayAdaptor && pNv->Architecture >= NV_ARCH_10) - /* This reportedly works around some video overlay bandwidth problems */ - horizTotal += 2; - } - - if (mode->Flags & V_INTERLACE) - vertTotal |= 1; - -#if 0 - ErrorF("horizDisplay: 0x%X \n", horizDisplay); - ErrorF("horizStart: 0x%X \n", horizStart); - ErrorF("horizEnd: 0x%X \n", horizEnd); - ErrorF("horizTotal: 0x%X \n", horizTotal); - ErrorF("horizBlankStart: 0x%X \n", horizBlankStart); - ErrorF("horizBlankEnd: 0x%X \n", horizBlankEnd); - ErrorF("vertDisplay: 0x%X \n", vertDisplay); - ErrorF("vertStart: 0x%X \n", vertStart); - ErrorF("vertEnd: 0x%X \n", vertEnd); - ErrorF("vertTotal: 0x%X \n", vertTotal); - ErrorF("vertBlankStart: 0x%X \n", vertBlankStart); - ErrorF("vertBlankEnd: 0x%X \n", vertBlankEnd); -#endif - - /* - * compute correct Hsync & Vsync polarity - */ - if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) - && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { - - regp->MiscOutReg = 0x23; - if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40; - if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80; - } else { - int VDisplay = mode->VDisplay; - if (mode->Flags & V_DBLSCAN) - VDisplay *= 2; - if (mode->VScan > 1) - VDisplay *= mode->VScan; - if (VDisplay < 400) - regp->MiscOutReg = 0xA3; /* +hsync -vsync */ - else if (VDisplay < 480) - regp->MiscOutReg = 0x63; /* -hsync +vsync */ - else if (VDisplay < 768) - regp->MiscOutReg = 0xE3; /* -hsync -vsync */ - else - regp->MiscOutReg = 0x23; /* +hsync +vsync */ - } - - regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2; - - /* - * Time Sequencer - */ - regp->Sequencer[NV_VIO_SR_RESET_INDEX] = 0x00; - /* 0x20 disables the sequencer */ - if (mode->Flags & V_CLKDIV2) - regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x29; - else - regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x21; - regp->Sequencer[NV_VIO_SR_PLANE_MASK_INDEX] = 0x0F; - regp->Sequencer[NV_VIO_SR_CHAR_MAP_INDEX] = 0x00; - regp->Sequencer[NV_VIO_SR_MEM_MODE_INDEX] = 0x0E; - - /* - * CRTC - */ - regp->CRTC[NV_CIO_CR_HDT_INDEX] = horizTotal; - regp->CRTC[NV_CIO_CR_HDE_INDEX] = horizDisplay; - regp->CRTC[NV_CIO_CR_HBS_INDEX] = horizBlankStart; - regp->CRTC[NV_CIO_CR_HBE_INDEX] = (1 << 7) | - XLATE(horizBlankEnd, 0, NV_CIO_CR_HBE_4_0); - regp->CRTC[NV_CIO_CR_HRS_INDEX] = horizStart; - regp->CRTC[NV_CIO_CR_HRE_INDEX] = XLATE(horizBlankEnd, 5, NV_CIO_CR_HRE_HBE_5) | - XLATE(horizEnd, 0, NV_CIO_CR_HRE_4_0); - regp->CRTC[NV_CIO_CR_VDT_INDEX] = vertTotal; - regp->CRTC[NV_CIO_CR_OVL_INDEX] = XLATE(vertStart, 9, NV_CIO_CR_OVL_VRS_9) | - XLATE(vertDisplay, 9, NV_CIO_CR_OVL_VDE_9) | - XLATE(vertTotal, 9, NV_CIO_CR_OVL_VDT_9) | - (1 << 4) | - XLATE(vertBlankStart, 8, NV_CIO_CR_OVL_VBS_8) | - XLATE(vertStart, 8, NV_CIO_CR_OVL_VRS_8) | - XLATE(vertDisplay, 8, NV_CIO_CR_OVL_VDE_8) | - XLATE(vertTotal, 8, NV_CIO_CR_OVL_VDT_8); - regp->CRTC[NV_CIO_CR_RSAL_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_CELL_HT_INDEX] = ((mode->Flags & V_DBLSCAN) ? MASK(NV_CIO_CR_CELL_HT_SCANDBL) : 0) | - 1 << 6 | - XLATE(vertBlankStart, 9, NV_CIO_CR_CELL_HT_VBS_9); - regp->CRTC[NV_CIO_CR_CURS_ST_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_CURS_END_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_SA_HI_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_SA_LO_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_TCOFF_HI_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_TCOFF_LO_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_VRS_INDEX] = vertStart; - regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0); - regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay; - /* framebuffer can be larger than crtc scanout area. */ - regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = pScrn->displayWidth / 8 * pScrn->bitsPerPixel / 8; - regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00; - regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart; - regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd; - regp->CRTC[NV_CIO_CR_MODE_INDEX] = 0x43; - regp->CRTC[NV_CIO_CR_LCOMP_INDEX] = 0xff; - - /* - * Some extended CRTC registers (they are not saved with the rest of the vga regs). - */ - - /* framebuffer can be larger than crtc scanout area. */ - regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(pScrn->displayWidth / 8 * pScrn->bitsPerPixel / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); - regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->CrtcHDisplay < 1280 ? - MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00; - regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) | - XLATE(vertBlankStart, 10, NV_CIO_CRE_LSR_VBS_10) | - XLATE(vertStart, 10, NV_CIO_CRE_LSR_VRS_10) | - XLATE(vertDisplay, 10, NV_CIO_CRE_LSR_VDE_10) | - XLATE(vertTotal, 10, NV_CIO_CRE_LSR_VDT_10); - regp->CRTC[NV_CIO_CRE_HEB__INDEX] = XLATE(horizStart, 8, NV_CIO_CRE_HEB_HRS_8) | - XLATE(horizBlankStart, 8, NV_CIO_CRE_HEB_HBS_8) | - XLATE(horizDisplay, 8, NV_CIO_CRE_HEB_HDE_8) | - XLATE(horizTotal, 8, NV_CIO_CRE_HEB_HDT_8); - regp->CRTC[NV_CIO_CRE_EBR_INDEX] = XLATE(vertBlankStart, 11, NV_CIO_CRE_EBR_VBS_11) | - XLATE(vertStart, 11, NV_CIO_CRE_EBR_VRS_11) | - XLATE(vertDisplay, 11, NV_CIO_CRE_EBR_VDE_11) | - XLATE(vertTotal, 11, NV_CIO_CRE_EBR_VDT_11); - - if (mode->Flags & V_INTERLACE) { - horizTotal = (horizTotal >> 1) & ~1; - regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = horizTotal; - regp->CRTC[NV_CIO_CRE_HEB__INDEX] |= XLATE(horizTotal, 8, NV_CIO_CRE_HEB_ILC_8); - } else - regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = 0xff; /* interlace off */ - - /* - * Graphics Display Controller - */ - regp->Graphics[NV_VIO_GX_SR_INDEX] = 0x00; - regp->Graphics[NV_VIO_GX_SREN_INDEX] = 0x00; - regp->Graphics[NV_VIO_GX_CCOMP_INDEX] = 0x00; - regp->Graphics[NV_VIO_GX_ROP_INDEX] = 0x00; - regp->Graphics[NV_VIO_GX_READ_MAP_INDEX] = 0x00; - regp->Graphics[NV_VIO_GX_MODE_INDEX] = 0x40; /* 256 color mode */ - regp->Graphics[NV_VIO_GX_MISC_INDEX] = 0x05; /* map 64k mem + graphic mode */ - regp->Graphics[NV_VIO_GX_DONT_CARE_INDEX] = 0x0F; - regp->Graphics[NV_VIO_GX_BIT_MASK_INDEX] = 0xFF; - - regp->Attribute[0] = 0x00; /* standard colormap translation */ - regp->Attribute[1] = 0x01; - regp->Attribute[2] = 0x02; - regp->Attribute[3] = 0x03; - regp->Attribute[4] = 0x04; - regp->Attribute[5] = 0x05; - regp->Attribute[6] = 0x06; - regp->Attribute[7] = 0x07; - regp->Attribute[8] = 0x08; - regp->Attribute[9] = 0x09; - regp->Attribute[10] = 0x0A; - regp->Attribute[11] = 0x0B; - regp->Attribute[12] = 0x0C; - regp->Attribute[13] = 0x0D; - regp->Attribute[14] = 0x0E; - regp->Attribute[15] = 0x0F; - regp->Attribute[NV_CIO_AR_MODE_INDEX] = 0x01; /* Enable graphic mode */ - /* Non-vga */ - regp->Attribute[NV_CIO_AR_OSCAN_INDEX] = 0x00; - regp->Attribute[NV_CIO_AR_PLANE_INDEX] = 0x0F; /* enable all color planes */ - regp->Attribute[NV_CIO_AR_HPP_INDEX] = 0x00; - regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00; -} - -/** - * Sets up registers for the given mode/adjusted_mode pair. - * - * The clocks, CRTCs and outputs attached to this CRTC must be off. - * - * This shouldn't enable any clocks, CRTCs, or outputs, but they should - * be easily turned on/off after this. - */ -static void -nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - struct nouveau_crtc_state *savep = &pNv->saved_regs.head[nv_crtc->head]; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - bool lvds_output = false, tmds_output = false, off_chip_digital = false; - int i; - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - bool digital = false; - - if (output->crtc != crtc || !nv_encoder) - continue; - - if (nv_encoder->dcb->type == OUTPUT_LVDS) - digital = lvds_output = true; - if (nv_encoder->dcb->type == OUTPUT_TMDS) - digital = tmds_output = true; - if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital) - off_chip_digital = true; - } - - /* Registers not directly related to the (s)vga mode */ - - /* What is the meaning of this register? */ - /* A few popular values are 0x18, 0x1c, 0x38, 0x3c */ - regp->CRTC[NV_CIO_CRE_ENH_INDEX] = savep->CRTC[NV_CIO_CRE_ENH_INDEX] & ~(1<<5); - - regp->crtc_eng_ctrl = 0; - /* Except for rare conditions I2C is enabled on the primary crtc */ - if (nv_crtc->head == 0) - regp->crtc_eng_ctrl |= NV_CRTC_FSEL_I2C; - /* Set overlay to desired crtc. */ - if (pNv->overlayAdaptor) { - NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); - if (pPriv->overlayCRTC == nv_crtc->head) - regp->crtc_eng_ctrl |= NV_CRTC_FSEL_OVERLAY; - } - - /* ADDRESS_SPACE_PNVM is the same as setting HCUR_ASI */ - regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 | - NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 | - NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM; - if (pNv->alphaCursor) - regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32; - if (mode->Flags & V_DBLSCAN) - regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE; - - /* Unblock some timings */ - regp->CRTC[NV_CIO_CRE_53] = 0; - regp->CRTC[NV_CIO_CRE_54] = 0; - - /* 0x00 is disabled, 0x11 is lvds, 0x22 crt and 0x88 tmds */ - if (lvds_output) - regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x11; - else if (tmds_output) - regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x88; - else - regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x22; - - /* These values seem to vary */ - /* This register seems to be used by the bios to make certain decisions on some G70 cards? */ - regp->CRTC[NV_CIO_CRE_SCRATCH4__INDEX] = savep->CRTC[NV_CIO_CRE_SCRATCH4__INDEX]; - - nv_crtc_set_digital_vibrance(crtc, nv_crtc->saturation); - - /* probably a scratch reg, but kept for cargo-cult purposes: - * bit0: crtc0?, head A - * bit6: lvds, head A - * bit7: (only in X), head A - */ - if (nv_crtc->head == 0) - regp->CRTC[NV_CIO_CRE_4B] = savep->CRTC[NV_CIO_CRE_4B] | 0x80; - - /* The blob seems to take the current value from crtc 0, add 4 to that - * and reuse the old value for crtc 1 */ - regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] = pNv->saved_regs.head[0].CRTC[NV_CIO_CRE_TVOUT_LATENCY]; - if (!nv_crtc->head) - regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] += 4; - - /* the blob sometimes sets |= 0x10 (which is the same as setting |= - * 1 << 30 on 0x60.830), for no apparent reason */ - regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; - - regp->crtc_830 = mode->CrtcVDisplay - 3; - regp->crtc_834 = mode->CrtcVDisplay - 1; - - if (pNv->Architecture == NV_ARCH_40) - /* This is what the blob does */ - regp->crtc_850 = NVReadCRTC(pNv, 0, NV_PCRTC_850); - - if (pNv->Architecture == NV_ARCH_40) - regp->gpio_ext = NVReadCRTC(pNv, 0, NV_PCRTC_GPIO_EXT); - - regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; - - /* Some misc regs */ - if (pNv->Architecture == NV_ARCH_40) { - regp->CRTC[NV_CIO_CRE_85] = 0xFF; - regp->CRTC[NV_CIO_CRE_86] = 0x1; - } - - regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (pScrn->depth + 1) / 8; - /* Enable slaved mode (called MODE_TV in nv4ref.h) */ - if (lvds_output || tmds_output) - regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7); - - /* Generic PRAMDAC regs */ - - if (pNv->Architecture >= NV_ARCH_10) - /* Only bit that bios and blob set. */ - regp->nv10_cursync = (1 << 25); - - regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | - NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL | - NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; - if (pScrn->depth == 16) - regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; - if (pNv->alphaCursor) - regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; - - regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */ - - nv_crtc_set_image_sharpening(crtc, nv_crtc->sharpness); - - /* Some values the blob sets */ - regp->ramdac_a20 = 0x0; - regp->ramdac_a24 = 0xfffff; - regp->ramdac_a34 = 0x1; -} - -enum fp_display_regs { - FP_DISPLAY_END, - FP_TOTAL, - FP_CRTC, - FP_SYNC_START, - FP_SYNC_END, - FP_VALID_START, - FP_VALID_END -}; - -/* this could be set in nv_output, but would require some rework of load/save */ -static void -nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - struct nouveau_crtc_state *savep = &pNv->saved_regs.head[nv_crtc->head]; - struct nouveau_encoder *nv_encoder = NULL; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - uint32_t mode_ratio, panel_ratio; - int i; - - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - struct nouveau_encoder *tmp_nve = to_nouveau_encoder(output); - - if (output->crtc != crtc) - continue; - - if (IS_DFP(tmp_nve->dcb->type)) { - /* assumes a maximum of one fp output per crtc */ - nv_encoder = tmp_nve; - break; - } - } - if (!nv_encoder) - return; - - regp->fp_horiz_regs[FP_DISPLAY_END] = adjusted_mode->HDisplay - 1; - regp->fp_horiz_regs[FP_TOTAL] = adjusted_mode->HTotal - 1; - if (!pNv->gf4_disp_arch || - (adjusted_mode->HSyncStart - adjusted_mode->HDisplay) >= - pNv->vbios->digital_min_front_porch) - regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HDisplay; - else - regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HSyncStart - pNv->vbios->digital_min_front_porch - 1; - regp->fp_horiz_regs[FP_SYNC_START] = adjusted_mode->HSyncStart - 1; - regp->fp_horiz_regs[FP_SYNC_END] = adjusted_mode->HSyncEnd - 1; - regp->fp_horiz_regs[FP_VALID_START] = adjusted_mode->HSkew; - regp->fp_horiz_regs[FP_VALID_END] = adjusted_mode->HDisplay - 1; - - regp->fp_vert_regs[FP_DISPLAY_END] = adjusted_mode->VDisplay - 1; - regp->fp_vert_regs[FP_TOTAL] = adjusted_mode->VTotal - 1; - regp->fp_vert_regs[FP_CRTC] = adjusted_mode->VTotal - 5 - 1; - regp->fp_vert_regs[FP_SYNC_START] = adjusted_mode->VSyncStart - 1; - regp->fp_vert_regs[FP_SYNC_END] = adjusted_mode->VSyncEnd - 1; - regp->fp_vert_regs[FP_VALID_START] = 0; - regp->fp_vert_regs[FP_VALID_END] = adjusted_mode->VDisplay - 1; - - /* bit26: a bit seen on some g7x, no as yet discernable purpose */ - regp->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | - (savep->fp_control & (1 << 26 | NV_PRAMDAC_FP_TG_CONTROL_READ_PROG)); - /* Deal with vsync/hsync polarity */ - /* LVDS screens do set this, but modes with +ve syncs are very rare */ - if (adjusted_mode->Flags & V_PVSYNC) - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS; - if (adjusted_mode->Flags & V_PHSYNC) - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS; - /* panel scaling first, as native would get set otherwise */ - if (nv_encoder->scaling_mode == SCALE_PANEL || - nv_encoder->scaling_mode == SCALE_NOSCALE) /* panel handles it */ - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER; - else if (mode->HDisplay == adjusted_mode->HDisplay && - mode->VDisplay == adjusted_mode->VDisplay) /* native mode */ - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE; - else /* gpu needs to scale */ - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE; - if (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) - regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; - if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && - adjusted_mode->Clock > 165000) - regp->fp_control |= (2 << 24); - if (nv_encoder->dual_link) - regp->fp_control |= (8 << 28); - - regp->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND | - NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND | - NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR | - NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR | - NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED | - NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE | - NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE; - - /* We want automatic scaling */ - regp->fp_debug_1 = 0; - /* This can override HTOTAL and VTOTAL */ - regp->fp_debug_2 = 0; - - /* Use 20.12 fixed point format to avoid floats */ - mode_ratio = (1 << 12) * mode->HDisplay / mode->VDisplay; - panel_ratio = (1 << 12) * adjusted_mode->HDisplay / adjusted_mode->VDisplay; - /* if ratios are equal, SCALE_ASPECT will automatically (and correctly) - * get treated the same as SCALE_FULLSCREEN */ - if (nv_encoder->scaling_mode == SCALE_ASPECT && mode_ratio != panel_ratio) { - uint32_t diff, scale; - bool divide_by_2 = pNv->gf4_disp_arch; - - if (mode_ratio < panel_ratio) { - /* vertical needs to expand to glass size (automatic) - * horizontal needs to be scaled at vertical scale factor - * to maintain aspect */ - - scale = (1 << 12) * mode->VDisplay / adjusted_mode->VDisplay; - regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE | - XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE); - - /* restrict area of screen used, horizontally */ - diff = adjusted_mode->HDisplay - - adjusted_mode->VDisplay * mode_ratio / (1 << 12); - regp->fp_horiz_regs[FP_VALID_START] += diff / 2; - regp->fp_horiz_regs[FP_VALID_END] -= diff / 2; - } - - if (mode_ratio > panel_ratio) { - /* horizontal needs to expand to glass size (automatic) - * vertical needs to be scaled at horizontal scale factor - * to maintain aspect */ - - scale = (1 << 12) * mode->HDisplay / adjusted_mode->HDisplay; - regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE | - XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE); - - /* restrict area of screen used, vertically */ - diff = adjusted_mode->VDisplay - - (1 << 12) * adjusted_mode->HDisplay / mode_ratio; - regp->fp_vert_regs[FP_VALID_START] += diff / 2; - regp->fp_vert_regs[FP_VALID_END] -= diff / 2; - } - } - - /* Output property. */ - if (nv_encoder && nv_encoder->dithering) { - if (pNv->NVArch == 0x11) - regp->dither = savep->dither | 0x00010000; - else { - int i; - regp->dither = savep->dither | 0x00000001; - for (i = 0; i < 3; i++) { - regp->dither_regs[i] = 0xe4e4e4e4; - regp->dither_regs[i + 3] = 0x44444444; - } - } - } else { - if (pNv->NVArch != 0x11) { - /* reset them */ - int i; - for (i = 0; i < 3; i++) { - regp->dither_regs[i] = savep->dither_regs[i]; - regp->dither_regs[i + 3] = savep->dither_regs[i + 3]; - } - } - regp->dither = savep->dither; - } -} - -/** - * Sets up registers for the given mode/adjusted_mode pair. - * - * The clocks, CRTCs and outputs attached to this CRTC must be off. - * - * This shouldn't enable any clocks, CRTCs, or outputs, but they should - * be easily turned on/off after this. - */ -static void -nv_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode, - int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - NVPtr pNv = NVPTR(pScrn); - - NV_TRACE(pScrn, "CTRC mode on CRTC %d:\n", nv_crtc->head); - xf86PrintModeline(pScrn->scrnIndex, mode); - NV_TRACE(pScrn, "Output mode on CRTC %d:\n", nv_crtc->head); - xf86PrintModeline(pScrn->scrnIndex, adjusted_mode); - - /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ - nv_lock_vga_crtc_shadow(pNv, nv_crtc->head, -1); - - nv_crtc_mode_set_vga(crtc, mode, adjusted_mode); - /* calculated in output_prepare, nv40 needs it written before calculating PLLs */ - if (pNv->Architecture == NV_ARCH_40) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, pNv->set_state.sel_clk); - nv_crtc_mode_set_regs(crtc, mode); - nv_crtc_mode_set_fp_regs(crtc, mode, adjusted_mode); - nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->Clock); - - nouveau_hw_load_state(pScrn, nv_crtc->head, &pNv->set_state); - - NVCrtcSetBase(crtc, x, y); - -#if X_BYTE_ORDER == X_BIG_ENDIAN - /* turn on LFB swapping */ - { - uint8_t tmp = NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RCR); - tmp |= MASK(NV_CIO_CRE_RCR_ENDIAN_BIG); - NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RCR, tmp); - } -#endif -} - -static void nv_crtc_save(xf86CrtcPtr crtc) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - NVPtr pNv = NVPTR(crtc->scrn); - - if (pNv->twoHeads) - NVSetOwner(pNv, nv_crtc->head); - - nouveau_hw_save_state(crtc->scrn, nv_crtc->head, &pNv->saved_regs); - - /* init some state to saved value */ - pNv->set_state.sel_clk = pNv->saved_regs.sel_clk & ~(0x5 << 16); - nv_crtc->state->CRTC[NV_CIO_CRE_LCD__INDEX] = pNv->saved_regs.head[nv_crtc->head].CRTC[NV_CIO_CRE_LCD__INDEX]; -} - -static void nv_crtc_restore(xf86CrtcPtr crtc) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - NVPtr pNv = NVPTR(crtc->scrn); - int head = nv_crtc->head; - uint8_t saved_cr21 = pNv->saved_regs.head[head].CRTC[NV_CIO_CRE_21]; - - if (pNv->twoHeads) - NVSetOwner(pNv, head); - - nouveau_hw_load_state(crtc->scrn, head, &pNv->saved_regs); - nv_lock_vga_crtc_shadow(pNv, head, saved_cr21); - - nv_crtc->last_dpms = NV_DPMS_CLEARED; -} - -static void nv_crtc_prepare(xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - - if (pNv->twoHeads) - NVSetOwner(pNv, nv_crtc->head); - - crtc->funcs->dpms(crtc, DPMSModeOff); - - /* Sync the engine before adjust mode */ - if (pNv->EXADriverPtr) { - exaMarkSync(pScrn->pScreen); - exaWaitSync(pScrn->pScreen); - } - - NVBlankScreen(pNv, nv_crtc->head, true); - - /* Some more preperation. */ - NVWriteCRTC(pNv, nv_crtc->head, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); - if (pNv->Architecture == NV_ARCH_40) { - uint32_t reg900 = NVReadRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_900); - NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_900, reg900 & ~0x10000); - } -} - -static void nv_crtc_commit(xf86CrtcPtr crtc) -{ - crtc->funcs->dpms (crtc, DPMSModeOn); - - if (crtc->scrn->pScreen != NULL) { - NVPtr pNv = NVPTR(crtc->scrn); - - xf86_reload_cursors (crtc->scrn->pScreen); - if (!pNv->alphaCursor) { - /* this works round the fact that xf86_reload_cursors - * will quite happily show the hw cursor when it knows - * the hardware can't do alpha, and the current cursor - * has an alpha channel - */ - xf86ForceHWCursor(crtc->scrn->pScreen, 1); - xf86ForceHWCursor(crtc->scrn->pScreen, 0); - } - } -} - -static void nv_crtc_destroy(xf86CrtcPtr crtc) -{ - xfree(to_nouveau_crtc(crtc)); -} - -static Bool nv_crtc_lock(xf86CrtcPtr crtc) -{ - return FALSE; -} - -static void nv_crtc_unlock(xf86CrtcPtr crtc) -{ -} - -static void -nv_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, - int size) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - NVPtr pNv = NVPTR(crtc->scrn); - struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs; - int i; - - rgbs = (struct rgb *)nv_crtc->state->DAC; - - for (i = 0; i < 256; i++) { - rgbs[i].r = red[i] >> 8; - rgbs[i].g = green[i] >> 8; - rgbs[i].b = blue[i] >> 8; - } - - nouveau_hw_load_state_palette(pNv, nv_crtc->head, &pNv->set_state); -} - -/** - * Allocates memory for a locked-in-framebuffer shadow of the given - * width and height for this CRTC's rotated shadow framebuffer. - */ - -static void * -nv_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - ScrnInfoPtr pScrn = crtc->scrn; - ScreenPtr pScreen = pScrn->pScreen; - NVPtr pNv = NVPTR(pScrn); - void *offset; - int size, align = 64; - - nv_crtc->shadow_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8); - size = nv_crtc->shadow_pitch * height; - - assert(nv_crtc->shadow == NULL); - if (!pScreen) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Can't allocate shadow memory for rotated CRTC at server regeneration\n"); - return NULL; - } - nv_crtc->shadow = exaOffscreenAlloc(pScreen, size, align, TRUE, NULL, NULL); - if (nv_crtc->shadow == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow memory for rotated CRTC.\n"); - return NULL; - } - offset = pNv->offscreen_map + nv_crtc->shadow->offset; - - return offset; -} - -/** - * Creates a pixmap for this CRTC's rotated shadow framebuffer. - */ -static PixmapPtr -nv_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - ScrnInfoPtr pScrn = crtc->scrn; - PixmapPtr rotate_pixmap; - - if (!data) - data = crtc->funcs->shadow_allocate (crtc, width, height); - - rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, width, height, - pScrn->depth, - pScrn->bitsPerPixel, - nv_crtc->shadow_pitch, data); - if (rotate_pixmap == NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't allocate shadow pixmap for rotated CRTC\n"); - } - - return rotate_pixmap; -} - -static void -nv_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) -{ - ScrnInfoPtr pScrn = crtc->scrn; - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - ScreenPtr pScreen = pScrn->pScreen; - - if (rotate_pixmap) { /* This should also unmap the buffer object if relevant. */ - pScreen->DestroyPixmap(rotate_pixmap); - } - - if (data && nv_crtc->shadow) - exaOffscreenFree(pScreen, nv_crtc->shadow); - - nv_crtc->shadow = NULL; -} - -static const xf86CrtcFuncsRec nv_crtc_funcs = { - .dpms = nv_crtc_dpms, - .save = nv_crtc_save, - .restore = nv_crtc_restore, - .mode_fixup = nv_crtc_mode_fixup, - .mode_set = nv_crtc_mode_set, - .prepare = nv_crtc_prepare, - .commit = nv_crtc_commit, - .destroy = nv_crtc_destroy, - .lock = nv_crtc_lock, - .unlock = nv_crtc_unlock, - .set_cursor_colors = nv_crtc_set_cursor_colors, - .set_cursor_position = nv_crtc_set_cursor_position, - .show_cursor = nv_crtc_show_cursor, - .hide_cursor = nv_crtc_hide_cursor, - .load_cursor_image = nv_crtc_load_cursor_image, - .load_cursor_argb = nv_crtc_load_cursor_argb, - .gamma_set = nv_crtc_gamma_set, - .shadow_create = nv_crtc_shadow_create, - .shadow_allocate = nv_crtc_shadow_allocate, - .shadow_destroy = nv_crtc_shadow_destroy, -#ifdef RANDR_13_INTERFACE - .set_origin = NVCrtcSetBase, -#endif -}; - -void -nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num) -{ - NVPtr pNv = NVPTR(pScrn); - static xf86CrtcFuncsRec crtcfuncs; - xf86CrtcPtr crtc; - struct nouveau_crtc *nv_crtc; - int i; - - crtcfuncs = nv_crtc_funcs; - - if (!pNv->alphaCursor) - crtcfuncs.load_cursor_argb = NULL; - if (pNv->NoAccel) { - crtcfuncs.shadow_create = NULL; - crtcfuncs.shadow_allocate = NULL; - crtcfuncs.shadow_destroy = NULL; - } - - if (!(crtc = xf86CrtcCreate(pScrn, &crtcfuncs))) - return; - - if (!(nv_crtc = xcalloc(1, sizeof (struct nouveau_crtc)))) { - xf86CrtcDestroy(crtc); - return; - } - - nv_crtc->head = crtc_num; - nv_crtc->last_dpms = NV_DPMS_CLEARED; - nv_crtc->state = &pNv->set_state.head[crtc_num]; - - crtc->driver_private = nv_crtc; - - /* Initialise the default LUT table. */ - for (i = 0; i < 256; i++) { - nv_crtc->state->DAC[i*3] = i; - nv_crtc->state->DAC[(i*3)+1] = i; - nv_crtc->state->DAC[(i*3)+2] = i; - } -} - -void NVCrtcSetBase(xf86CrtcPtr crtc, int x, int y) -{ - ScrnInfoPtr pScrn = crtc->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - struct nouveau_crtc_state *regp = nv_crtc->state; - struct nouveau_bo *bo; - uint32_t start, pitch; - - bo = pNv->scanout; - pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); - if (crtc->rotatedData != NULL) { - pitch = nv_crtc->shadow_pitch; - bo = pNv->offscreen; - x = 0; - y = 0; - } - - if (nv_crtc->bo) - nouveau_bo_unpin(nv_crtc->bo); - nouveau_bo_pin(bo, NOUVEAU_BO_VRAM); - nv_crtc->bo = bo; - - start = nv_crtc->bo->offset; - start += (y * pScrn->displayWidth + x) * pScrn->bitsPerPixel / 8; - if (crtc->rotatedData != NULL) - start += nv_crtc->shadow->offset; - - regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = pitch >> 3; - regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = - XLATE(pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8); - crtc_wr_cio_state(crtc, NV_CIO_CRE_RPC0_INDEX); - crtc_wr_cio_state(crtc, NV_CIO_CR_OFFSET_INDEX); - - start &= ~3; - nv_crtc->state->fb_start = start; - NVWriteCRTC(pNv, nv_crtc->head, NV_PCRTC_START, start); - - crtc->x = x; - crtc->y = y; -} diff --git a/src/nv_cursor.c b/src/nv_cursor.c deleted file mode 100644 index 3df1539..0000000 --- a/src/nv_cursor.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2003 NVIDIA, Corporation - * Copyright 2007 Maarten Maathuis - * Copyright 2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -#define TO_ARGB1555(c) (0x8000 | /* Mask bit */ \ - ((c & 0xf80000) >> 9 ) | /* Red */ \ - ((c & 0xf800) >> 6 ) | /* Green */ \ - ((c & 0xf8) >> 3 )) /* Blue */ -#define TO_ARGB8888(c) (0xff000000 | c) - -#define SOURCE_MASK_INTERLEAVE 32 -#define TRANSPARENT_PIXEL 0 - -/* - * Convert a source/mask bitmap cursor to an ARGB cursor, clipping or - * padding as necessary. source/mask are assumed to be alternated each - * SOURCE_MASK_INTERLEAVE bits. - */ -void -nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride, - int bpp, uint32_t fg, uint32_t bg) -{ - int width = min(src_stride, dst_stride); - uint32_t b, m, pxval; - int i, j, k; - - for (i = 0; i < width; i++) { - for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) { - int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j; - int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE; - - b = src[2*src_off]; - m = src[2*src_off + 1]; - - for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) { - pxval = TRANSPARENT_PIXEL; -#if X_BYTE_ORDER == X_BIG_ENDIAN - if (m & 0x80000000) - pxval = (b & 0x80000000) ? fg : bg; - b <<= 1; - m <<= 1; -#else - if (m & 1) - pxval = (b & 1) ? fg : bg; - b >>= 1; - m >>= 1; -#endif - if (bpp == 32) - ((uint32_t *)dst)[dst_off + k] = pxval; - else - ((uint16_t *)dst)[dst_off + k] = pxval; - } - } - } -} - -static void nv_cursor_transform_cursor(NVPtr pNv, struct nouveau_crtc *nv_crtc) -{ - uint16_t *tmp; - struct nouveau_bo *cursor = NULL; - int px = nv_cursor_pixels(pNv); - int width = nv_cursor_width(pNv); - - if (!(tmp = xcalloc(px, 4))) - return; - - /* convert to colour cursor */ - nv_cursor_convert_cursor(pNv->curImage, tmp, width, width, - pNv->alphaCursor ? 32 : 16, nv_crtc->cursor_fg, - nv_crtc->cursor_bg); - - nouveau_bo_ref(nv_crtc->head ? pNv->Cursor2 : pNv->Cursor, &cursor); - nouveau_bo_map(cursor, NOUVEAU_BO_WR); - - memcpy(cursor->map, tmp, px * 4); - - nouveau_bo_unmap(cursor); - nouveau_bo_ref(NULL, &cursor); - - xfree(tmp); -} - -void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg) -{ - NVPtr pNv = NVPTR(crtc->scrn); - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - uint32_t fore, back; - - if (pNv->alphaCursor) { - fore = TO_ARGB8888(fg); - back = TO_ARGB8888(bg); -#if X_BYTE_ORDER == X_BIG_ENDIAN - if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) { - fore = lswapl(fore); - back = lswapl(back); - } -#endif - } else { - fore = TO_ARGB1555(fg); - back = TO_ARGB1555(bg); - } - - if (nv_crtc->cursor_fg != fore || nv_crtc->cursor_bg != back) { - nv_crtc->cursor_fg = fore; - nv_crtc->cursor_bg = back; - nv_cursor_transform_cursor(pNv, nv_crtc); - } -} - -void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image) -{ - NVPtr pNv = NVPTR(crtc->scrn); - - /* save copy of image for colour changes */ - memcpy(pNv->curImage, image, nv_cursor_pixels(pNv) / 4); - - nv_cursor_transform_cursor(pNv, to_nouveau_crtc(crtc)); -} - -void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) -{ - NVPtr pNv = NVPTR(crtc->scrn); - int head = to_nouveau_crtc(crtc)->head, i, alpha; - struct nouveau_bo *cursor = NULL; - uint32_t *dst, *src = (uint32_t *)image, tmp; - - nouveau_bo_ref(head ? pNv->Cursor2 : pNv->Cursor, &cursor); - nouveau_bo_map(cursor, NOUVEAU_BO_WR); - dst = cursor->map; - - /* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha - * cursors (though NPM in combination with fp dithering may not work on - * nv11, from "nv" driver history) - * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the - * blob uses, however we get given PM cursors so we use PM mode - */ - for (i = 0; i < nv_cursor_pixels(pNv); i++) { - /* hw gets unhappy if alpha <= rgb values. for a PM image "less - * than" shouldn't happen; fix "equal to" case by adding one to - * alpha channel (slightly inaccurate, but so is attempting to - * get back to NPM images, due to limits of integer precision) - */ - alpha = (*src >> 24); - if (!alpha || alpha == 0xff) - /* alpha == max(r,g,b) works ok for 0x0 and 0xff */ - tmp = *src; - else - tmp = ((alpha + 1) << 24) | (*src & 0xffffff); -#if X_BYTE_ORDER == X_BIG_ENDIAN - if (pNv->NVArch == 0x11) - tmp = lswapl(tmp); -#endif - *dst++ = tmp; - src++; - } - - nouveau_bo_unmap(cursor); - nouveau_bo_ref(NULL, &cursor); -} - -void nv_crtc_show_cursor(xf86CrtcPtr crtc) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - - nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, true); -} - -void nv_crtc_hide_cursor(xf86CrtcPtr crtc) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - - nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, false); -} - -void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y) -{ - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc); - NVPtr pNv = NVPTR(crtc->scrn); - - NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_CU_START_POS, - XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) | - XLATE(x, 0, NV_PRAMDAC_CU_START_POS_X)); -} - -Bool NVCursorInitRandr12(ScreenPtr pScreen) -{ - NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]); - int width = nv_cursor_width(pNv); - int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | - (pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0); - - return xf86_cursors_init(pScreen, width, width, flags); -} diff --git a/src/nv_dma.c b/src/nv_dma.c index ed51b9f..c3d7639 100644 --- a/src/nv_dma.c +++ b/src/nv_dma.c @@ -23,7 +23,6 @@ #include #include "nv_include.h" -#include "nvreg.h" static void NVLockedUp(ScrnInfoPtr pScrn) diff --git a/src/nv_driver.c b/src/nv_driver.c index a0656af..4f39eb5 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -27,9 +27,7 @@ #include "xorg-server.h" #include "xf86int10.h" #include "xf86drm.h" -#ifdef XF86DRM_MODE #include "xf86drmMode.h" -#endif /* * Forward definitions for the functions that make up the driver. @@ -55,8 +53,6 @@ static void NVFreeScreen(int scrnIndex, int flags); static Bool NVMapMem(ScrnInfoPtr pScrn); static Bool NVUnmapMem(ScrnInfoPtr pScrn); -static void NVSave(ScrnInfoPtr pScrn); -static void NVRestore(ScrnInfoPtr pScrn); #define NOUVEAU_PCI_DEVICE(_vendor_id, _device_id) \ { (_vendor_id), (_device_id), PCI_MATCH_ANY, PCI_MATCH_ANY, \ @@ -323,50 +319,8 @@ void NVAdjustFrame(int scrnIndex, int x, int y, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; - NVPtr pNv = NVPTR(pScrn); - - if (pNv->kms_enable) { - drmmode_adjust_frame(pScrn, x, y, flags); - } else { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - xf86CrtcPtr crtc = config->output[config->compat_output]->crtc; - - if (crtc && crtc->enabled) - NVCrtcSetBase(crtc, x, y); - } -} -static Bool -NV50AcquireDisplay(ScrnInfoPtr pScrn) -{ - if (!NV50DispInit(pScrn)) - return FALSE; - if (!NV50CursorAcquire(pScrn)) - return FALSE; - - return TRUE; -} - -static Bool -NV50ReleaseDisplay(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - - NV50CursorRelease(pScrn); - NV50DispShutdown(pScrn); - - if (pNv->pInt10 && pNv->Int10Mode) { - xf86Int10InfoPtr pInt10 = pNv->pInt10; - - pInt10->num = 0x10; - pInt10->ax = 0x4f02; - pInt10->bx = pNv->Int10Mode | 0x8000; - pInt10->cx = - pInt10->dx = 0; - xf86ExecX86int10(pInt10); - } - - return TRUE; + drmmode_adjust_frame(pScrn, x, y, flags); } /* @@ -393,23 +347,6 @@ NVEnterVT(int scrnIndex, int flags) if (!pNv->NoAccel) NVAccelCommonInit(pScrn); - if (!pNv->kms_enable) { - /* Save current state, VGA fonts etc */ - NVSave(pScrn); - - /* Clear the framebuffer, we don't want to see garbage - * on-screen up until X decides to draw something - */ - nouveau_bo_map(pNv->scanout, NOUVEAU_BO_WR); - memset(pNv->scanout->map, 0, pNv->scanout->size); - nouveau_bo_unmap(pNv->scanout); - - if (pNv->Architecture == NV_ARCH_50) { - if (!NV50AcquireDisplay(pScrn)) - return FALSE; - } - } - pNv->allow_dpms = FALSE; if (!xf86SetDesiredModes(pScrn)) return FALSE; @@ -443,13 +380,6 @@ NVLeaveVT(int scrnIndex, int flags) ret = drmDropMaster(nouveau_device(pNv->dev)->fd); if (ret) ErrorF("Error dropping master: %d\n", ret); - - if (!pNv->kms_enable) { - if (pNv->Architecture < NV_ARCH_50) - NVRestore(pScrn); - else - NV50ReleaseDisplay(pScrn); - } } static void @@ -577,97 +507,10 @@ NVFreeScreen(int scrnIndex, int flags) NVCloseDRM(pScrn); - if (pNv->Architecture == NV_ARCH_50 && !pNv->kms_enable) { - NV50ConnectorDestroy(pScrn); - NV50OutputDestroy(pScrn); - NV50CrtcDestroy(pScrn); - } - - /* Free this here and not in CloseScreen, as it's needed after the first server generation. */ - if (pNv->pInt10) - xf86FreeInt10(pNv->pInt10); - xfree(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } -static Bool -nouveau_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - ScreenPtr screen = screenInfo.screens[scrn->scrnIndex]; - NVPtr pNv = NVPTR(scrn); - uint32_t pitch, old_width, old_height, old_pitch; - struct nouveau_bo *old_bo = NULL; - uint32_t tile_mode = 0, tile_flags = 0, ah = height; - PixmapPtr ppix = screen->GetScreenPixmap(screen); - int ret, i; - - ErrorF("resize called %d %d\n", width, height); - - if (scrn->virtualX == width && scrn->virtualY == height) - return TRUE; - - pitch = nv_pitch_align(pNv, width, scrn->depth); - pitch *= (scrn->bitsPerPixel >> 3); - - old_width = scrn->virtualX; - old_height = scrn->virtualY; - old_pitch = scrn->displayWidth; - nouveau_bo_ref(pNv->scanout, &old_bo); - nouveau_bo_ref(NULL, &pNv->scanout); - - scrn->virtualX = width; - scrn->virtualY = height; - scrn->displayWidth = pitch / (scrn->bitsPerPixel >> 3); - - ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, - 0, pitch * ah, tile_mode, tile_flags, - &pNv->scanout); - if (ret) - goto fail; - - if (pNv->ShadowPtr) { - xfree(pNv->ShadowPtr); - pNv->ShadowPitch = pitch; - pNv->ShadowPtr = xalloc(pNv->ShadowPitch * height); - } - - nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR); - screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, - (!pNv->NoAccel || pNv->ShadowFB) ? - pNv->ShadowPtr : pNv->scanout->map); - scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; - nouveau_bo_unmap(pNv->scanout); - - for (i = 0; i < xf86_config->num_crtc; i++) { - xf86CrtcPtr crtc = xf86_config->crtc[i]; - - if (!crtc->enabled) - continue; - - xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation, - crtc->x, crtc->y); - } - - nouveau_bo_ref(NULL, &old_bo); - - NVDRIFinishScreenInit(scrn, true); - return TRUE; - - fail: - nouveau_bo_ref(old_bo, &pNv->scanout); - scrn->virtualX = old_width; - scrn->virtualY = old_height; - scrn->displayWidth = old_pitch; - - return FALSE; -} - -static const xf86CrtcConfigFuncsRec nv_xf86crtc_config_funcs = { - nouveau_xf86crtc_resize -}; - #define NVPreInitFail(fmt, args...) do { \ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%d: "fmt, __LINE__, ##args); \ NVFreeScreen(pScrn->scrnIndex, 0); \ @@ -736,14 +579,14 @@ NVPreInitDRM(ScrnInfoPtr pScrn) /* Check if KMS is enabled before we do anything, we don't want to * go stomping on registers behind its back */ -#ifdef XF86DRM_MODE - pNv->kms_enable = !drmCheckModesettingSupported(bus_id); -#endif - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "[drm] kernel modesetting %s\n", pNv->kms_enable ? - "in use" : "not available"); - + if (drmCheckModesettingSupported(bus_id)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] kernel modesetting not available\n"); + xfree(bus_id); + return FALSE; + } xfree(bus_id); + return TRUE; } @@ -852,35 +695,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } - /* Initialize the card through int10 interface if needed */ - if (xf86LoadSubModule(pScrn, "int10")) { -#if !defined(__alpha__) && !defined(__powerpc__) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n"); - pNv->pInt10 = xf86InitInt10(pNv->pEnt->index); -#endif - } - /* Initialise the kernel module */ if (!NVPreInitDRM(pScrn)) NVPreInitFail("\n"); - /* Save current console video mode */ - if (pNv->Architecture >= NV_ARCH_50 && pNv->pInt10 && !pNv->kms_enable) { - const xf86Int10InfoPtr pInt10 = pNv->pInt10; - - pInt10->num = 0x10; - pInt10->ax = 0x4f03; - pInt10->bx = - pInt10->cx = - pInt10->dx = 0; - xf86ExecX86int10(pInt10); - pNv->Int10Mode = pInt10->bx & 0x3fff; - - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, - "VESA-HACK: Console VGA mode is 0x%x\n", - pNv->Int10Mode); - } - /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; @@ -899,8 +717,8 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) break; case 30: /* OK on NV50 KMS */ - if (!pNv->kms_enable || pNv->Architecture != NV_ARCH_50) - NVPreInitFail("Depth 30 supported on G80+KMS only\n"); + if (pNv->Architecture != NV_ARCH_50) + NVPreInitFail("Depth 30 supported on G80 only\n"); break; case 15: /* 15 may get done one day, so leave any code for it in place */ default: @@ -978,13 +796,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", pNv->HWCursor ? "HW" : "SW"); - pNv->FpScale = TRUE; - - if (xf86GetOptValBool(pNv->Options, OPTION_FP_SCALE, &pNv->FpScale)) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Flat panel scaling %s\n", - pNv->FpScale ? "on" : "off"); - } - if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { pNv->NoAccel = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); @@ -1000,16 +811,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) #if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5) || EXA_VERSION_MAJOR > 2 if (!pNv->NoAccel && xf86ReturnOptValBool(pNv->Options, OPTION_EXA_PIXMAPS, TRUE)) { - if (pNv->kms_enable) { - pNv->exa_driver_pixmaps = TRUE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "EXAPixmaps support requires KMS\n"); - } + pNv->exa_driver_pixmaps = TRUE; } - if (!pNv->NoAccel && pNv->kms_enable && - pNv->Architecture >= NV_ARCH_50) { + if (!pNv->NoAccel && pNv->Architecture >= NV_ARCH_50) { pNv->wfb_enabled = TRUE; pNv->tiled_scanout = TRUE; } @@ -1024,113 +829,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags) (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); } - pNv->FPDither = FALSE; - if (xf86GetOptValBool(pNv->Options, OPTION_FP_DITHER, &(pNv->FPDither))) - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "enabling flat panel dither\n"); - - if (pNv->pEnt->device->MemBase != 0) { - /* Require that the config file value matches one of the PCI values. */ - if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->MemBase)) { - NVPreInitFail( - "MemBase 0x%08lX doesn't match any PCI base register.\n", - pNv->pEnt->device->MemBase); - } - pNv->VRAMPhysical = pNv->pEnt->device->MemBase; - from = X_CONFIG; - } else { - if (pNv->PciInfo->regions[1].base_addr != 0) { - pNv->VRAMPhysical = pNv->PciInfo->regions[1].base_addr & 0xff800000; - from = X_PROBED; - } else { - NVPreInitFail("No valid FB address in PCI config space\n"); - return FALSE; - } - } - xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", - (unsigned long)pNv->VRAMPhysical); - - if (pNv->pEnt->device->IOBase != 0) { - /* Require that the config file value matches one of the PCI values. */ - if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->IOBase)) { - NVPreInitFail("IOBase 0x%08lX doesn't match any PCI base register.\n", - pNv->pEnt->device->IOBase); - } - pNv->IOAddress = pNv->pEnt->device->IOBase; - from = X_CONFIG; - } else { - if (pNv->PciInfo->regions[0].base_addr != 0) { - pNv->IOAddress = pNv->PciInfo->regions[0].base_addr & 0xffffc000; - from = X_PROBED; - } else { - NVPreInitFail("No valid MMIO address in PCI config space\n"); - } - } - xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", - (unsigned long)pNv->IOAddress); - -#ifdef XF86DRM_MODE - if (pNv->kms_enable){ - ret = drmmode_pre_init(pScrn, nouveau_device(pNv->dev)->fd, - pScrn->bitsPerPixel >> 3); - if (ret == FALSE) - NVPreInitFail("Kernel modesetting failed to initialize\n"); - } else -#endif - { - int max_width, max_height; - - if (pNv->Architecture < NV_ARCH_10) { - max_width = (pScrn->bitsPerPixel > 16) ? 2032 : 2048; - max_height = 2048; - } else if (pNv->Architecture < NV_ARCH_50) { - max_width = (pScrn->bitsPerPixel > 16) ? 4080 : 4096; - max_height = 4096; - } else { - max_width = (pScrn->bitsPerPixel > 16) ? 8176 : 8192; - max_height = 8192; - } - - /* Allocate an xf86CrtcConfig */ - xf86CrtcConfigInit(pScrn, &nv_xf86crtc_config_funcs); - xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); - } - - NVCommonSetup(pScrn); - - if (!pNv->kms_enable) { - if (pNv->Architecture == NV_ARCH_50) - if (!NV50DispPreInit(pScrn)) - NVPreInitFail("\n"); - - /* This is the internal system, not the randr-1.2 ones. */ - if (pNv->Architecture == NV_ARCH_50) { - NV50CrtcInit(pScrn); - NV50ConnectorInit(pScrn); - NV50OutputSetup(pScrn); - } - - for (i = 0; i <= pNv->twoHeads; i++) { - if (pNv->Architecture == NV_ARCH_50) - nv50_crtc_init(pScrn, i); - else - nv_crtc_init(pScrn, i); - } - - if (pNv->Architecture < NV_ARCH_50) { - NVLockVgaCrtcs(pNv, false); - NvSetupOutputs(pScrn); - } else - nv50_output_create(pScrn); /* create randr-1.2 "outputs". */ - - if (!xf86InitialConfiguration(pScrn, TRUE)) - NVPreInitFail("No valid modes.\n"); - } - - pScrn->videoRam = pNv->RamAmountKBytes; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kBytes\n", - pScrn->videoRam); - - pNv->VRAMPhysicalSize = pScrn->videoRam * 1024; + ret = drmmode_pre_init(pScrn, nouveau_device(pNv->dev)->fd, + pScrn->bitsPerPixel >> 3); + if (ret == FALSE) + NVPreInitFail("Kernel modesetting failed to initialize\n"); /* * If the driver can do gamma correction, it should call xf86SetGamma() @@ -1187,16 +889,13 @@ static Bool NVMapMem(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); + struct nouveau_device *dev = pNv->dev; uint64_t res; uint32_t tile_mode = 0, tile_flags = 0; int ret, size; - nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_FB_SIZE, &res); - pNv->VRAMSize=res; - nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_FB_PHYSICAL, &res); + nouveau_device_get_param(dev, NOUVEAU_GETPARAM_FB_PHYSICAL, &res); pNv->VRAMPhysical=res; - nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_AGP_SIZE, &res); - pNv->AGPSize=res; size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { @@ -1207,7 +906,7 @@ NVMapMem(ScrnInfoPtr pScrn) size *= pScrn->virtualY; } - ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, + ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 0, size, tile_mode, tile_flags, &pNv->scanout); if (ret) { @@ -1220,17 +919,17 @@ NVMapMem(ScrnInfoPtr pScrn) nouveau_bo_unmap(pNv->scanout); if (pNv->NoAccel) - goto skip_offscreen_gart; + return TRUE; if (!pNv->exa_driver_pixmaps) { - size = (pNv->VRAMPhysicalSize / 2) - size; + size = (dev->vm_vram_size / 2) - size; if (pNv->Architecture >= NV_ARCH_50) { tile_mode = 0; tile_flags = 0x7000; } - ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | + ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 0, size, tile_mode, tile_flags, &pNv->offscreen); if (ret) { @@ -1248,22 +947,16 @@ NVMapMem(ScrnInfoPtr pScrn) nouveau_bo_unmap(pNv->offscreen); } - if (pNv->AGPSize) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "AGPGART: %dMiB available\n", - (unsigned int)(pNv->AGPSize >> 20)); - if (pNv->AGPSize > (16*1024*1024)) - size = 16*1024*1024; - else - /* always leave 512kb for other things like the fifos */ - size = pNv->AGPSize - 512*1024; - } else { - size = (4 << 20) - (1 << 18) ; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "GART: PCI DMA - using %dKiB\n", size >> 10); - } - if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: %dMiB available\n", + (unsigned int)(dev->vm_gart_size >> 20)); + if (dev->vm_gart_size > (16 * 1024 * 1024)) + size = 16 * 1024 * 1024; + else + /* always leave 512kb for other things like the fifos */ + size = dev->vm_gart_size - 512*1024; + + if (nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, size, &pNv->GART)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to allocate GART memory\n"); @@ -1274,56 +967,6 @@ NVMapMem(ScrnInfoPtr pScrn) (unsigned int)(pNv->GART->size >> 20)); } -skip_offscreen_gart: - /* We don't need to allocate cursors / lut here if we're using - * kernel modesetting - **/ - if (pNv->kms_enable) - return TRUE; - - if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN | - NOUVEAU_BO_MAP, 0, 64 * 64 * 4, &pNv->Cursor)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for hardware cursor\n"); - return FALSE; - } - - if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN | - NOUVEAU_BO_MAP, 0, 64 * 64 * 4, &pNv->Cursor2)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for hardware cursor\n"); - return FALSE; - } - - /* This is not the ideal solution, but significant changes are needed - * otherwise. Ideally you do this once upon preinit, but drm is - * closed between screen inits. - */ - if (pNv->Architecture == NV_ARCH_50) { - int i; - - for(i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - - if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | - NOUVEAU_BO_PIN | - NOUVEAU_BO_MAP, 0, 0x1000, - &crtc->lut)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate memory for lut %d\n", i); - return FALSE; - } - - /* Copy the last known values. */ - if (crtc->lut_values_valid) { - nouveau_bo_map(crtc->lut, NOUVEAU_BO_WR); - memcpy(crtc->lut->map, crtc->lut_values, - 4 * 256 * sizeof(uint16_t)); - nouveau_bo_unmap(crtc->lut); - } - } - } - return TRUE; } @@ -1336,67 +979,14 @@ NVUnmapMem(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); - if (!pNv->dev) { - pci_device_unmap_range(pNv->PciInfo, pNv->VRAMMap, - pNv->PciInfo->regions[1].size); - } + drmmode_remove_fb(pScrn); -#ifdef XF86DRM_MODE - if (pNv->kms_enable) - drmmode_remove_fb(pScrn); -#endif nouveau_bo_ref(NULL, &pNv->scanout); nouveau_bo_ref(NULL, &pNv->offscreen); nouveau_bo_ref(NULL, &pNv->GART); - nouveau_bo_ref(NULL, &pNv->Cursor); - nouveau_bo_ref(NULL, &pNv->Cursor2); - - /* Again not the most ideal way. */ - if (pNv->Architecture == NV_ARCH_50 && !pNv->kms_enable) { - int i; - - for(i = 0; i < 2; i++) { - nouveauCrtcPtr crtc = pNv->crtc[i]; - - nouveau_bo_ref(NULL, &crtc->lut); - } - } - return TRUE; } - -/* - * Restore the initial (text) mode. - */ -static void -NVRestore(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - - NVLockVgaCrtcs(pNv, false); - - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring encoders\n"); - for (i = 0; i < pNv->vbios->dcb->entries; i++) - nv_encoder_restore(pScrn, &pNv->encoders[i]); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring crtcs\n"); - for (i = 0; i < xf86_config->num_crtc; i++) - xf86_config->crtc[i]->funcs->restore(xf86_config->crtc[i]); - - nouveau_hw_save_vga_fonts(pScrn, 0); - - if (pNv->twoHeads) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring CRTC_OWNER to %d.\n", pNv->vtOWNER); - NVSetOwner(pNv, pNv->vtOWNER); - } - - NVLockVgaCrtcs(pNv, true); -} - static void NVLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO * colors, VisualPtr pVisual) @@ -1504,9 +1094,6 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) for (i = 0; i < xf86_config->num_output; i++) xf86_config->output[i]->scrn = pScrn; - if (!pNv->kms_enable) - NVSave(pScrn); - /* * The next step is to setup the screen's visuals, and initialise the * framebuffer code. In cases where the framebuffer's default @@ -1601,14 +1188,8 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); - if (!pNv->NoAccel) { - if (!nouveau_exa_init(pScreen)) - return FALSE; - } else if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n"); + if (!pNv->NoAccel && !nouveau_exa_init(pScreen)) return FALSE; - } - miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -1632,17 +1213,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * Must follow software cursor initialization. */ if (pNv->HWCursor) { - if (pNv->kms_enable) - ret = drmmode_cursor_init(pScreen); - else - if (pNv->Architecture < NV_ARCH_50) - ret = NVCursorInitRandr12(pScreen); - else - ret = NV50CursorInit(pScreen); - + ret = drmmode_cursor_init(pScreen); if (ret != TRUE) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Hardware cursor initialization failed\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); pNv->HWCursor = FALSE; } } @@ -1665,8 +1239,7 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScrn->vtSema = TRUE; pScrn->pScreen = pScreen; - if (pNv->kms_enable) - drmmode_fbcon_copy(pScrn); + drmmode_fbcon_copy(pScrn); if (!NVEnterVT(pScrn->scrnIndex, 0)) return FALSE; @@ -1705,44 +1278,6 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) static Bool NVSaveScreen(ScreenPtr pScreen, int mode) { - ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - NVPtr pNv = NVPTR(pScrn); - bool on = xf86IsUnblank(mode); - int i; - - if (pScrn->vtSema && pNv->Architecture < NV_ARCH_50) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - - for (i = 0; i < xf86_config->num_crtc; i++) { - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(xf86_config->crtc[i]); - - if (xf86_config->crtc[i]->enabled) - NVBlankScreen(pNv, nv_crtc->head, !on); - } - } - return TRUE; } -static void -NVSave(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - NVPtr pNv = NVPTR(pScrn); - int i; - - if (pNv->Architecture == NV_ARCH_50) - return; - - NVLockVgaCrtcs(pNv, false); - - nouveau_hw_save_vga_fonts(pScrn, 1); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Saving crtcs\n"); - for (i = 0; i < xf86_config->num_crtc; i++) - xf86_config->crtc[i]->funcs->save(xf86_config->crtc[i]); - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Saving encoders\n"); - for (i = 0; i < pNv->vbios->dcb->entries; i++) - nv_encoder_save(pScrn, &pNv->encoders[i]); -} diff --git a/src/nv_i2c.c b/src/nv_i2c.c deleted file mode 100644 index e8b2e29..0000000 --- a/src/nv_i2c.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2006 Stephane Marchesin - * Copyright 2007 Maarten Maathuis - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -/* - * DDC1 support only requires DDC_SDA_MASK, - * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK - */ -#define DDC_SDA_READ_MASK (1 << 3) -#define DDC_SCL_READ_MASK (1 << 2) -#define DDC_SDA_WRITE_MASK (1 << 4) -#define DDC_SCL_WRITE_MASK (1 << 5) - -static void -NVI2CGetBits(I2CBusPtr b, int *clock, int *data) -{ - NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); - struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr; - unsigned char val; - - /* Get the result. */ - /* Doing this on head 0 seems fine. */ - if (dcb_i2c->port_type == 4) /* C51 */ - val = NVReadCRTC(pNv, 0, 0x600800 + dcb_i2c->read) >> 16; - else - val = NVReadVgaCrtc(pNv, 0, dcb_i2c->read); - - *clock = (val & DDC_SCL_READ_MASK) != 0; - *data = (val & DDC_SDA_READ_MASK) != 0; -} - -static void -NVI2CPutBits(I2CBusPtr b, int clock, int data) -{ - NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); - struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr; - uint32_t val; - - /* Doing this on head 0 seems fine. */ - if (dcb_i2c->port_type == 4) /* C51 */ - val = NVReadCRTC(pNv, 0, 0x600800 + dcb_i2c->write); - else - val = NVReadVgaCrtc(pNv, 0, dcb_i2c->write); - - val = (val & ~0xf) | 1; - - if (clock) - val |= DDC_SCL_WRITE_MASK; - else - val &= ~DDC_SCL_WRITE_MASK; - - if (data) - val |= DDC_SDA_WRITE_MASK; - else - val &= ~DDC_SDA_WRITE_MASK; - - /* Doing this on head 0 seems fine. */ - if (dcb_i2c->port_type == 4) /* C51 */ - NVWriteCRTC(pNv, 0, 0x600800 + dcb_i2c->write, val); - else - NVWriteVgaCrtc(pNv, 0, dcb_i2c->write, val); -} - -static uint32_t NV50_GetI2CPort(ScrnInfoPtr pScrn, int index) -{ - NVPtr pNv = NVPTR(pScrn); - - if (index <= 3) - return 0xe138 + (index * 24); - - /* I have my doubts that this is 100% correct everywhere, - * but this is the best guess based on the data we have. - */ - if (pNv->NVArch >= 0x90) /* 0x90, 0xA0 */ - return 0xe1d4 + (index * 32); - return 0xe1e0 + (index * 24); -} - -static void NV50_I2CPutBits(I2CBusPtr b, int clock, int data) -{ - NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); - struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr; - - NVWrite(pNv, NV50_GetI2CPort(xf86Screens[b->scrnIndex], dcb_i2c->write), (4 | clock | data << 1)); -} - -static void NV50_I2CGetBits(I2CBusPtr b, int *clock, int *data) -{ - NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]); - struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr; - unsigned char val; - - val = NVRead(pNv, NV50_GetI2CPort(xf86Screens[b->scrnIndex], dcb_i2c->read)); - *clock = !!(val & 1); - *data = !!(val & 2); -} - -int -NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, struct dcb_i2c_entry *dcb_i2c, char *name) -{ - I2CBusPtr pI2CBus; - - if (dcb_i2c->chan) - goto initialized; - - if (!(pI2CBus = xf86CreateI2CBusRec())) - return -ENOMEM; - - pI2CBus->BusName = name; - pI2CBus->scrnIndex = pScrn->scrnIndex; - if (dcb_i2c->port_type == 5) { /* NV50 */ - pI2CBus->I2CPutBits = NV50_I2CPutBits; - pI2CBus->I2CGetBits = NV50_I2CGetBits; - /* Could this be used for the rest as well? */ - pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ - pI2CBus->StartTimeout = 550; - pI2CBus->BitTimeout = 40; - pI2CBus->ByteTimeout = 40; - pI2CBus->AcknTimeout = 40; - } else { - pI2CBus->I2CPutBits = NVI2CPutBits; - pI2CBus->I2CGetBits = NVI2CGetBits; - pI2CBus->AcknTimeout = 5; - } - pI2CBus->DriverPrivate.ptr = dcb_i2c; - - if (!xf86I2CBusInit(pI2CBus)) - return -EINVAL; - - dcb_i2c->chan = pI2CBus; - -initialized: - *bus_ptr = dcb_i2c->chan; - - return 0; -} - diff --git a/src/nv_include.h b/src/nv_include.h index 03e8c6a..f17cf8b 100644 --- a/src/nv_include.h +++ b/src/nv_include.h @@ -71,12 +71,9 @@ #include "nv_local.h" #include "nv_type.h" #include "nv_proto.h" -#include "nouveau_hw.h" #include "nv_dma.h" #include "nouveau_drm.h" #include "nouveau_class.h" -#include "nvreg.h" -#include "nv50reg.h" #include "sarea.h" #include "nouveau_drmif.h" diff --git a/src/nv_output.c b/src/nv_output.c deleted file mode 100644 index 2573702..0000000 --- a/src/nv_output.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Copyright 2003 NVIDIA, Corporation - * Copyright 2006 Dave Airlie - * Copyright 2007 Maarten Maathuis - * Copyright 2007-2009 Stuart Bennett - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include /* X_GETTIMEOFDAY */ -#include "nv_include.h" - -#define MULTIPLE_ENCODERS(e) (e & (e - 1)) -#define FOR_EACH_ENCODER_IN_CONNECTOR(i, c, e) for (i = 0; i < pNv->vbios->dcb->entries; i++) \ - if (c->possible_encoders & (1 << i) && \ - (e = &pNv->encoders[i])) - -static int nv_output_ramdac_offset(struct nouveau_encoder *nv_encoder) -{ - int offset = 0; - - if (nv_encoder->dcb->or & (8 | OUTPUT_C)) - offset += 0x68; - if (nv_encoder->dcb->or & (8 | OUTPUT_B)) - offset += 0x2000; - - return offset; -} - -static int nv_get_digital_bound_head(NVPtr pNv, int or) -{ - /* special case of nv_read_tmds to find crtc associated with an output. - * this does not give a correct answer for off-chip dvi, but there's no - * use for such an answer anyway - */ - int ramdac = (or & OUTPUT_C) >> 2; - - NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL, - NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4); - return (((NVReadRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac); -} - -#define WAIT_FOR(cond, timeout_us) __extension__ ({ \ - struct timeval begin, cur; \ - long d_secs, d_usecs, diff = 0; \ - \ - X_GETTIMEOFDAY(&begin); \ - while (!(cond) && diff < timeout_us) { \ - X_GETTIMEOFDAY(&cur); \ - d_secs = cur.tv_sec - begin.tv_sec; \ - d_usecs = cur.tv_usec - begin.tv_usec; \ - diff = d_secs * 1000000 + d_usecs; \ - }; \ - diff >= timeout_us ? -EAGAIN : 0; \ -}) - -/* - * arbitrary limit to number of sense oscillations tolerated in one sample - * period (observed to be at least 13 in "nvidia") - */ -#define MAX_HBLANK_OSC 20 - -/* - * arbitrary limit to number of conflicting sample pairs to tolerate at a - * voltage step (observed to be at least 5 in "nvidia") - */ -#define MAX_SAMPLE_PAIRS 10 - -static int sample_load_twice(NVPtr pNv, bool sense[2]) -{ - int i; - - for (i = 0; i < 2; i++) { - bool sense_a, sense_b, sense_b_prime; - int j = 0; - - /* - * wait for bit 0 clear -- out of hblank -- (say reg value 0x4), - * then wait for transition 0x4->0x5->0x4: enter hblank, leave - * hblank again - * use a 10ms timeout (guards against crtc being inactive, in - * which case blank state would never change) - */ - if (WAIT_FOR(!(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1), 10000)) - return -EWOULDBLOCK; - if (WAIT_FOR(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1, 10000)) - return -EWOULDBLOCK; - if (WAIT_FOR(!(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1), 10000)) - return -EWOULDBLOCK; - - WAIT_FOR(0, 100); /* faster than usleep(100) */ - /* when level triggers, sense is _LO_ */ - sense_a = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10; - - /* take another reading until it agrees with sense_a... */ - do { - WAIT_FOR(0, 100); - sense_b = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10; - if (sense_a != sense_b) { - sense_b_prime = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10; - if (sense_b == sense_b_prime) { - /* ... unless two consecutive subsequent - * samples agree; sense_a is replaced */ - sense_a = sense_b; - /* force mis-match so we loop */ - sense_b = !sense_a; - } - } - } while ((sense_a != sense_b) && ++j < MAX_HBLANK_OSC); - - if (j == MAX_HBLANK_OSC) - /* with so much oscillation, default to sense:LO */ - sense[i] = false; - else - sense[i] = sense_a; - } - - return 0; -} - -static bool nv_legacy_load_detect(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - uint8_t saved_seq1, saved_pi, saved_rpc1; - uint8_t saved_palette0[3], saved_palette_mask; - uint32_t saved_rtest_ctrl, saved_rgen_ctrl; - int i; - uint8_t blue; - bool sense = true; - - /* - * for this detection to work, there needs to be a mode set up on the - * CRTC. this is presumed to be the case - */ - - if (pNv->twoHeads) - /* only implemented for head A for now */ - NVSetOwner(pNv, 0); - - saved_seq1 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX); - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20); - - saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL, - saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); - - usleep(10000); - - saved_pi = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX); - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX, - saved_pi & ~(0x80 | MASK(NV_CIO_CRE_PIXEL_FORMAT))); - saved_rpc1 = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX); - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0); - - VGA_WR08(pNv->REGS, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); - for (i = 0; i < 3; i++) - saved_palette0[i] = NV_RD08(pNv->REGS, NV_PRMDIO_PALETTE_DATA); - saved_palette_mask = NV_RD08(pNv->REGS, NV_PRMDIO_PIXEL_MASK); - VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK, 0); - - saved_rgen_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL, - (saved_rgen_ctrl & ~(NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS | - NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM)) | - NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON); - - blue = 8; /* start of test range */ - - do { - bool sense_pair[2]; - - VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); - NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, 0); - NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, 0); - /* testing blue won't find monochrome monitors. I don't care */ - NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, blue); - - i = 0; - /* take sample pairs until both samples in the pair agree */ - do { - if (sample_load_twice(pNv, sense_pair)) - goto out; - } while ((sense_pair[0] != sense_pair[1]) && - ++i < MAX_SAMPLE_PAIRS); - - if (i == MAX_SAMPLE_PAIRS) - /* too much oscillation defaults to LO */ - sense = false; - else - sense = sense_pair[0]; - - /* - * if sense goes LO before blue ramps to 0x18, monitor is not connected. - * ergo, if blue gets to 0x18, monitor must be connected - */ - } while (++blue < 0x18 && sense); - -out: - VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl); - VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); - for (i = 0; i < 3; i++) - NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl); - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); - NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); - NVWriteVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1); - - if (blue == 0x18) { - NV_TRACE(pScrn, "Load detected on head A\n"); - return true; - } - - return false; -} - -static bool -nv_nv17_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) -{ - NVPtr pNv = NVPTR(pScrn); - uint32_t testval, regoffset = nv_output_ramdac_offset(nv_encoder); - uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp; - int head, present = 0; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - -#define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20) - testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */ - if (pNv->vbios->dactestval) - testval = pNv->vbios->dactestval; - - saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, - saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); - - saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2); - - nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); - if (regoffset == 0x68) { - saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4); - nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); - } - - usleep(4000); - - saved_routput = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset); - head = (saved_routput & 0x100) >> 8; - /* if there's a spare crtc, using it will minimise flicker for the case - * where the in-use crtc is in use by an off-chip tmds encoder */ - if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled) - head ^= 1; - /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, - (saved_routput & 0xfffffece) | head << 8); - usleep(1000); - - temp = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1); - - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TESTPOINT_DATA, - NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK | testval); - temp = NVReadRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL, - temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); - usleep(1000); - - present = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) & - NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI; - - temp = NVReadRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL, - temp & ~NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED); - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TESTPOINT_DATA, 0); - - /* bios does something more complex for restoring, but I think this is good enough */ - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl); - if (regoffset == 0x68) - nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); - nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); - - if (present) { - NV_TRACE(pScrn, "Load detected on output %c\n", - '@' + ffs(nv_encoder->dcb->or)); - return true; - } - - return false; -} - -static void -update_output_fields(xf86OutputPtr output, struct nouveau_encoder *det_encoder) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - NVPtr pNv = NVPTR(output->scrn); - - if (nv_connector->detected_encoder == det_encoder) - return; - - nv_connector->detected_encoder = det_encoder; - output->possible_crtcs = det_encoder->dcb->heads; - if (IS_DFP(det_encoder->dcb->type)) { - output->doubleScanAllowed = false; - output->interlaceAllowed = false; - } else { - output->doubleScanAllowed = true; - if (pNv->Architecture == NV_ARCH_20 || - (pNv->Architecture == NV_ARCH_10 && - (pNv->Chipset & 0x0ff0) != CHIPSET_NV10 && - (pNv->Chipset & 0x0ff0) != CHIPSET_NV15)) - /* HW is broken */ - output->interlaceAllowed = false; - else - output->interlaceAllowed = true; - } -} - -static bool edid_sink_connected(xf86OutputPtr output) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - NVPtr pNv = NVPTR(output->scrn); - bool waslocked = NVLockVgaCrtcs(pNv, false); - bool wastied = nv_heads_tied(pNv); - - if (wastied) - NVSetOwner(pNv, 0); /* necessary? */ - - nv_connector->edid = xf86OutputGetEDID(output, nv_connector->pDDCBus); - - if (wastied) - NVSetOwner(pNv, 0x4); - if (waslocked) - NVLockVgaCrtcs(pNv, true); - - return !!nv_connector->edid; -} - -static xf86OutputStatus -nv_output_detect(xf86OutputPtr output) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - ScrnInfoPtr pScrn = output->scrn; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_encoder *det_encoder; - xf86OutputStatus ret = XF86OutputStatusDisconnected; - - struct nouveau_encoder *find_encoder_by_type(enum nouveau_encoder_type type) - { - int i; - for (i = 0; i < pNv->vbios->dcb->entries; i++) - if (nv_connector->possible_encoders & (1 << i) && - (type == OUTPUT_ANY || pNv->encoders[i].dcb->type == type)) - return &pNv->encoders[i]; - return NULL; - } - - /* if an LVDS output was ever connected it remains so */ - if (nv_connector->detected_encoder && - nv_connector->detected_encoder->dcb->type == OUTPUT_LVDS) - return XF86OutputStatusConnected; - - if (nv_connector->pDDCBus && edid_sink_connected(output)) { - if (MULTIPLE_ENCODERS(nv_connector->possible_encoders)) { - if (nv_connector->edid->features.input_type) - det_encoder = find_encoder_by_type(OUTPUT_TMDS); - else - det_encoder = find_encoder_by_type(OUTPUT_ANALOG); - } else - det_encoder = find_encoder_by_type(OUTPUT_ANY); - ret = XF86OutputStatusConnected; - } else if ((det_encoder = find_encoder_by_type(OUTPUT_ANALOG))) { - /* bind encoder if enabled in xorg.conf */ - if (output->conf_monitor && - xf86CheckBoolOption(output->conf_monitor->mon_option_lst, - "Enable", FALSE)) - ret = XF86OutputStatusConnected; - else if (pNv->gf4_disp_arch) { - if (nv_nv17_load_detect(pScrn, det_encoder)) - ret = XF86OutputStatusConnected; - } else - if (nv_legacy_load_detect(pScrn)) - ret = XF86OutputStatusConnected; - } else if ((det_encoder = find_encoder_by_type(OUTPUT_LVDS))) { - if (det_encoder->dcb->lvdsconf.use_straps_for_mode) { - if (nouveau_bios_fp_mode(pScrn, NULL)) - ret = XF86OutputStatusConnected; - } else if (!pNv->vbios->fp_no_ddc && - nouveau_bios_embedded_edid(pScrn)) { - nv_connector->edid = xf86InterpretEDID(pScrn->scrnIndex, - nouveau_bios_embedded_edid(pScrn)); - ret = XF86OutputStatusConnected; - } - } - - if (ret != XF86OutputStatusDisconnected) - update_output_fields(output, det_encoder); - - return ret; -} - -static DisplayModePtr -get_native_mode_from_edid(xf86OutputPtr output, DisplayModePtr edid_modes) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - int max_h_active = 0, max_v_active = 0; - int i; - DisplayModePtr mode; - - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_timings *dt = - &nv_connector->edid->det_mon[i].section.d_timings; - - if (nv_connector->edid->det_mon[i].type != DT) - continue; - /* Selecting only based on width ok? */ - if (dt->h_active > max_h_active) { - max_h_active = dt->h_active; - max_v_active = dt->v_active; - } - } - if (!max_h_active || !max_v_active) /* clearly a joke EDID */ - for (i = 0; i < STD_TIMINGS; i++) { - struct std_timings *st = - &nv_connector->edid->timings2[i]; - - if (st->hsize > max_h_active) { - max_h_active = st->hsize; - max_v_active = st->vsize; - } - } - if (!max_h_active || !max_v_active) { - NV_ERROR(output->scrn, "EDID too broken to find native mode\n"); - return NULL; - } - - if (nv_encoder->native_mode) { - xfree(nv_encoder->native_mode); - nv_encoder->native_mode = NULL; - } - - for (mode = edid_modes; mode != NULL; mode = mode->next) { - if (mode->HDisplay == max_h_active && - mode->VDisplay == max_v_active) { - /* Take the preferred mode when it exists. */ - if (mode->type & M_T_PREFERRED) { - nv_encoder->native_mode = xf86DuplicateMode(mode); - break; - } - /* Find the highest refresh mode otherwise. */ - if (!nv_encoder->native_mode || - (mode->VRefresh > nv_encoder->native_mode->VRefresh)) { - if (nv_encoder->native_mode) - xfree(nv_encoder->native_mode); - mode->type |= M_T_PREFERRED; - nv_encoder->native_mode = xf86DuplicateMode(mode); - } - } - } - - return nv_encoder->native_mode; -} - -static DisplayModePtr -nv_output_get_edid_modes(xf86OutputPtr output) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - DisplayModePtr edid_modes; - - if (IS_DFP(nv_encoder->dcb->type) && - nv_encoder->scaling_mode != SCALE_PANEL) - /* the digital scaler is not limited to modes given in the EDID, - * so enable the GTF bit in order that the xserver thinks - * continuous timing is available and adds the standard modes - */ - nv_connector->edid->features.msc |= 1; - - xf86OutputSetEDID(output, nv_connector->edid); - if (!(edid_modes = xf86OutputGetEDIDModes(output))) - return edid_modes; - - if (IS_DFP(nv_encoder->dcb->type)) - if (!get_native_mode_from_edid(output, edid_modes)) - return NULL; - if (nv_encoder->dcb->type == OUTPUT_TMDS) - nv_encoder->dual_link = nv_encoder->native_mode->Clock >= 165000; - - return edid_modes; -} - -static DisplayModePtr -nv_lvds_output_get_modes(xf86OutputPtr output) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - ScrnInfoPtr pScrn = output->scrn; - DisplayModeRec mode, *ret_mode = NULL; - int clock = 0; /* needs to be zero for straps case */ - bool dl, if_is_24bit = false; - - /* panels only have one mode, and it doesn't change */ - if (nv_encoder->native_mode) - return xf86DuplicateMode(nv_encoder->native_mode); - - if (nv_encoder->dcb->lvdsconf.use_straps_for_mode) { - if (!nouveau_bios_fp_mode(pScrn, &mode)) - return NULL; - - mode.status = MODE_OK; - mode.type = M_T_DRIVER | M_T_PREFERRED; - xf86SetModeDefaultName(&mode); - - nv_encoder->native_mode = xf86DuplicateMode(&mode); - ret_mode = xf86DuplicateMode(&mode); - } else - if ((ret_mode = nv_output_get_edid_modes(output))) - clock = nv_encoder->native_mode->Clock; - - if (nouveau_bios_parse_lvds_table(pScrn, clock, &dl, &if_is_24bit)) { - if (nv_encoder->native_mode) { - xfree(nv_encoder->native_mode); - nv_encoder->native_mode = NULL; - } - return NULL; - } - - /* because of the pre-existing native mode exit above, this will only - * get run at startup (and before create_resources is called in - * mode_fixup), so subsequent user dither settings are not overridden - */ - nv_encoder->dithering |= !if_is_24bit; - nv_encoder->dual_link = dl; - - return ret_mode; -} - -static int nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_connector(output)->detected_encoder; - - /* mode_valid can be called by someone doing addmode on an output - * which is disconnected and so without an encoder; avoid crashing - */ - if (!nv_encoder) - return MODE_ERROR; - - if (!output->doubleScanAllowed && mode->Flags & V_DBLSCAN) - return MODE_NO_DBLESCAN; - if (!output->interlaceAllowed && mode->Flags & V_INTERLACE) - return MODE_NO_INTERLACE; - - if (nv_encoder->dcb->type == OUTPUT_ANALOG) { - if (nv_encoder->dcb->crtconf.maxfreq) { - if (mode->Clock > nv_encoder->dcb->crtconf.maxfreq) - return MODE_CLOCK_HIGH; - } else - if (mode->Clock > 350000) - return MODE_CLOCK_HIGH; - } - /* must have a native mode for fp (except in panel scaling case) */ - if (IS_DFP(nv_encoder->dcb->type) && !nv_encoder->native_mode && - nv_encoder->scaling_mode != SCALE_PANEL) - return MODE_NOCLOCK; - if (IS_DFP(nv_encoder->dcb->type) && nv_encoder->native_mode) - /* No modes > panel's native res */ - if (mode->HDisplay > nv_encoder->native_mode->HDisplay || - mode->VDisplay > nv_encoder->native_mode->VDisplay) - return MODE_PANEL; - if (nv_encoder->dcb->type == OUTPUT_TMDS) { - if (nv_encoder->dcb->duallink_possible) { - if (mode->Clock > 330000) /* 2x165 MHz */ - return MODE_CLOCK_HIGH; - } else - if (mode->Clock > 165000) /* 165 MHz */ - return MODE_CLOCK_HIGH; - } - - return MODE_OK; -} - -static void -nv_output_destroy(xf86OutputPtr output) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - struct nouveau_encoder *nv_encoder; - NVPtr pNv = NVPTR(output->scrn); - int i; - - if (!nv_connector) - return; - - if (nv_connector->edid) - xfree(nv_connector->edid); - FOR_EACH_ENCODER_IN_CONNECTOR(i, nv_connector, nv_encoder) - if (nv_encoder->native_mode) - xfree(nv_encoder->native_mode); - xfree(nv_connector); -} - -static char * get_current_scaling_name(enum scaling_modes mode) -{ - static const struct { - char *name; - enum scaling_modes mode; - } scaling_mode[] = { - { "panel", SCALE_PANEL }, - { "fullscreen", SCALE_FULLSCREEN }, - { "aspect", SCALE_ASPECT }, - { "noscale", SCALE_NOSCALE }, - { NULL, SCALE_INVALID } - }; - int i; - - for (i = 0; scaling_mode[i].name; i++) - if (scaling_mode[i].mode == mode) - return scaling_mode[i].name; - - return NULL; -} - -static int nv_output_create_prop(xf86OutputPtr output, char *name, Atom *atom, - INT32 *rangevals, INT32 cur_val, char *cur_str, Bool do_mode_set) -{ - int ret = -ENOMEM; - Bool range = rangevals ? TRUE : FALSE; - - if ((*atom = MakeAtom(name, strlen(name), TRUE)) == BAD_RESOURCE) - goto fail; - if (RRQueryOutputProperty(output->randr_output, *atom)) - return 0; /* already exists */ - if ((ret = RRConfigureOutputProperty(output->randr_output, *atom, - do_mode_set, range, FALSE, range ? 2 : 0, rangevals))) - goto fail; - if (range) - ret = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER, 32, - PropModeReplace, 1, &cur_val, FALSE, do_mode_set); - else - ret = RRChangeOutputProperty(output->randr_output, *atom, XA_STRING, 8, - PropModeReplace, strlen(cur_str), cur_str, - FALSE, do_mode_set); - -fail: - if (ret) - xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, - "Creation of %s property failed: %d\n", name, ret); - - return ret; -} - -static Atom dithering_atom, scaling_mode_atom; -static Atom dv_atom, sharpness_atom; - -static void nv_output_create_resources(xf86OutputPtr output) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - NVPtr pNv = NVPTR(output->scrn); - - /* may be called before encoder is picked, resources will be created - * by update_output_fields() - */ - if (!nv_encoder) - return; - - if (IS_DFP(nv_encoder->dcb->type)) { - nv_output_create_prop(output, "DITHERING", &dithering_atom, - (INT32 []){ 0, 1 }, nv_encoder->dithering, NULL, TRUE); - nv_output_create_prop(output, "SCALING_MODE", &scaling_mode_atom, - NULL, 0, get_current_scaling_name(nv_encoder->scaling_mode), TRUE); - } - if (pNv->NVArch >= 0x11 && output->crtc) { - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc); - INT32 dv_range[2] = { 0, !pNv->gf4_disp_arch ? 3 : 63 }; - /* unsure of correct condition here: blur works on my nv34, but not on my nv31 */ - INT32 is_range[2] = { pNv->NVArch > 0x31 ? -32 : 0, 31 }; - - nv_output_create_prop(output, "DIGITAL_VIBRANCE", &dv_atom, - dv_range, nv_crtc->saturation, NULL, FALSE); - if (pNv->NVArch >= 0x30) - nv_output_create_prop(output, "IMAGE_SHARPENING", &sharpness_atom, - is_range, nv_crtc->sharpness, NULL, FALSE); - } -} - -static Bool -nv_output_set_property(xf86OutputPtr output, Atom property, - RRPropertyValuePtr value) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - NVPtr pNv = NVPTR(output->scrn); - - if (property == scaling_mode_atom) { - char *name = (char *) value->data; - int32_t val; - - if (value->type != XA_STRING || value->format != 8) - return FALSE; - - /* Match a string to a scaling mode */ - val = nv_scaling_mode_lookup(name, value->size); - if (val == SCALE_INVALID) - return FALSE; - - /* LVDS must always use gpu scaling. */ - if (val == SCALE_PANEL && nv_encoder->dcb->type == OUTPUT_LVDS) - return FALSE; - - nv_encoder->scaling_mode = val; - } else if (property == dithering_atom) { - int32_t val = *(int32_t *) value->data; - - if (value->type != XA_INTEGER || value->format != 32) - return FALSE; - - if (val < 0 || val > 1) - return FALSE; - - nv_encoder->dithering = val; - } else if (property == dv_atom || property == sharpness_atom) { - int32_t val = *(int32_t *) value->data; - - if (value->type != XA_INTEGER || value->format != 32) - return FALSE; - - if (!output->crtc) - return FALSE; - - if (property == dv_atom) { - if (val < 0 || val > (!pNv->gf4_disp_arch ? 3 : 63)) - return FALSE; - - nv_crtc_set_digital_vibrance(output->crtc, val); - } else { - if (val < (pNv->NVArch > 0x31 ? -32 : 0) || val > 31) - return FALSE; - - nv_crtc_set_image_sharpening(output->crtc, val); - } - } - - return TRUE; -} - -static Bool -nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, - DisplayModePtr adjusted_mode) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - - if (nv_connector->nv_encoder != nv_connector->detected_encoder) { - nv_connector->nv_encoder = nv_connector->detected_encoder; - if (output->randr_output) { - RRDeleteOutputProperty(output->randr_output, dithering_atom); - RRDeleteOutputProperty(output->randr_output, scaling_mode_atom); - output->funcs->create_resources(output); - } - } - - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - - /* For internal panels and gpu scaling on DVI we need the native mode */ - if (IS_DFP(nv_encoder->dcb->type) && - nv_encoder->scaling_mode != SCALE_PANEL) { - adjusted_mode->HDisplay = nv_encoder->native_mode->HDisplay; - adjusted_mode->HSkew = nv_encoder->native_mode->HSkew; - adjusted_mode->HSyncStart = nv_encoder->native_mode->HSyncStart; - adjusted_mode->HSyncEnd = nv_encoder->native_mode->HSyncEnd; - adjusted_mode->HTotal = nv_encoder->native_mode->HTotal; - adjusted_mode->VDisplay = nv_encoder->native_mode->VDisplay; - adjusted_mode->VScan = nv_encoder->native_mode->VScan; - adjusted_mode->VSyncStart = nv_encoder->native_mode->VSyncStart; - adjusted_mode->VSyncEnd = nv_encoder->native_mode->VSyncEnd; - adjusted_mode->VTotal = nv_encoder->native_mode->VTotal; - adjusted_mode->Clock = nv_encoder->native_mode->Clock; - adjusted_mode->Flags = nv_encoder->native_mode->Flags; - - xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V); - } - - return TRUE; -} - -static void nv_digital_output_prepare_sel_clk(NVPtr pNv, struct nouveau_encoder *nv_encoder, int head) -{ - struct nouveau_mode_state *state = &pNv->set_state; - uint32_t bits1618 = nv_encoder->dcb->or & OUTPUT_A ? 0x10000 : 0x40000; - - if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP) - return; - - /* SEL_CLK is only used on the primary ramdac - * It toggles spread spectrum PLL output and sets the bindings of PLLs - * to heads on digital outputs - */ - if (head) - state->sel_clk |= bits1618; - else - state->sel_clk &= ~bits1618; - - /* nv30: - * bit 0 NVClk spread spectrum on/off - * bit 2 MemClk spread spectrum on/off - * bit 4 PixClk1 spread spectrum on/off toggle - * bit 6 PixClk2 spread spectrum on/off toggle - * - * nv40 (observations from bios behaviour and mmio traces): - * bits 4&6 as for nv30 - * bits 5&7 head dependent as for bits 4&6, but do not appear with 4&6; - * maybe a different spread mode - * bits 8&10 seen on dual-link dvi outputs, purpose unknown (set by POST scripts) - * The logic behind turning spread spectrum on/off in the first place, - * and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table - * entry has the necessary info) - */ - if (nv_encoder->dcb->type == OUTPUT_LVDS && pNv->saved_regs.sel_clk & 0xf0) { - int shift = (pNv->saved_regs.sel_clk & 0x50) ? 0 : 1; - - state->sel_clk &= ~0xf0; - state->sel_clk |= (head ? 0x40 : 0x10) << shift; - } -} - -#define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ - NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ - NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) -#define FP_TG_CONTROL_OFF (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE | \ - NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE | \ - NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE) - -static bool is_fpc_off(uint32_t fpc) -{ - return ((fpc & (FP_TG_CONTROL_ON | FP_TG_CONTROL_OFF)) == - FP_TG_CONTROL_OFF); -} - -static void -nv_output_prepare(xf86OutputPtr output) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - NVPtr pNv = NVPTR(output->scrn); - int head = to_nouveau_crtc(output->crtc)->head; - struct nouveau_crtc_state *crtcstate = pNv->set_state.head; - uint8_t *cr_lcd = &crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX]; - uint8_t *cr_lcd_oth = &crtcstate[head ^ 1].CRTC[NV_CIO_CRE_LCD__INDEX]; - - output->funcs->dpms(output, DPMSModeOff); - - if (nv_encoder->dcb->type == OUTPUT_ANALOG) { - if (NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL) & - FP_TG_CONTROL_ON) { - /* digital remnants must be cleaned before new crtc - * values programmed. delay is time for the vga stuff - * to realise it's in control again - */ - NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, - FP_TG_CONTROL_OFF); - usleep(50000); - } - /* don't inadvertently turn it on when state written later */ - crtcstate[head].fp_control = FP_TG_CONTROL_OFF; - } - - /* calculate some output specific CRTC regs now, so that they can be - * written in nv_crtc_set_mode - */ - - if (IS_DFP(nv_encoder->dcb->type)) - nv_digital_output_prepare_sel_clk(pNv, nv_encoder, head); - - /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f) - * at LCD__INDEX which we don't alter - */ - if (!(*cr_lcd & 0x44)) { - *cr_lcd = IS_DFP(nv_encoder->dcb->type) ? 0x3 : 0x0; - if (IS_DFP(nv_encoder->dcb->type) && pNv->twoHeads) { - if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP) - *cr_lcd |= head ? 0x0 : 0x8; - else { - *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30; - if (nv_encoder->dcb->type == OUTPUT_LVDS) - *cr_lcd |= 0x30; - if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) { - /* avoid being connected to both crtcs */ - *cr_lcd_oth &= ~0x30; - NVWriteVgaCrtc(pNv, head ^ 1, - NV_CIO_CRE_LCD__INDEX, - *cr_lcd_oth); - } - } - } - } -} - -static void -nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - ScrnInfoPtr pScrn = output->scrn; - NVPtr pNv = NVPTR(pScrn); - struct dcb_entry *dcbe = nv_encoder->dcb; - int head = to_nouveau_crtc(output->crtc)->head; - - NV_TRACE(pScrn, "%s called for encoder %d\n", __func__, dcbe->index); - - if (pNv->gf4_disp_arch && dcbe->type == OUTPUT_ANALOG) { - uint32_t dac_offset = nv_output_ramdac_offset(nv_encoder); - uint32_t otherdac; - int i; - - /* bit 16-19 are bits that are set on some G70 cards, - * but don't seem to have much effect */ - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset, - head << 8 | NV_PRAMDAC_DACCLK_SEL_DACCLK); - /* force any other vga encoders to bind to the other crtc */ - for (i = 0; i < pNv->vbios->dcb->entries; i++) - if (i != dcbe->index && pNv->encoders[i].dcb && - pNv->encoders[i].dcb->type == OUTPUT_ANALOG) { - dac_offset = nv_output_ramdac_offset(&pNv->encoders[i]); - otherdac = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset); - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset, - (otherdac & ~0x100) | (head ^ 1) << 8); - } - } - if (dcbe->type == OUTPUT_TMDS) - run_tmds_table(pScrn, dcbe, head, adjusted_mode->Clock); - else if (dcbe->type == OUTPUT_LVDS) - call_lvds_script(pScrn, dcbe, head, LVDS_RESET, adjusted_mode->Clock); - if (IS_DFP(dcbe->type)) - /* update fp_control state for any changes made by scripts, - * so correct value is written at DPMS on */ - pNv->set_state.head[head].fp_control = - NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL); - - /* This could use refinement for flatpanels, but it should work this way */ - if (pNv->NVArch < 0x44) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + nv_output_ramdac_offset(nv_encoder), 0xf0000000); - else - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + nv_output_ramdac_offset(nv_encoder), 0x00100000); -} - -static void -nv_output_commit(xf86OutputPtr output) -{ - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - ScrnInfoPtr pScrn = output->scrn; - struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc); - - output->funcs->dpms(output, DPMSModeOn); - - NV_TRACE(pScrn, "Output %s is running on CRTC %d using output %c\n", - output->name, nv_crtc->head, '@' + ffs(nv_encoder->dcb->or)); -} - -static void dpms_update_fp_control(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_crtc *nv_crtc; - uint32_t *fpc; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - if (mode == DPMSModeOn) { - nv_crtc = to_nouveau_crtc(crtc); - fpc = &nv_crtc->state->fp_control; - - if (is_fpc_off(*fpc)) - /* using saved value is ok, as (is_digital && dpms_on && - * fp_control==OFF) is (at present) *only* true when - * fpc's most recent change was by below "off" code - */ - *fpc = nv_crtc->dpms_saved_fp_control; - - nv_crtc->fp_users |= 1 << nv_encoder->dcb->index; - NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_FP_TG_CONTROL, *fpc); - } else - for (i = 0; i < xf86_config->num_crtc; i++) { - nv_crtc = to_nouveau_crtc(xf86_config->crtc[i]); - fpc = &nv_crtc->state->fp_control; - - nv_crtc->fp_users &= ~(1 << nv_encoder->dcb->index); - if (!is_fpc_off(*fpc) && !nv_crtc->fp_users) { - nv_crtc->dpms_saved_fp_control = *fpc; - /* cut the FP output */ - *fpc &= ~FP_TG_CONTROL_ON; - *fpc |= FP_TG_CONTROL_OFF; - NVWriteRAMDAC(pNv, nv_crtc->head, - NV_PRAMDAC_FP_TG_CONTROL, *fpc); - } - } -} - -static bool is_powersaving_dpms(int mode) -{ - return (mode == DPMSModeStandby || mode == DPMSModeSuspend || - mode == DPMSModeOff); -} - -static void -lvds_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode) -{ - NVPtr pNv = NVPTR(pScrn); - bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms); - - if (nv_encoder->last_dpms == mode) - return; - nv_encoder->last_dpms = mode; - - NV_TRACE(pScrn, "Setting dpms mode %d on lvds encoder (output %d)\n", - mode, nv_encoder->dcb->index); - - if (was_powersaving && is_powersaving_dpms(mode)) - return; - - if (nv_encoder->dcb->lvdsconf.use_power_scripts) { - /* when removing an output, crtc may not be set, but PANEL_OFF - * must still be run - */ - int head = crtc ? to_nouveau_crtc(crtc)->head : - nv_get_digital_bound_head(pNv, nv_encoder->dcb->or); - - if (mode == DPMSModeOn) - call_lvds_script(pScrn, nv_encoder->dcb, head, - LVDS_PANEL_ON, nv_encoder->native_mode->Clock); - else - /* pxclk of 0 is fine for PANEL_OFF, and for a - * disconnected LVDS encoder there is no native_mode - */ - call_lvds_script(pScrn, nv_encoder->dcb, head, - LVDS_PANEL_OFF, 0); - } - - dpms_update_fp_control(pScrn, nv_encoder, crtc, mode); - - if (mode == DPMSModeOn) - nv_digital_output_prepare_sel_clk(pNv, nv_encoder, to_nouveau_crtc(crtc)->head); - else { - pNv->set_state.sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK); - pNv->set_state.sel_clk &= ~0xf0; - } - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, pNv->set_state.sel_clk); -} - -static void -vga_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode) -{ - NVPtr pNv = NVPTR(pScrn); - - if (nv_encoder->last_dpms == mode) - return; - nv_encoder->last_dpms = mode; - - NV_TRACE(pScrn, "Setting dpms mode %d on vga encoder (output %d)\n", - mode, nv_encoder->dcb->index); - - if (pNv->gf4_disp_arch) { - uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder)); - - if (mode == DPMSModeOff) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder), - outputval & ~NV_PRAMDAC_DACCLK_SEL_DACCLK); - else if (mode == DPMSModeOn) - NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder), - outputval | NV_PRAMDAC_DACCLK_SEL_DACCLK); - } -} - -static void -tmds_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode) -{ - if (nv_encoder->last_dpms == mode) - return; - nv_encoder->last_dpms = mode; - - NV_TRACE(pScrn, "Setting dpms mode %d on tmds encoder (output %d)\n", - mode, nv_encoder->dcb->index); - - dpms_update_fp_control(pScrn, nv_encoder, crtc, mode); -} - -static void nv_output_dpms(xf86OutputPtr output, int mode) -{ - struct nouveau_connector *nv_connector = to_nouveau_connector(output); - struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output); - ScrnInfoPtr pScrn = output->scrn; - xf86CrtcPtr crtc = output->crtc; - NVPtr pNv = NVPTR(pScrn); - int i; - void (* const encoder_dpms[4])(ScrnInfoPtr, struct nouveau_encoder *, xf86CrtcPtr, int) = - /* index matches DCB type */ - { vga_encoder_dpms, NULL, tmds_encoder_dpms, lvds_encoder_dpms }; - - struct nouveau_encoder *nv_encoder_i; - FOR_EACH_ENCODER_IN_CONNECTOR(i, nv_connector, nv_encoder_i) - if (nv_encoder_i != nv_encoder) - encoder_dpms[nv_encoder_i->dcb->type](pScrn, nv_encoder_i, crtc, DPMSModeOff); - - if (nv_encoder) /* may be called before encoder is picked, but iteration above solves it */ - encoder_dpms[nv_encoder->dcb->type](pScrn, nv_encoder, crtc, mode); -} - -void nv_encoder_save(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) -{ - NVPtr pNv = NVPTR(pScrn); - - if (!nv_encoder->dcb) /* uninitialised encoder */ - return; - - if (pNv->gf4_disp_arch && nv_encoder->dcb->type == OUTPUT_ANALOG) - nv_encoder->restore.output = - NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + - nv_output_ramdac_offset(nv_encoder)); - if (pNv->twoHeads && IS_DFP(nv_encoder->dcb->type)) - nv_encoder->restore.head = - nv_get_digital_bound_head(pNv, nv_encoder->dcb->or); -} - -void nv_encoder_restore(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder) -{ - NVPtr pNv = NVPTR(pScrn); - int head = nv_encoder->restore.head; - - if (!nv_encoder->dcb) /* uninitialised encoder */ - return; - - if (pNv->gf4_disp_arch && nv_encoder->dcb->type == OUTPUT_ANALOG) - NVWriteRAMDAC(pNv, 0, - NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder), - nv_encoder->restore.output); - if (nv_encoder->dcb->type == OUTPUT_LVDS) - call_lvds_script(pScrn, nv_encoder->dcb, head, LVDS_PANEL_ON, - nv_encoder->native_mode->Clock); - if (nv_encoder->dcb->type == OUTPUT_TMDS) { - int clock = nouveau_hw_pllvals_to_clk - (&pNv->saved_regs.head[head].pllvals); - - run_tmds_table(pScrn, nv_encoder->dcb, head, clock); - } - - nv_encoder->last_dpms = NV_DPMS_CLEARED; -} - -static const xf86OutputFuncsRec nv_output_funcs = { - .dpms = nv_output_dpms, - .mode_valid = nv_output_mode_valid, - .mode_fixup = nv_output_mode_fixup, - .mode_set = nv_output_mode_set, - .detect = nv_output_detect, - .get_modes = nv_output_get_edid_modes, - .destroy = nv_output_destroy, - .prepare = nv_output_prepare, - .commit = nv_output_commit, - .create_resources = nv_output_create_resources, - .set_property = nv_output_set_property, -}; - -static const xf86OutputFuncsRec nv_lvds_output_funcs = { - .dpms = nv_output_dpms, - .mode_valid = nv_output_mode_valid, - .mode_fixup = nv_output_mode_fixup, - .mode_set = nv_output_mode_set, - .detect = nv_output_detect, - .get_modes = nv_lvds_output_get_modes, - .destroy = nv_output_destroy, - .prepare = nv_output_prepare, - .commit = nv_output_commit, - .create_resources = nv_output_create_resources, - .set_property = nv_output_set_property, -}; - -static void -nv_add_encoder(ScrnInfoPtr pScrn, struct dcb_entry *dcbent) -{ - NVPtr pNv = NVPTR(pScrn); - struct nouveau_encoder *nv_encoder = &pNv->encoders[dcbent->index]; - - nv_encoder->dcb = dcbent; - nv_encoder->last_dpms = NV_DPMS_CLEARED; - nv_encoder->dithering = pNv->FPDither; - if (pNv->FpScale && pNv->gf4_disp_arch) /* GPU Scaling */ - nv_encoder->scaling_mode = SCALE_ASPECT; - else if (nv_encoder->dcb->type == OUTPUT_LVDS) - nv_encoder->scaling_mode = SCALE_NOSCALE; - else - nv_encoder->scaling_mode = SCALE_PANEL; - if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) { - nv_encoder->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1); - if (nv_encoder->scaling_mode == SCALE_INVALID) - nv_encoder->scaling_mode = SCALE_ASPECT; /* default */ - } -} - -static void -nv_add_connector(ScrnInfoPtr pScrn, int i2c_index, int encoders, const xf86OutputFuncsRec *output_funcs, char *outputname) -{ - NVPtr pNv = NVPTR(pScrn); - xf86OutputPtr output; - struct nouveau_connector *nv_connector; - - if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname))) - return; - if (!(nv_connector = xcalloc(1, sizeof (struct nouveau_connector)))) { - xf86OutputDestroy(output); - return; - } - - output->driver_private = nv_connector; - - if (i2c_index < 0xf) - NV_I2CInit(pScrn, &nv_connector->pDDCBus, &pNv->vbios->dcb->i2c[i2c_index], xstrdup(outputname)); - nv_connector->possible_encoders = encoders; -} - -void NvSetupOutputs(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - struct parsed_dcb *dcb = pNv->vbios->dcb; - uint16_t connectors[0x10] = { 0 }; - int i, vga_count = 0, dvid_count = 0, dvii_count = 0, lvds_count = 0; - - if (!(pNv->encoders = xcalloc(dcb->entries, sizeof (struct nouveau_encoder)))) - return; - - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; - - if (dcbent->type == OUTPUT_TV) - continue; - if (dcbent->type > 3) { - NV_WARN(pScrn, "DCB type %d not known\n", dcbent->type); - continue; - } - - connectors[dcbent->i2c_index] |= 1 << i; - - nv_add_encoder(pScrn, dcbent); - } - - for (i = 0; i < dcb->entries; i++) { - struct dcb_entry *dcbent = &dcb->entry[i]; - int i2c_index = dcbent->i2c_index; - uint16_t encoders = connectors[i2c_index]; - char outputname[20]; - xf86OutputFuncsRec const *funcs = &nv_output_funcs; - - if (!encoders) - continue; - - switch (dcbent->type) { - case OUTPUT_ANALOG: - if (!MULTIPLE_ENCODERS(encoders)) - sprintf(outputname, "VGA-%d", vga_count++); - else - sprintf(outputname, "DVI-I-%d", dvii_count++); - break; - case OUTPUT_TMDS: - if (!MULTIPLE_ENCODERS(encoders)) - sprintf(outputname, "DVI-D-%d", dvid_count++); - else - sprintf(outputname, "DVI-I-%d", dvii_count++); - break; - case OUTPUT_LVDS: - sprintf(outputname, "LVDS-%d", lvds_count++); - funcs = &nv_lvds_output_funcs; - /* don't create i2c adapter when lvds ddc not allowed */ - if (dcbent->lvdsconf.use_straps_for_mode || - pNv->vbios->fp_no_ddc) - i2c_index = 0xf; - break; - default: - continue; - } - - nv_add_connector(pScrn, i2c_index, encoders, funcs, outputname); - connectors[i2c_index] = 0; /* avoid connectors being added multiply */ - } -} diff --git a/src/nv_proto.h b/src/nv_proto.h index ee1c8f2..733ee0a 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -9,11 +9,6 @@ void drmmode_remove_fb(ScrnInfoPtr pScrn); Bool drmmode_cursor_init(ScreenPtr pScreen); void drmmode_fbcon_copy(ScrnInfoPtr pScrn); -/* in nouveau_calc.c */ -void nouveau_calc_arb(ScrnInfoPtr pScrn, int vclk, int bpp, int *burst, int *lwm); -int nouveau_calc_pll_mnp(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk, - struct nouveau_pll_vals *pv); - /* in nv_accel_common.c */ Bool NVAccelCommonInit(ScrnInfoPtr pScrn); Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret); @@ -38,21 +33,6 @@ void NVWaitVSync(ScrnInfoPtr pScrn, int crtc); void NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv); unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr, int, int, int, int); -/* in nv_setup.c */ -void RivaEnterLeave(ScrnInfoPtr pScrn, Bool enter); -void NVCommonSetup(ScrnInfoPtr pScrn); - -/* in nv_cursor.c */ -Bool NVCursorInitRandr12(ScreenPtr pScreen); -void nv_crtc_show_cursor(xf86CrtcPtr crtc); -void nv_crtc_hide_cursor(xf86CrtcPtr crtc); -void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y); -void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg); -void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image); -void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image); -void nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, - int dst_stride, int bpp, uint32_t fg, uint32_t bg); - /* in nv_dma.c */ void NVSync(ScrnInfoPtr pScrn); Bool NVInitDma(ScrnInfoPtr pScrn); @@ -72,52 +52,6 @@ void nouveau_wfb_init(); /* in nv_shadow.c */ void NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); -/* in nv_bios.c */ -int NVParseBios(ScrnInfoPtr pScrn); -int call_lvds_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk); -bool nouveau_bios_fp_mode(ScrnInfoPtr pScrn, DisplayModeRec *mode); -int nouveau_bios_parse_lvds_table(ScrnInfoPtr pScrn, int pxclk, bool *dl, bool *if_is_24bit); -int run_tmds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, int pxclk); -int get_pll_limits(ScrnInfoPtr pScrn, uint32_t limit_match, struct pll_lims *pll_lim); -uint8_t * nouveau_bios_embedded_edid(ScrnInfoPtr pScrn); -int nouveau_bios_run_display_table(ScrnInfoPtr, struct dcb_entry *, int pxclk); - -/* nv_crtc.c */ -void nv_crtc_set_digital_vibrance(xf86CrtcPtr crtc, int level); -void nv_crtc_set_image_sharpening(xf86CrtcPtr crtc, int level); -void NVCrtcSetBase(xf86CrtcPtr crtc, int x, int y); -void nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num); - -/* nv_output.c */ -void nv_encoder_restore(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder); -void nv_encoder_save(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder); -void NvSetupOutputs(ScrnInfoPtr pScrn); - -/* nouveau_hw.c */ -void NVWriteVgaSeq(NVPtr pNv, int head, uint8_t index, uint8_t value); -uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index); -void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value); -uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index); -void NVSetOwner(NVPtr pNv, int owner); -int nouveau_hw_get_current_head(ScrnInfoPtr pScrn); -void NVBlankScreen(NVPtr pNv, int head, bool blank); -void nouveau_hw_setpll(ScrnInfoPtr pScrn, uint32_t reg1, - struct nouveau_pll_vals *pv); -int nouveau_hw_get_pllvals(ScrnInfoPtr pScrn, enum pll_types plltype, - struct nouveau_pll_vals *pllvals); -int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals); -int nouveau_hw_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype); -void nouveau_hw_save_vga_fonts(ScrnInfoPtr pScrn, bool save); -void nouveau_hw_save_state(ScrnInfoPtr pScrn, int head, - struct nouveau_mode_state *state); -void nouveau_hw_load_state(ScrnInfoPtr pScrn, int head, - struct nouveau_mode_state *state); -void nouveau_hw_load_state_palette(NVPtr pNv, int head, - struct nouveau_mode_state *state); - -/* in nv_i2c.c */ -int NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, struct dcb_i2c_entry *dcb_i2c, char *name); - /* in nv04_video_overlay.c */ void NV04PutOverlayImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, BoxPtr, int, int, int, int, short, short, short, @@ -213,42 +147,6 @@ void NV50EXADoneComposite(PixmapPtr); Bool NV50EXAUploadSIFC(const char *src, int src_pitch, PixmapPtr pdPix, int x, int y, int w, int h, int cpp); -/* in nv50_display.c */ -Bool NV50DispPreInit(ScrnInfoPtr); -Bool NV50DispInit(ScrnInfoPtr); -void NV50DispShutdown(ScrnInfoPtr); - -/* in nv50_cursor.c */ -Bool NV50CursorInit(ScreenPtr); -Bool NV50CursorAcquire(ScrnInfoPtr); -void NV50CursorRelease(ScrnInfoPtr); - -/* in nv50_crtc.c */ -void NV50DisplayCommand(ScrnInfoPtr pScrn, uint32_t addr, uint32_t value); -void NV50CrtcCommand(nouveauCrtcPtr crtc, uint32_t addr, uint32_t value); -void NV50CrtcInit(ScrnInfoPtr pScrn); -void NV50CrtcDestroy(ScrnInfoPtr pScrn); - -/* in nv50_output.c */ -int NV50OrOffset(nouveauOutputPtr output); -void NV50OutputSetup(ScrnInfoPtr pScrn); -void NV50OutputDestroy(ScrnInfoPtr pScrn); - -/* nv50_dac.c */ -void NV50DacSetFunctionPointers(nouveauOutputPtr output); - -/* nv50_sor.c */ -void NV50SorSetFunctionPointers(nouveauOutputPtr output); - -/* nv50_connector.c */ -void NV50ConnectorInit(ScrnInfoPtr pScrn); -void NV50ConnectorDestroy(ScrnInfoPtr pScrn); - -/* nv50_randr.c */ -void nv50_crtc_init(ScrnInfoPtr pScrn, int crtc_num); -void nv50_output_create(ScrnInfoPtr pScrn); -int nv_scaling_mode_lookup(char *name, int size); - /* nv50_xv.c */ int nv50_xv_image_put(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int, BoxPtr, int, int, int, int, uint16_t, uint16_t, diff --git a/src/nv_setup.c b/src/nv_setup.c deleted file mode 100644 index f0478ca..0000000 --- a/src/nv_setup.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2003 NVIDIA, Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "nv_include.h" - -static void nv4GetConfig (NVPtr pNv) -{ - uint32_t reg_FB0 = nvReadFB(pNv, NV_PFB_BOOT_0); - - if (reg_FB0 & 0x00000100) - pNv->RamAmountKBytes = ((reg_FB0 >> 12) & 0x0F) * 1024 * 2 + 1024 * 2; - else - switch (reg_FB0 & 0x00000003) { - case 0: - pNv->RamAmountKBytes = 1024 * 32; - break; - case 1: - pNv->RamAmountKBytes = 1024 * 4; - break; - case 2: - pNv->RamAmountKBytes = 1024 * 8; - break; - case 3: - default: - pNv->RamAmountKBytes = 1024 * 16; - break; - } -} - -static void nv10GetConfig(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - uint32_t implementation = pNv->Chipset & 0x0ff0; - struct pci_device *dev = NULL; - uint32_t data; - - if (implementation == CHIPSET_NFORCE || - implementation == CHIPSET_NFORCE2) { - dev = pci_device_find_by_slot(0, 0, 0, 1); - if (!dev) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "couldn't find bridge device\n"); - return; - } - } - -#if X_BYTE_ORDER == X_BIG_ENDIAN - if (!(nvReadMC(pNv, 0x0004) & 0x01000001)) - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Card is in big endian mode, something is very wrong !\n"); -#endif - - if (implementation == CHIPSET_NFORCE) { - pci_device_cfg_read_u32(dev, &data, 0x7c); - pNv->RamAmountKBytes = (((data >> 6) & 31) + 1) * 1024; - } else if (implementation == CHIPSET_NFORCE2) { - pci_device_cfg_read_u32(dev, &data, 0x84); - pNv->RamAmountKBytes = (((data >> 4) & 127) + 1) * 1024; - } else { - pNv->RamAmountKBytes = - (nvReadFB(pNv, NV_PFB_CSTATUS) & 0xFFF00000) >> 10; - } - - if (pNv->RamAmountKBytes > 256*1024) - pNv->RamAmountKBytes = 256*1024; -} - -void -NVCommonSetup(ScrnInfoPtr pScrn) -{ - NVPtr pNv = NVPTR(pScrn); - uint16_t implementation = pNv->Chipset & 0x0ff0; - - /* 0x01000000 is the size */ - pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->REGS); - pci_device_map_range(pNv->PciInfo, pNv->VRAMPhysical, 0x10000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->FB_BAR); - - pNv->alphaCursor = (pNv->NVArch >= 0x11); - - pNv->twoHeads = (pNv->Architecture >= NV_ARCH_10) && - (implementation != CHIPSET_NV10) && - (implementation != CHIPSET_NV15) && - (implementation != CHIPSET_NFORCE) && - (implementation != CHIPSET_NV20); - - pNv->gf4_disp_arch = pNv->twoHeads && implementation != CHIPSET_NV11; - - /* nv30 and nv35 have two stage PLLs, but use only one register; they are dealt with separately */ - pNv->two_reg_pll = (implementation == CHIPSET_NV31) || - (implementation == CHIPSET_NV36) || - (pNv->Architecture >= NV_ARCH_40); - - pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) && - (implementation != CHIPSET_NV10); - - pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04); - - /* look for known laptop chips */ - /* FIXME still probably missing some ids (for randr12, pre-nv40 mobile should be auto-detected) */ - switch(pNv->Chipset & 0xffff) { - case 0x0098: - case 0x0099: - case 0x00C8: - case 0x00C9: - case 0x00CC: - case 0x0112: - case 0x0144: - case 0x0146: - case 0x0148: - case 0x0149: - case 0x0160: - case 0x0164: - case 0x0166: - case 0x0167: - case 0x0168: - case 0x0169: - case 0x016B: - case 0x016C: - case 0x016D: - case 0x0174: - case 0x0175: - case 0x0176: - case 0x0177: - case 0x0179: - case 0x017C: - case 0x017D: - case 0x0186: - case 0x0187: - case 0x018D: - case 0x01D6: - case 0x01D7: - case 0x01D8: - case 0x0228: - case 0x0244: - case 0x0286: - case 0x028C: - case 0x0297: - case 0x0298: - case 0x0299: - case 0x0316: - case 0x0317: - case 0x031A: - case 0x031B: - case 0x031C: - case 0x031D: - case 0x031E: - case 0x031F: - case 0x0324: - case 0x0325: - case 0x0328: - case 0x0329: - case 0x032C: - case 0x032D: - case 0x0347: - case 0x0348: - case 0x0349: - case 0x034B: - case 0x034C: - case 0x0397: - case 0x0398: - case 0x039B: - pNv->Mobile = TRUE; - break; - default: - break; - } - - if (pNv->twoHeads) { - pNv->vtOWNER = nouveau_hw_get_current_head(pScrn); - - NV_TRACE(pScrn, "Initial CRTC_OWNER is %d\n", pNv->vtOWNER); - - /* we need to ensure the heads are not tied henceforth, or - * reading any 8 bit reg on head B will fail. - * setting a single arbitrary head solves that */ - NVSetOwner(pNv, 0); - } - - /* Parse the bios to initialize the card */ - if (!pNv->kms_enable) - NVParseBios(pScrn); - - if (pNv->Architecture == NV_ARCH_04) - nv4GetConfig(pNv); - else - nv10GetConfig(pScrn); -} - diff --git a/src/nv_type.h b/src/nv_type.h index 6face1f..510ec11 100644 --- a/src/nv_type.h +++ b/src/nv_type.h @@ -17,14 +17,6 @@ #error "This driver requires a DRI-enabled X server" #endif -#include "nouveau_bios.h" - -#include "nouveau_ms.h" - -#include "nouveau_crtc.h" -#include "nouveau_connector.h" -#include "nouveau_output.h" - #define NV_ARCH_03 0x03 #define NV_ARCH_04 0x04 #define NV_ARCH_10 0x10 @@ -69,74 +61,31 @@ #define CHIPSET_C512 0x03D0 #define CHIPSET_G73_BRIDGED 0x02E0 - -#undef SetBit /* some input related header also includes a macro called SetBit, which gives a lot of warnings. */ -#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b)) -#define MASKEXPAND(mask) BITMASK(1?mask,0?mask) -#define SetBF(mask,value) ((value) << (0?mask)) -#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) ) -#define SetBitField(value,from,to) SetBF(to, GetBF(value,from)) -#define SetBit(n) (1<<(n)) -#define Set8Bits(value) ((value)&0xff) - /* NV50 */ -typedef enum ORNum { - DAC0 = 0, - DAC1 = 1, - DAC2 = 2, - SOR0 = 0, - SOR1 = 1, - SOR2 = 2, -} ORNum; - typedef struct _NVRec *NVPtr; typedef struct _NVRec { - struct nouveau_mode_state saved_regs; - struct nouveau_mode_state set_state; - uint32_t saved_vga_font[4][16384]; uint32_t Architecture; EntityInfoPtr pEnt; struct pci_device *PciInfo; int Chipset; int NVArch; Bool Primary; - CARD32 IOAddress; /* VRAM physical address */ unsigned long VRAMPhysical; - /* Size of VRAM BAR */ - unsigned long VRAMPhysicalSize; - /* Accesible VRAM size (by the GPU) */ - unsigned long VRAMSize; - /* Mapped VRAM BAR */ - void * VRAMMap; - /* Accessible AGP size */ - unsigned long AGPSize; /* Various pinned memory regions */ struct nouveau_bo * scanout; struct nouveau_bo * offscreen; void * offscreen_map; - //struct nouveau_bo * FB_old; /* for KMS */ - struct nouveau_bo * shadow[2]; /* for easy acces by exa */ - struct nouveau_bo * Cursor; - struct nouveau_bo * Cursor2; struct nouveau_bo * GART; - struct nvbios VBIOS; - struct nouveau_bios_info *vbios; Bool NoAccel; Bool HWCursor; - Bool FpScale; Bool ShadowFB; unsigned char * ShadowPtr; int ShadowPitch; - uint32_t RamAmountKBytes; - volatile CARD32 *REGS; - volatile CARD32 *FB_BAR; - - uint8_t cur_head; ExaDriverPtr EXADriverPtr; Bool exa_driver_pixmaps; Bool exa_force_cp; @@ -146,48 +95,24 @@ typedef struct _NVRec { CreateScreenResourcesProcPtr CreateScreenResources; CloseScreenProcPtr CloseScreen; /* Cursor */ - uint32_t curImage[256]; - /* I2C / DDC */ - xf86Int10InfoPtr pInt10; - unsigned Int10Mode; - void (*VideoTimerCallback)(ScrnInfoPtr, Time); + uint32_t curImage[256]; + void (*VideoTimerCallback)(ScrnInfoPtr, Time); XF86VideoAdaptorPtr overlayAdaptor; XF86VideoAdaptorPtr blitAdaptor; XF86VideoAdaptorPtr textureAdaptor[2]; int videoKey; - Bool FPDither; - int Mobile; - int vtOWNER; OptionInfoPtr Options; - bool alphaCursor; - bool twoHeads; - bool gf4_disp_arch; - bool two_reg_pll; Bool LockedUp; CARD32 currentRop; - Bool WaitVSyncPossible; - Bool BlendingPossible; DRIInfoPtr pDRIInfo; drmVersionPtr pLibDRMVersion; drmVersionPtr pKernelDRMVersion; - Bool kms_enable; - - I2CBusPtr pI2CBus[DCB_MAX_NUM_I2C_ENTRIES]; - struct nouveau_encoder *encoders; - -#ifdef XF86DRM_MODE void *drmmode; /* for KMS */ Bool allow_dpms; -#endif - - nouveauCrtcPtr crtc[2]; - nouveauOutputPtr output; /* this a linked list. */ - /* Assume a connector can exist for each i2c bus. */ - nouveauConnectorPtr connector[DCB_MAX_NUM_I2C_ENTRIES]; /* DRM interface */ struct nouveau_device *dev; @@ -228,15 +153,6 @@ typedef struct _NVRec { #define NVPTR(p) ((NVPtr)((p)->driverPrivate)) -#define nvReadCurVGA(pNv, reg) NVReadVgaCrtc(pNv, pNv->cur_head, reg) -#define nvWriteCurVGA(pNv, reg, val) NVWriteVgaCrtc(pNv, pNv->cur_head, reg, val) - -#define nvReadCurRAMDAC(pNv, reg) NVReadRAMDAC(pNv, pNv->cur_head, reg) -#define nvWriteCurRAMDAC(pNv, reg, val) NVWriteRAMDAC(pNv, pNv->cur_head, reg, val) - -#define nvReadCurCRTC(pNv, reg) NVReadCRTC(pNv, pNv->cur_head, reg) -#define nvWriteCurCRTC(pNv, reg, val) NVWriteCRTC(pNv, pNv->cur_head, reg, val) - typedef struct _NVPortPrivRec { short brightness; short contrast; @@ -329,4 +245,40 @@ nouveau_pixmap_offset(PixmapPtr ppix) return exaGetPixmapOffset(ppix); } +static inline uint32_t + nv_pitch_align(NVPtr pNv, uint32_t width, int bpp) +{ + int mask; + + if (bpp == 15) + bpp = 16; + if (bpp == 24 || bpp == 30) + bpp = 8; + + /* Alignment requirements taken from the Haiku driver */ + if (pNv->Architecture == NV_ARCH_04) + mask = 128 / bpp - 1; + else + mask = 512 / bpp - 1; + + return (width + mask) & ~mask; +} + +/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */ +#define NV04_CURSOR_SIZE 32 +/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */ +#define NV10_CURSOR_SIZE 64 + +static inline int nv_cursor_width(NVPtr pNv) +{ + return pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; +} + +static inline int nv_cursor_pixels(NVPtr pNv) +{ + int width = nv_cursor_width(pNv); + + return width * width; +} + #endif /* __NV_STRUCT_H__ */ diff --git a/src/nvreg.h b/src/nvreg.h deleted file mode 100644 index 060e243..0000000 --- a/src/nvreg.h +++ /dev/null @@ -1,503 +0,0 @@ -/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */ -/* - * Copyright 1996-1997 David J. McKay - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nvreg.h,v 1.6 2002/01/25 21:56:06 tsi Exp $ */ - -#ifndef __NVREG_H_ -#define __NVREG_H_ - -#define NV_PMC_OFFSET 0x00000000 -#define NV_PMC_SIZE 0x00001000 - -#define NV_PBUS_OFFSET 0x00001000 -#define NV_PBUS_SIZE 0x00001000 - -#define NV_PFIFO_OFFSET 0x00002000 -#define NV_PFIFO_SIZE 0x00002000 - -#define NV_HDIAG_OFFSET 0x00005000 -#define NV_HDIAG_SIZE 0x00001000 - -#define NV_PRAM_OFFSET 0x00006000 -#define NV_PRAM_SIZE 0x00001000 - -#define NV_PVIDEO_OFFSET 0x00008000 -#define NV_PVIDEO_SIZE 0x00001000 - -#define NV_PTIMER_OFFSET 0x00009000 -#define NV_PTIMER_SIZE 0x00001000 - -#define NV_PPM_OFFSET 0x0000A000 -#define NV_PPM_SIZE 0x00001000 - -#define NV_PRMVGA_OFFSET 0x000A0000 -#define NV_PRMVGA_SIZE 0x00020000 - -#define NV_PRMVIO0_OFFSET 0x000C0000 -#define NV_PRMVIO_SIZE 0x00002000 -#define NV_PRMVIO1_OFFSET 0x000C2000 - -#define NV_PFB_OFFSET 0x00100000 -#define NV_PFB_SIZE 0x00001000 - -#define NV_PEXTDEV_OFFSET 0x00101000 -#define NV_PEXTDEV_SIZE 0x00001000 - -#define NV_PME_OFFSET 0x00200000 -#define NV_PME_SIZE 0x00001000 - -#define NV_PROM_OFFSET 0x00300000 -#define NV_PROM_SIZE 0x00010000 - -#define NV_PGRAPH_OFFSET 0x00400000 -#define NV_PGRAPH_SIZE 0x00010000 - -#define NV_PCRTC0_OFFSET 0x00600000 -#define NV_PCRTC0_SIZE 0x00002000 /* empirical */ - -#define NV_PRMCIO0_OFFSET 0x00601000 -#define NV_PRMCIO_SIZE 0x00002000 -#define NV_PRMCIO1_OFFSET 0x00603000 - -#define NV50_DISPLAY_OFFSET 0x00610000 -#define NV50_DISPLAY_SIZE 0x0000FFFF - -#define NV_PRAMDAC0_OFFSET 0x00680000 -#define NV_PRAMDAC0_SIZE 0x00002000 - -#define NV_PRMDIO0_OFFSET 0x00681000 -#define NV_PRMDIO_SIZE 0x00002000 -#define NV_PRMDIO1_OFFSET 0x00683000 - -#define NV_PRAMIN_OFFSET 0x00700000 -#define NV_PRAMIN_SIZE 0x00100000 - -#define NV_FIFO_OFFSET 0x00800000 -#define NV_FIFO_SIZE 0x00800000 - -#define NV_PMC_BOOT_0 0x00000000 -#define NV_PMC_ENABLE 0x00000200 - -#define NV_VIO_VSE2 0x000003c3 -#define NV_VIO_SRX 0x000003c4 - -#define NV_CIO_CRX__COLOR 0x000003d4 -#define NV_CIO_CR__COLOR 0x000003d5 - -#define NV_PBUS_DEBUG_1 0x00001084 -#define NV_PBUS_DEBUG_4 0x00001098 -#define NV_PBUS_DEBUG_DUALHEAD_CTL 0x000010f0 -#define NV_PBUS_POWERCTRL_1 0x00001584 -#define NV_PBUS_POWERCTRL_2 0x00001588 -#define NV_PBUS_POWERCTRL_4 0x00001590 -#define NV_PBUS_PCI_NV_19 0x0000184C -#define NV_PBUS_PCI_NV_20 0x00001850 -# define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0) -# define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0) - -#define NV_PFIFO_RAMHT 0x00002210 - -#define NV_PRMVIO_MISC__WRITE 0x000c03c2 -#define NV_PRMVIO_SRX 0x000c03c4 -#define NV_PRMVIO_SR 0x000c03c5 -# define NV_VIO_SR_RESET_INDEX 0x00 -# define NV_VIO_SR_CLOCK_INDEX 0x01 -# define NV_VIO_SR_PLANE_MASK_INDEX 0x02 -# define NV_VIO_SR_CHAR_MAP_INDEX 0x03 -# define NV_VIO_SR_MEM_MODE_INDEX 0x04 -#define NV_PRMVIO_MISC__READ 0x000c03cc -#define NV_PRMVIO_GRX 0x000c03ce -#define NV_PRMVIO_GX 0x000c03cf -# define NV_VIO_GX_SR_INDEX 0x00 -# define NV_VIO_GX_SREN_INDEX 0x01 -# define NV_VIO_GX_CCOMP_INDEX 0x02 -# define NV_VIO_GX_ROP_INDEX 0x03 -# define NV_VIO_GX_READ_MAP_INDEX 0x04 -# define NV_VIO_GX_MODE_INDEX 0x05 -# define NV_VIO_GX_MISC_INDEX 0x06 -# define NV_VIO_GX_DONT_CARE_INDEX 0x07 -# define NV_VIO_GX_BIT_MASK_INDEX 0x08 - -#define NV_PFB_BOOT_0 0x00100000 -#define NV_PFB_CFG0 0x00100200 -#define NV_PFB_CFG1 0x00100204 -#define NV_PFB_CSTATUS 0x0010020C -#define NV_PFB_REFCTRL 0x00100210 -# define NV_PFB_REFCTRL_VALID_1 (1 << 31) -#define NV_PFB_PAD 0x0010021C -# define NV_PFB_PAD_CKE_NORMAL (1 << 0) -#define NV_PFB_TILE_NV10 0x00100240 -#define NV_PFB_TILE_SIZE_NV10 0x00100244 -#define NV_PFB_REF 0x001002D0 -# define NV_PFB_REF_CMD_REFRESH (1 << 0) -#define NV_PFB_PRE 0x001002D4 -# define NV_PFB_PRE_CMD_PRECHARGE (1 << 0) -#define NV_PFB_CLOSE_PAGE2 0x0010033C -#define NV_PFB_TILE_NV40 0x00100600 -#define NV_PFB_TILE_SIZE_NV40 0x00100604 - -#define NV_PEXTDEV_BOOT_0 0x00101000 -# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12) -#define NV_PEXTDEV_BOOT_3 0x0010100c - -#define NV_PCRTC_INTR_0 0x00600100 -# define NV_PCRTC_INTR_0_VBLANK (1 << 0) -#define NV_PCRTC_INTR_EN_0 0x00600140 -#define NV_PCRTC_START 0x00600800 -#define NV_PCRTC_CONFIG 0x00600804 -# define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) -# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) -#define NV_PCRTC_CURSOR_CONFIG 0x00600810 -# define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) -# define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) -# define NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM (1 << 8) -# define NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32 (1 << 12) -# define NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 (1 << 16) -# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_32 (2 << 24) -# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 (4 << 24) -# define NV_PCRTC_CURSOR_CONFIG_CUR_BLEND_ALPHA (1 << 28) - -/* note: PCRTC_GPIO is not available on nv10, and in fact aliases 0x600810 */ -#define NV_PCRTC_GPIO 0x00600818 -#define NV_PCRTC_GPIO_EXT 0x0060081c -#define NV_PCRTC_830 0x00600830 -#define NV_PCRTC_834 0x00600834 -#define NV_PCRTC_850 0x00600850 -#define NV_PCRTC_ENGINE_CTRL 0x00600860 -# define NV_CRTC_FSEL_I2C (1 << 4) -# define NV_CRTC_FSEL_OVERLAY (1 << 12) - -#define NV_PRMCIO_ARX 0x006013c0 -#define NV_PRMCIO_AR__WRITE 0x006013c0 -#define NV_PRMCIO_AR__READ 0x006013c1 -# define NV_CIO_AR_MODE_INDEX 0x10 -# define NV_CIO_AR_OSCAN_INDEX 0x11 -# define NV_CIO_AR_PLANE_INDEX 0x12 -# define NV_CIO_AR_HPP_INDEX 0x13 -# define NV_CIO_AR_CSEL_INDEX 0x14 -#define NV_PRMCIO_INP0 0x006013c2 -#define NV_PRMCIO_CRX__COLOR 0x006013d4 -#define NV_PRMCIO_CR__COLOR 0x006013d5 - /* Standard VGA CRTC registers */ -# define NV_CIO_CR_HDT_INDEX 0x00 /* horizontal display total */ -# define NV_CIO_CR_HDE_INDEX 0x01 /* horizontal display end */ -# define NV_CIO_CR_HBS_INDEX 0x02 /* horizontal blanking start */ -# define NV_CIO_CR_HBE_INDEX 0x03 /* horizontal blanking end */ -# define NV_CIO_CR_HBE_4_0 4:0 -# define NV_CIO_CR_HRS_INDEX 0x04 /* horizontal retrace start */ -# define NV_CIO_CR_HRE_INDEX 0x05 /* horizontal retrace end */ -# define NV_CIO_CR_HRE_4_0 4:0 -# define NV_CIO_CR_HRE_HBE_5 7:7 -# define NV_CIO_CR_VDT_INDEX 0x06 /* vertical display total */ -# define NV_CIO_CR_OVL_INDEX 0x07 /* overflow bits */ -# define NV_CIO_CR_OVL_VDT_8 0:0 -# define NV_CIO_CR_OVL_VDE_8 1:1 -# define NV_CIO_CR_OVL_VRS_8 2:2 -# define NV_CIO_CR_OVL_VBS_8 3:3 -# define NV_CIO_CR_OVL_VDT_9 5:5 -# define NV_CIO_CR_OVL_VDE_9 6:6 -# define NV_CIO_CR_OVL_VRS_9 7:7 -# define NV_CIO_CR_RSAL_INDEX 0x08 /* normally "preset row scan" */ -# define NV_CIO_CR_CELL_HT_INDEX 0x09 /* cell height?! normally "max scan line" */ -# define NV_CIO_CR_CELL_HT_VBS_9 5:5 -# define NV_CIO_CR_CELL_HT_SCANDBL 7:7 -# define NV_CIO_CR_CURS_ST_INDEX 0x0a /* cursor start */ -# define NV_CIO_CR_CURS_END_INDEX 0x0b /* cursor end */ -# define NV_CIO_CR_SA_HI_INDEX 0x0c /* screen start address high */ -# define NV_CIO_CR_SA_LO_INDEX 0x0d /* screen start address low */ -# define NV_CIO_CR_TCOFF_HI_INDEX 0x0e /* cursor offset high */ -# define NV_CIO_CR_TCOFF_LO_INDEX 0x0f /* cursor offset low */ -# define NV_CIO_CR_VRS_INDEX 0x10 /* vertical retrace start */ -# define NV_CIO_CR_VRE_INDEX 0x11 /* vertical retrace end */ -# define NV_CIO_CR_VRE_3_0 3:0 -# define NV_CIO_CR_VDE_INDEX 0x12 /* vertical display end */ -# define NV_CIO_CR_OFFSET_INDEX 0x13 /* sets screen pitch */ -# define NV_CIO_CR_ULINE_INDEX 0x14 /* underline location */ -# define NV_CIO_CR_VBS_INDEX 0x15 /* vertical blank start */ -# define NV_CIO_CR_VBE_INDEX 0x16 /* vertical blank end */ -# define NV_CIO_CR_MODE_INDEX 0x17 /* crtc mode control */ -# define NV_CIO_CR_LCOMP_INDEX 0x18 /* line compare */ - /* Extended VGA CRTC registers */ -# define NV_CIO_CRE_RPC0_INDEX 0x19 /* repaint control 0 */ -# define NV_CIO_CRE_RPC0_OFFSET_10_8 7:5 -# define NV_CIO_CRE_RPC1_INDEX 0x1a /* repaint control 1 */ -# define NV_CIO_CRE_RPC1_LARGE 2:2 -# define NV_CIO_CRE_FF_INDEX 0x1b /* fifo control */ -# define NV_CIO_CRE_ENH_INDEX 0x1c /* enhanced? */ -# define NV_CIO_SR_LOCK_INDEX 0x1f /* crtc lock */ -# define NV_CIO_SR_UNLOCK_RW_VALUE 0x57 -# define NV_CIO_SR_LOCK_VALUE 0x99 -# define NV_CIO_CRE_FFLWM__INDEX 0x20 /* fifo low water mark */ -# define NV_CIO_CRE_21 0x21 /* vga shadow crtc lock */ -# define NV_CIO_CRE_LSR_INDEX 0x25 /* ? */ -# define NV_CIO_CRE_LSR_VDT_10 0:0 -# define NV_CIO_CRE_LSR_VDE_10 1:1 -# define NV_CIO_CRE_LSR_VRS_10 2:2 -# define NV_CIO_CRE_LSR_VBS_10 3:3 -# define NV_CIO_CRE_LSR_HBE_6 4:4 -# define NV_CIO_CR_ARX_INDEX 0x26 /* attribute index -- ro copy of 0x60.3c0 */ -# define NV_CIO_CRE_CHIP_ID_INDEX 0x27 /* chip revision */ -# define NV_CIO_CRE_PIXEL_INDEX 0x28 -# define NV_CIO_CRE_PIXEL_FORMAT 1:0 -# define NV_CIO_CRE_HEB__INDEX 0x2d /* horizontal extra bits? */ -# define NV_CIO_CRE_HEB_HDT_8 0:0 -# define NV_CIO_CRE_HEB_HDE_8 1:1 -# define NV_CIO_CRE_HEB_HBS_8 2:2 -# define NV_CIO_CRE_HEB_HRS_8 3:3 -# define NV_CIO_CRE_HEB_ILC_8 4:4 -# define NV_CIO_CRE_2E 0x2e /* some scratch or dummy reg to force writes to sink in */ -# define NV_CIO_CRE_HCUR_ADDR2_INDEX 0x2f /* cursor */ -# define NV_CIO_CRE_HCUR_ADDR0_INDEX 0x30 /* pixmap */ -# define NV_CIO_CRE_HCUR_ADDR0_ADR 6:0 -# define NV_CIO_CRE_HCUR_ASI 7:7 -# define NV_CIO_CRE_HCUR_ADDR1_INDEX 0x31 /* address */ -# define NV_CIO_CRE_HCUR_ADDR1_ENABLE 0:0 -# define NV_CIO_CRE_HCUR_ADDR1_CUR_DBL 1:1 -# define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2 -# define NV_CIO_CRE_LCD__INDEX 0x33 -# define NV_CIO_CRE_LCD_LCD_SELECT 0:0 -# define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36 -# define NV_CIO_CRE_DDC0_WR__INDEX 0x37 -# define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */ -# define NV_CIO_CRE_SCRATCH3__INDEX 0x3b -# define NV_CIO_CRE_SCRATCH4__INDEX 0x3c -# define NV_CIO_CRE_DDC_STATUS__INDEX 0x3e -# define NV_CIO_CRE_DDC_WR__INDEX 0x3f -# define NV_CIO_CRE_EBR_INDEX 0x41 /* extra bits ? (vertical) */ -# define NV_CIO_CRE_EBR_VDT_11 0:0 -# define NV_CIO_CRE_EBR_VDE_11 2:2 -# define NV_CIO_CRE_EBR_VRS_11 4:4 -# define NV_CIO_CRE_EBR_VBS_11 6:6 -# define NV_CIO_CRE_44 0x44 /* head control */ -# define NV_CIO_CRE_CSB 0x45 /* colour saturation boost */ -# define NV_CIO_CRE_RCR 0x46 -# define NV_CIO_CRE_RCR_ENDIAN_BIG 7:7 -# define NV_CIO_CRE_47 0x47 /* extended fifo lwm, used on nv30+ */ -# define NV_CIO_CRE_4B 0x4b /* given patterns in 0x[2-3][a-c] regs, probably scratch 6 */ -# define NV_CIO_CRE_TVOUT_LATENCY 0x52 -# define NV_CIO_CRE_53 0x53 /* `fp_htiming' according to Haiku */ -# define NV_CIO_CRE_54 0x54 /* `fp_vtiming' according to Haiku */ -# define NV_CIO_CRE_57 0x57 /* index reg for cr58 */ -# define NV_CIO_CRE_58 0x58 /* data reg for cr57 */ -# define NV_CIO_CRE_59 0x59 /* related to on/off-chip-ness of digital outputs */ -# define NV_CIO_CRE_5B 0x5B /* newer colour saturation reg */ -# define NV_CIO_CRE_85 0x85 -# define NV_CIO_CRE_86 0x86 -#define NV_PRMCIO_INP0__COLOR 0x006013da - -#define NV_PRAMDAC_CU_START_POS 0x00680300 -# define NV_PRAMDAC_CU_START_POS_X 15:0 -# define NV_PRAMDAC_CU_START_POS_Y 31:16 -#define NV_RAMDAC_NV10_CURSYNC 0x00680404 - -#define NV_PRAMDAC_NVPLL_COEFF 0x00680500 -#define NV_PRAMDAC_MPLL_COEFF 0x00680504 -#define NV_PRAMDAC_VPLL_COEFF 0x00680508 -# define NV30_RAMDAC_ENABLE_VCO2 (8 << 4) - -#define NV_PRAMDAC_PLL_COEFF_SELECT 0x0068050c -# define NV_RAMDAC_PLL_SELECT_USE_VPLL2_TRUE (4 << 0) -# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL (1 << 8) -# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL (2 << 8) -# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL (4 << 8) -# define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2 (8 << 8) -# define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2 (1 << 28) -# define NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2 (2 << 28) - -#define NV_PRAMDAC_PLL_SETUP_CONTROL 0x00680510 -#define NV_RAMDAC_VPLL2 0x00680520 -#define NV_PRAMDAC_SEL_CLK 0x00680524 -#define NV_RAMDAC_DITHER_NV11 0x00680528 -#define NV_PRAMDAC_DACCLK 0x0068052c -# define NV_PRAMDAC_DACCLK_SEL_DACCLK (1 << 0) - -#define NV_RAMDAC_NVPLL_B 0x00680570 -#define NV_RAMDAC_MPLL_B 0x00680574 -#define NV_RAMDAC_VPLL_B 0x00680578 -#define NV_RAMDAC_VPLL2_B 0x0068057c -# define NV31_RAMDAC_ENABLE_VCO2 (8 << 28) -#define NV_PRAMDAC_580 0x00680580 -# define NV_RAMDAC_580_VPLL1_ACTIVE (1 << 8) -# define NV_RAMDAC_580_VPLL2_ACTIVE (1 << 28) - -#define NV_PRAMDAC_GENERAL_CONTROL 0x00680600 -# define NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON (3 << 4) -# define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL (1 << 8) -# define NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL (1 << 12) -# define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM (2 << 16) -# define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS (1 << 20) -# define NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG (2 << 28) -#define NV_PRAMDAC_TEST_CONTROL 0x00680608 -# define NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED (1 << 12) -# define NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF (1 << 16) -# define NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI (1 << 28) -#define NV_PRAMDAC_TESTPOINT_DATA 0x00680610 -# define NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK (8 << 28) -#define NV_PRAMDAC_630 0x00680630 -#define NV_PRAMDAC_634 0x00680634 - -#define NV_PRAMDAC_FP_VDISPLAY_END 0x00680800 -#define NV_PRAMDAC_FP_VTOTAL 0x00680804 -#define NV_PRAMDAC_FP_VCRTC 0x00680808 -#define NV_PRAMDAC_FP_VSYNC_START 0x0068080c -#define NV_PRAMDAC_FP_VSYNC_END 0x00680810 -#define NV_PRAMDAC_FP_VVALID_START 0x00680814 -#define NV_PRAMDAC_FP_VVALID_END 0x00680818 -#define NV_PRAMDAC_FP_HDISPLAY_END 0x00680820 -#define NV_PRAMDAC_FP_HTOTAL 0x00680824 -#define NV_PRAMDAC_FP_HCRTC 0x00680828 -#define NV_PRAMDAC_FP_HSYNC_START 0x0068082c -#define NV_PRAMDAC_FP_HSYNC_END 0x00680830 -#define NV_PRAMDAC_FP_HVALID_START 0x00680834 -#define NV_PRAMDAC_FP_HVALID_END 0x00680838 - -#define NV_RAMDAC_FP_DITHER 0x0068083c -#define NV_PRAMDAC_FP_TG_CONTROL 0x00680848 -# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS (1 << 0) -# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE (2 << 0) -# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS (1 << 4) -# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE (2 << 4) -# define NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE (0 << 8) -# define NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER (1 << 8) -# define NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE (2 << 8) -# define NV_PRAMDAC_FP_TG_CONTROL_READ_PROG (1 << 20) -# define NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 (1 << 24) -# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS (1 << 28) -# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE (2 << 28) -#define NV_PRAMDAC_850 0x00680850 -#define NV_PRAMDAC_85C 0x0068085c -#define NV_PRAMDAC_FP_DEBUG_0 0x00680880 -# define NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE (1 << 0) -# define NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE (1 << 4) -/* This doesn't seem to be essential for tmds, but still often set */ -# define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED (8 << 4) -# define NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR (1 << 8) -# define NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR (1 << 12) -# define NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND (1 << 20) -# define NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND (1 << 24) -# define NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1 << 28) -#define NV_PRAMDAC_FP_DEBUG_1 0x00680884 -# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE 11:0 -# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE (1 << 12) -# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE 27:16 -# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE (1 << 28) -#define NV_PRAMDAC_FP_DEBUG_2 0x00680888 -#define NV_PRAMDAC_FP_DEBUG_3 0x0068088C - -/* see NV_PRAMDAC_INDIR_TMDS in rules.xml */ -#define NV_PRAMDAC_FP_TMDS_CONTROL 0x006808b0 -# define NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE (1 << 16) -#define NV_PRAMDAC_FP_TMDS_DATA 0x006808b4 - -/* Some kind of switch */ -#define NV_PRAMDAC_900 0x00680900 -#define NV_PRAMDAC_A20 0x00680A20 -#define NV_PRAMDAC_A24 0x00680A24 -#define NV_PRAMDAC_A34 0x00680A34 - -/* names fabricated from NV_USER_DAC info */ -#define NV_PRMDIO_PIXEL_MASK 0x006813c6 -# define NV_PRMDIO_PIXEL_MASK_MASK 0xff -#define NV_PRMDIO_READ_MODE_ADDRESS 0x006813c7 -#define NV_PRMDIO_WRITE_MODE_ADDRESS 0x006813c8 -#define NV_PRMDIO_PALETTE_DATA 0x006813c9 - -#define NV_PGRAPH_DEBUG_0 0x00400080 -#define NV_PGRAPH_DEBUG_1 0x00400084 -#define NV_PGRAPH_DEBUG_2_NV04 0x00400088 -#define NV_PGRAPH_DEBUG_2 0x00400620 -#define NV_PGRAPH_DEBUG_3 0x0040008c -#define NV_PGRAPH_DEBUG_4 0x00400090 -#define NV_PGRAPH_INTR 0x00400100 -#define NV_PGRAPH_INTR_EN 0x00400140 -#define NV_PGRAPH_CTX_CONTROL 0x00400144 -#define NV_PGRAPH_CTX_CONTROL_NV04 0x00400170 -#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C -#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540 -#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544 -#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548 -#define NV_PGRAPH_BETA_AND 0x00400608 -#define NV_PGRAPH_LIMIT_VIOL_PIX 0x00400610 -#define NV_PGRAPH_BOFFSET0 0x00400640 -#define NV_PGRAPH_BOFFSET1 0x00400644 -#define NV_PGRAPH_BOFFSET2 0x00400648 -#define NV_PGRAPH_BLIMIT0 0x00400684 -#define NV_PGRAPH_BLIMIT1 0x00400688 -#define NV_PGRAPH_BLIMIT2 0x0040068c -#define NV_PGRAPH_STATUS 0x00400700 -#define NV_PGRAPH_SURFACE 0x00400710 -#define NV_PGRAPH_STATE 0x00400714 -#define NV_PGRAPH_FIFO 0x00400720 -#define NV_PGRAPH_PATTERN_SHAPE 0x00400810 -#define NV_PGRAPH_TILE 0x00400b00 - -#define NV_PVIDEO_INTR_EN 0x00008140 -#define NV_PVIDEO_BUFFER 0x00008700 -#define NV_PVIDEO_STOP 0x00008704 -#define NV_PVIDEO_UVPLANE_BASE(buff) (0x00008800+(buff)*4) -#define NV_PVIDEO_UVPLANE_LIMIT(buff) (0x00008808+(buff)*4) -#define NV_PVIDEO_UVPLANE_OFFSET_BUFF(buff) (0x00008820+(buff)*4) -#define NV_PVIDEO_BASE(buff) (0x00008900+(buff)*4) -#define NV_PVIDEO_LIMIT(buff) (0x00008908+(buff)*4) -#define NV_PVIDEO_LUMINANCE(buff) (0x00008910+(buff)*4) -#define NV_PVIDEO_CHROMINANCE(buff) (0x00008918+(buff)*4) -#define NV_PVIDEO_OFFSET_BUFF(buff) (0x00008920+(buff)*4) -#define NV_PVIDEO_SIZE_IN(buff) (0x00008928+(buff)*4) -#define NV_PVIDEO_POINT_IN(buff) (0x00008930+(buff)*4) -#define NV_PVIDEO_DS_DX(buff) (0x00008938+(buff)*4) -#define NV_PVIDEO_DT_DY(buff) (0x00008940+(buff)*4) -#define NV_PVIDEO_POINT_OUT(buff) (0x00008948+(buff)*4) -#define NV_PVIDEO_SIZE_OUT(buff) (0x00008950+(buff)*4) -#define NV_PVIDEO_FORMAT(buff) (0x00008958+(buff)*4) -# define NV_PVIDEO_FORMAT_PLANAR (1 << 0) -# define NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8 (1 << 16) -# define NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY (1 << 20) -# define NV_PVIDEO_FORMAT_MATRIX_ITURBT709 (1 << 24) -#define NV_PVIDEO_COLOR_KEY 0x00008B00 - -/* NV04 overlay defines from VIDIX & Haiku */ -#define NV_PVIDEO_INTR_EN_0 0x00680140 -#define NV_PVIDEO_STEP_SIZE 0x00680200 -#define NV_PVIDEO_CONTROL_Y 0x00680204 -#define NV_PVIDEO_CONTROL_X 0x00680208 -#define NV_PVIDEO_BUFF0_START_ADDRESS 0x0068020c -#define NV_PVIDEO_BUFF0_PITCH_LENGTH 0x00680214 -#define NV_PVIDEO_BUFF0_OFFSET 0x0068021c -#define NV_PVIDEO_BUFF1_START_ADDRESS 0x00680210 -#define NV_PVIDEO_BUFF1_PITCH_LENGTH 0x00680218 -#define NV_PVIDEO_BUFF1_OFFSET 0x00680220 -#define NV_PVIDEO_OE_STATE 0x00680224 -#define NV_PVIDEO_SU_STATE 0x00680228 -#define NV_PVIDEO_RM_STATE 0x0068022c -#define NV_PVIDEO_WINDOW_START 0x00680230 -#define NV_PVIDEO_WINDOW_SIZE 0x00680234 -#define NV_PVIDEO_FIFO_THRES_SIZE 0x00680238 -#define NV_PVIDEO_FIFO_BURST_LENGTH 0x0068023c -#define NV_PVIDEO_KEY 0x00680240 -#define NV_PVIDEO_OVERLAY 0x00680244 -#define NV_PVIDEO_RED_CSC_OFFSET 0x00680280 -#define NV_PVIDEO_GREEN_CSC_OFFSET 0x00680284 -#define NV_PVIDEO_BLUE_CSC_OFFSET 0x00680288 -#define NV_PVIDEO_CSC_ADJUST 0x0068028c - -#endif -- cgit v1.2.3