summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-01-06 14:58:15 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-01-11 09:46:23 +1000
commit17485c234ff191cee3dd19e3dd693a80b024e189 (patch)
treee69ec488f0ec8b186d4e8a39eecc0ee7b8e64308
parent061cb284b93612848296599759b915a4d66b6d01 (diff)
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 <bskeggs@redhat.com> Signed-off-by: Francisco Jerez <currojerez@riseup.net> Acked-by: Maarten Maathuis <madman2003@gmail.com>
-rw-r--r--configure.ac27
-rw-r--r--src/Makefile.am25
-rw-r--r--src/drmmode_display.c57
-rw-r--r--src/nouveau_bios.h224
-rw-r--r--src/nouveau_calc.c617
-rw-r--r--src/nouveau_connector.h65
-rw-r--r--src/nouveau_crtc.h91
-rw-r--r--src/nouveau_exa.c6
-rw-r--r--src/nouveau_hw.c1031
-rw-r--r--src/nouveau_hw.h352
-rw-r--r--src/nouveau_modeset.h31
-rw-r--r--src/nouveau_ms.h159
-rw-r--r--src/nouveau_output.h69
-rw-r--r--src/nouveau_xv.c39
-rw-r--r--src/nv04_xv_blit.c8
-rw-r--r--src/nv04_xv_ovl.c6
-rw-r--r--src/nv10_exa.c12
-rw-r--r--src/nv10_xv_ovl.c12
-rw-r--r--src/nv30_exa.c2
-rw-r--r--src/nv30_xv_tex.c5
-rw-r--r--src/nv40_exa.c3
-rw-r--r--src/nv40_xv_tex.c5
-rw-r--r--src/nv50_connector.c123
-rw-r--r--src/nv50_crtc.c535
-rw-r--r--src/nv50_cursor.c77
-rw-r--r--src/nv50_dac.c225
-rw-r--r--src/nv50_display.c150
-rw-r--r--src/nv50_output.c236
-rw-r--r--src/nv50_randr.c899
-rw-r--r--src/nv50_randr.h41
-rw-r--r--src/nv50_sor.c216
-rw-r--r--src/nv50reg.h449
-rw-r--r--src/nv_accel_common.c4
-rw-r--r--src/nv_bios.c4810
-rw-r--r--src/nv_const.h8
-rw-r--r--src/nv_crtc.c1095
-rw-r--r--src/nv_cursor.c216
-rw-r--r--src/nv_dma.c1
-rw-r--r--src/nv_driver.c539
-rw-r--r--src/nv_i2c.c158
-rw-r--r--src/nv_include.h3
-rw-r--r--src/nv_output.c1293
-rw-r--r--src/nv_proto.h102
-rw-r--r--src/nv_setup.c207
-rw-r--r--src/nv_type.h124
-rw-r--r--src/nvreg.h503
46 files changed, 176 insertions, 14684 deletions
diff --git a/configure.ac b/configure.ac
index e917c01..201bfc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -22,18 +22,18 @@
22 22
23AC_PREREQ(2.57) 23AC_PREREQ(2.57)
24AC_INIT([xf86-video-nouveau], 24AC_INIT([xf86-video-nouveau],
25 0.0.10, 25 0.0.15,
26 [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], 26 [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
27 xf86-video-nouveau) 27 xf86-video-nouveau)
28 28
29AC_DEFINE_UNQUOTED([NV_MAJOR_VERSION], 29AC_DEFINE_UNQUOTED([NV_MAJOR_VERSION],
30 [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]\)\.[[0-9]]\.[[0-9]]/\1/')], 30 [$(echo $PACKAGE_VERSION | sed -e 's/^\([[0-9]]*\)\.[[0-9]]*\.[[0-9]]*/\1/')],
31 [Major version]) 31 [Major version])
32AC_DEFINE_UNQUOTED([NV_MINOR_VERSION], 32AC_DEFINE_UNQUOTED([NV_MINOR_VERSION],
33 [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.\([[0-9]]\)\.[[0-9]]/\1/')], 33 [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.\([[0-9]]*\)\.[[0-9]]*/\1/')],
34 [Minor version]) 34 [Minor version])
35AC_DEFINE_UNQUOTED([NV_PATCHLEVEL], 35AC_DEFINE_UNQUOTED([NV_PATCHLEVEL],
36 [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]\.[[0-9]]\.\([[0-9]]\)/\1/')], 36 [$(echo $PACKAGE_VERSION | sed -e 's/^[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)/\1/')],
37 [Patch version]) 37 [Patch version])
38AC_DEFINE_UNQUOTED([NV_DRIVER_DATE], 38AC_DEFINE_UNQUOTED([NV_DRIVER_DATE],
39 [$(echo -n \";git log |head -3|tail -1|tr -d '\n';echo -n \")], 39 [$(echo -n \";git log |head -3|tail -1|tr -d '\n';echo -n \")],
@@ -96,25 +96,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ ]])],
96# needed for the next test 96# needed for the next test
97CFLAGS="$CFLAGS $XORG_CFLAGS" 97CFLAGS="$CFLAGS $XORG_CFLAGS"
98 98
99AC_MSG_CHECKING(for DRM modesetting)
100AC_ARG_WITH(
101 kms,
102 [ --with-kms=yes,no compile with drm modesetting support (default: auto)],
103 kms="$withval",
104 kms="yes")
105AC_MSG_RESULT($kms)
106
107if test "x$kms" = xyes; then
108 AC_CHECK_HEADER([xf86drmMode.h],[kms=yes],[kms=no],
109 [#include <stdint.h>
110 #include <stdlib.h> ]
111 )
112fi
113
114if test "x$kms" = xyes; then
115 AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting])
116fi
117
118AC_SUBST([CFLAGS]) 99AC_SUBST([CFLAGS])
119AC_SUBST([moduledir]) 100AC_SUBST([moduledir])
120 101
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@
29nouveau_drv_ladir = @moduledir@/drivers 29nouveau_drv_ladir = @moduledir@/drivers
30 30
31nouveau_drv_la_SOURCES = \ 31nouveau_drv_la_SOURCES = \
32 nouveau_bios.h \
33 nouveau_calc.c \
34 nouveau_hw.c nouveau_hw.h \
35 nouveau_local.h \ 32 nouveau_local.h \
36 nouveau_ms.h \
37 nouveau_exa.c nouveau_xv.c nouveau_dri2.c \ 33 nouveau_exa.c nouveau_xv.c nouveau_dri2.c \
38 nouveau_wfb.c \ 34 nouveau_wfb.c \
39 nv_accel_common.c \ 35 nv_accel_common.c \
40 nv_bios.c \
41 nv_const.h \ 36 nv_const.h \
42 nv_cursor.c \
43 nv_dma.c \ 37 nv_dma.c \
44 nv_dma.h \ 38 nv_dma.h \
45 nv_dri.c \ 39 nv_dri.c \
@@ -49,13 +43,8 @@ nouveau_drv_la_SOURCES = \
49 nv_dripriv.h \ 43 nv_dripriv.h \
50 nv_local.h \ 44 nv_local.h \
51 nv_proto.h \ 45 nv_proto.h \
52 nvreg.h \
53 nv_setup.c \
54 nv_shadow.c \ 46 nv_shadow.c \
55 nv_type.h \ 47 nv_type.h \
56 nv_crtc.c \
57 nv_output.c \
58 nv_i2c.c \
59 nv04_exa.c \ 48 nv04_exa.c \
60 nv04_xv_ovl.c \ 49 nv04_xv_ovl.c \
61 nv04_xv_blit.c \ 50 nv04_xv_blit.c \
@@ -68,23 +57,9 @@ nouveau_drv_la_SOURCES = \
68 nv40_exa.c \ 57 nv40_exa.c \
69 nv40_xv_tex.c \ 58 nv40_xv_tex.c \
70 nv50_accel.c nv50_accel.h \ 59 nv50_accel.c nv50_accel.h \
71 nv50_cursor.c \
72 nv50_crtc.c \
73 nv50_dac.c \
74 nv50_display.c \
75 nv50_exa.c \ 60 nv50_exa.c \
76 nv50_output.c \
77 nv50_sor.c \
78 nv50_randr.c \
79 nv50_randr.h \
80 nv50_connector.c \
81 nv50_xv.c \ 61 nv50_xv.c \
82 nv50_texture.h \ 62 nv50_texture.h \
83 nv50reg.h \
84 nouveau_crtc.h \
85 nouveau_output.h \
86 nouveau_connector.h \
87 nouveau_modeset.h \
88 drmmode_display.c \ 63 drmmode_display.c \
89 vl_hwmc.c \ 64 vl_hwmc.c \
90 vl_hwmc.h 65 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 @@
33 33
34#include "xorgVersion.h" 34#include "xorgVersion.h"
35 35
36#ifdef XF86DRM_MODE
37#include "nv_include.h" 36#include "nv_include.h"
38#include "xf86drmMode.h" 37#include "xf86drmMode.h"
39#include "X11/Xatom.h" 38#include "X11/Xatom.h"
@@ -368,6 +367,52 @@ done:
368 return ret; 367 return ret;
369} 368}
370 369
370#define SOURCE_MASK_INTERLEAVE 32
371#define TRANSPARENT_PIXEL 0
372
373/*
374 * Convert a source/mask bitmap cursor to an ARGB cursor, clipping or
375 * padding as necessary. source/mask are assumed to be alternated each
376 * SOURCE_MASK_INTERLEAVE bits.
377 */
378void
379nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride,
380 int bpp, uint32_t fg, uint32_t bg)
381{
382 int width = min(src_stride, dst_stride);
383 uint32_t b, m, pxval;
384 int i, j, k;
385
386 for (i = 0; i < width; i++) {
387 for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) {
388 int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j;
389 int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE;
390
391 b = src[2*src_off];
392 m = src[2*src_off + 1];
393
394 for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) {
395 pxval = TRANSPARENT_PIXEL;
396#if X_BYTE_ORDER == X_BIG_ENDIAN
397 if (m & 0x80000000)
398 pxval = (b & 0x80000000) ? fg : bg;
399 b <<= 1;
400 m <<= 1;
401#else
402 if (m & 1)
403 pxval = (b & 1) ? fg : bg;
404 b >>= 1;
405 m >>= 1;
406#endif
407 if (bpp == 32)
408 ((uint32_t *)dst)[dst_off + k] = pxval;
409 else
410 ((uint16_t *)dst)[dst_off + k] = pxval;
411 }
412 }
413 }
414}
415
371static void 416static void
372drmmode_reload_cursor_image(xf86CrtcPtr crtc) 417drmmode_reload_cursor_image(xf86CrtcPtr crtc)
373{ 418{
@@ -430,7 +475,6 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
430 } 475 }
431} 476}
432 477
433
434static void 478static void
435drmmode_hide_cursor (xf86CrtcPtr crtc) 479drmmode_hide_cursor (xf86CrtcPtr crtc)
436{ 480{
@@ -1196,9 +1240,6 @@ drmmode_is_rotate_pixmap(PixmapPtr ppix, struct nouveau_bo **bo)
1196 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); 1240 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn);
1197 int i; 1241 int i;
1198 1242
1199 if (!NVPTR(pScrn)->kms_enable)
1200 return FALSE;
1201
1202 for (i = 0; i < config->num_crtc; i++) { 1243 for (i = 0; i < config->num_crtc; i++) {
1203 xf86CrtcPtr crtc = config->crtc[i]; 1244 xf86CrtcPtr crtc = config->crtc[i];
1204 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 1245 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@@ -1237,9 +1278,6 @@ drmmode_remove_fb(ScrnInfoPtr pScrn)
1237 drmmode_crtc_private_ptr drmmode_crtc; 1278 drmmode_crtc_private_ptr drmmode_crtc;
1238 drmmode_ptr drmmode; 1279 drmmode_ptr drmmode;
1239 1280
1240 if (!NVPTR(pScrn)->kms_enable)
1241 return;
1242
1243 if (config) 1281 if (config)
1244 crtc = config->crtc[0]; 1282 crtc = config->crtc[0];
1245 if (!crtc) 1283 if (!crtc)
@@ -1260,10 +1298,9 @@ drmmode_cursor_init(ScreenPtr pScreen)
1260 int size = nv_cursor_width(pNv); 1298 int size = nv_cursor_width(pNv);
1261 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 1299 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1262 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 | 1300 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
1263 (pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0) | 1301 (pNv->NVArch >= 0x11 ? HARDWARE_CURSOR_ARGB : 0) |
1264 HARDWARE_CURSOR_UPDATE_UNHIDDEN; 1302 HARDWARE_CURSOR_UPDATE_UNHIDDEN;
1265 1303
1266 return xf86_cursors_init(pScreen, size, size, flags); 1304 return xf86_cursors_init(pScreen, size, size, flags);
1267} 1305}
1268 1306
1269#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 @@
1/*
2 * Copyright 2007-2008 Nouveau Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#ifndef __NOUVEAU_BIOS_H__
25#define __NOUVEAU_BIOS_H__
26
27#include "nvreg.h"
28
29#define DCB_MAX_NUM_ENTRIES 16
30#define DCB_MAX_NUM_I2C_ENTRIES 16
31
32#define DCB_LOC_ON_CHIP 0
33
34struct dcb_entry {
35 int index; /* may not be raw dcb index if merging has happened */
36 uint8_t type;
37 uint8_t i2c_index;
38 uint8_t heads;
39 uint8_t bus;
40 uint8_t location;
41 uint8_t or;
42 bool duallink_possible;
43 union {
44 struct {
45 int maxfreq;
46 } crtconf;
47 struct {
48 bool use_straps_for_mode;
49 bool use_power_scripts;
50 } lvdsconf;
51 };
52 bool i2c_upper_default;
53};
54
55struct dcb_i2c_entry {
56 uint8_t port_type;
57 uint8_t read, write;
58 I2CBusPtr chan;
59};
60
61struct parsed_dcb {
62 int entries;
63 struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
64 struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
65};
66
67struct bios_parsed_dcb {
68 uint8_t version;
69
70 struct parsed_dcb dcb;
71
72 uint16_t init8e_table_ptr;
73 uint8_t *i2c_table;
74 uint8_t i2c_default_indices;
75};
76
77enum nouveau_encoder_type
78{
79 /* 0-3 match DCB types */
80 OUTPUT_NONE = 4,
81 OUTPUT_ANALOG = 0,
82 OUTPUT_TMDS = 2,
83 OUTPUT_LVDS = 3,
84 OUTPUT_TV = 1,
85 OUTPUT_ANY = 5,
86};
87
88#define IS_DFP(t) (t == OUTPUT_LVDS || t == OUTPUT_TMDS)
89
90enum nouveau_or {
91 OUTPUT_A = (1 << 0),
92 OUTPUT_B = (1 << 1),
93 OUTPUT_C = (1 << 2)
94};
95
96enum LVDS_script {
97 /* Order *does* matter here */
98 LVDS_INIT = 1,
99 LVDS_RESET,
100 LVDS_BACKLIGHT_ON,
101 LVDS_BACKLIGHT_OFF,
102 LVDS_PANEL_ON,
103 LVDS_PANEL_OFF
104};
105
106/* changing these requires matching changes to reg tables in nv_get_clock */
107#define MAX_PLL_TYPES 4
108enum pll_types {
109 NVPLL,
110 MPLL,
111 VPLL1,
112 VPLL2
113};
114
115struct pll_lims {
116 struct {
117 int minfreq;
118 int maxfreq;
119 int min_inputfreq;
120 int max_inputfreq;
121
122 uint8_t min_m;
123 uint8_t max_m;
124 uint8_t min_n;
125 uint8_t max_n;
126 } vco1, vco2;
127
128 uint8_t max_log2p;
129 /*
130 * for most pre nv50 cards setting a log2P of 7 (the common max_log2p
131 * value) is no different to 6 (at least for vplls) so allowing the MNP
132 * calc to use 7 causes the generated clock to be out by a factor of 2.
133 * however, max_log2p cannot be fixed-up during parsing as the
134 * unmodified max_log2p value is still needed for setting mplls, hence
135 * an additional max_usable_log2p member
136 */
137 uint8_t max_usable_log2p;
138 uint8_t log2p_bias;
139 int refclk;
140};
141
142struct nouveau_bios_info {
143 struct parsed_dcb *dcb;
144
145 uint8_t chip_version;
146
147 uint32_t dactestval;
148 uint8_t digital_min_front_porch;
149 bool fp_no_ddc;
150};
151
152struct nvbios {
153 struct nouveau_bios_info pub;
154
155 uint8_t data[NV_PROM_SIZE];
156 unsigned int length;
157 bool execute;
158
159 uint8_t major_version;
160 uint8_t feature_byte;
161 bool is_mobile;
162
163 uint32_t fmaxvco, fminvco;
164
165 bool old_style_init;
166 uint16_t init_script_tbls_ptr;
167 uint16_t extra_init_script_tbl_ptr;
168 uint16_t macro_index_tbl_ptr;
169 uint16_t macro_tbl_ptr;
170 uint16_t condition_tbl_ptr;
171 uint16_t io_condition_tbl_ptr;
172 uint16_t io_flag_condition_tbl_ptr;
173 uint16_t init_function_tbl_ptr;
174
175 uint16_t pll_limit_tbl_ptr;
176 uint16_t ram_restrict_tbl_ptr;
177
178 struct bios_parsed_dcb bdcb;
179
180 struct {
181 int head;
182 uint16_t script_table_ptr;
183 } display;
184
185 struct {
186 uint16_t fptablepointer; /* also used by tmds */
187 uint16_t fpxlatetableptr;
188 int xlatwidth;
189 uint16_t lvdsmanufacturerpointer;
190 uint16_t fpxlatemanufacturertableptr;
191 uint16_t mode_ptr;
192 uint16_t xlated_entry;
193 bool power_off_for_reset;
194 bool reset_after_pclk_change;
195 bool dual_link;
196 bool link_c_increment;
197 bool BITbit1;
198 int duallink_transition_clk;
199 uint8_t *edid;
200
201 /* will need resetting after suspend */
202 int last_script_invoc;
203 bool lvds_init_run;
204 } fp;
205
206 struct {
207 uint16_t output0_script_ptr;
208 uint16_t output1_script_ptr;
209 } tmds;
210
211 struct {
212 uint16_t mem_init_tbl_ptr;
213 uint16_t sdr_seq_tbl_ptr;
214 uint16_t ddr_seq_tbl_ptr;
215
216 struct {
217 uint8_t crt, tv, panel;
218 } i2c_indices;
219
220 uint16_t lvds_single_a_script_ptr;
221 } legacy;
222};
223
224#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 @@
1/*
2 * Copyright 1993-2003 NVIDIA, Corporation
3 * Copyright 2007-2009 Stuart Bennett
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "nv_include.h"
25
26/****************************************************************************\
27* *
28* The video arbitration routines calculate some "magic" numbers. Fixes *
29* the snow seen when accessing the framebuffer without it. *
30* It just works (I hope). *
31* *
32\****************************************************************************/
33
34struct nv_fifo_info {
35 int graphics_lwm;
36 int video_lwm;
37 int graphics_burst_size;
38 int video_burst_size;
39 bool valid;
40};
41
42struct nv_sim_state {
43 int pclk_khz;
44 int mclk_khz;
45 int nvclk_khz;
46 int pix_bpp;
47 bool enable_mp;
48 bool enable_video;
49 int mem_page_miss;
50 int mem_latency;
51 int memory_type;
52 int memory_width;
53};
54
55static void nv4CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
56{
57 int pagemiss, cas, width, video_enable, bpp;
58 int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
59 int found, mclk_extra, mclk_loop, cbs, m1, p1;
60 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
61 int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
62 int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
63
64 pclk_freq = arb->pclk_khz;
65 mclk_freq = arb->mclk_khz;
66 nvclk_freq = arb->nvclk_khz;
67 pagemiss = arb->mem_page_miss;
68 cas = arb->mem_latency;
69 width = arb->memory_width >> 6;
70 video_enable = arb->enable_video;
71 bpp = arb->pix_bpp;
72 mp_enable = arb->enable_mp;
73 clwm = 0;
74 vlwm = 0;
75 cbs = 128;
76 pclks = 2;
77 nvclks = 2;
78 nvclks += 2;
79 nvclks += 1;
80 mclks = 5;
81 mclks += 3;
82 mclks += 1;
83 mclks += cas;
84 mclks += 1;
85 mclks += 1;
86 mclks += 1;
87 mclks += 1;
88 mclk_extra = 3;
89 nvclks += 2;
90 nvclks += 1;
91 nvclks += 1;
92 nvclks += 1;
93 if (mp_enable)
94 mclks += 4;
95 nvclks += 0;
96 pclks += 0;
97 found = 0;
98 vbs = 0;
99 while (found != 1) {
100 fifo->valid = true;
101 found = 1;
102 mclk_loop = mclks + mclk_extra;
103 us_m = mclk_loop * 1000 * 1000 / mclk_freq;
104 us_n = nvclks * 1000 * 1000 / nvclk_freq;
105 us_p = nvclks * 1000 * 1000 / pclk_freq;
106 if (video_enable) {
107 video_drain_rate = pclk_freq * 2;
108 crtc_drain_rate = pclk_freq * bpp / 8;
109 vpagemiss = 2;
110 vpagemiss += 1;
111 crtpagemiss = 2;
112 vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
113 if (nvclk_freq * 2 > mclk_freq * width)
114 video_fill_us = cbs * 1000 * 1000 / 16 / nvclk_freq;
115 else
116 video_fill_us = cbs * 1000 * 1000 / (8 * width) / mclk_freq;
117 us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
118 vlwm = us_video * video_drain_rate / (1000 * 1000);
119 vlwm++;
120 vbs = 128;
121 if (vlwm > 128)
122 vbs = 64;
123 if (vlwm > (256 - 64))
124 vbs = 32;
125 if (nvclk_freq * 2 > mclk_freq * width)
126 video_fill_us = vbs * 1000 * 1000 / 16 / nvclk_freq;
127 else
128 video_fill_us = vbs * 1000 * 1000 / (8 * width) / mclk_freq;
129 cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
130 us_crt = us_video + video_fill_us + cpm_us + us_m + us_n + us_p;
131 clwm = us_crt * crtc_drain_rate / (1000 * 1000);
132 clwm++;
133 } else {
134 crtc_drain_rate = pclk_freq * bpp / 8;
135 crtpagemiss = 2;
136 crtpagemiss += 1;
137 cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
138 us_crt = cpm_us + us_m + us_n + us_p;
139 clwm = us_crt * crtc_drain_rate / (1000 * 1000);
140 clwm++;
141 }
142 m1 = clwm + cbs - 512;
143 p1 = m1 * pclk_freq / mclk_freq;
144 p1 = p1 * bpp / 8;
145 if ((p1 < m1 && m1 > 0) ||
146 (video_enable && (clwm > 511 || vlwm > 255)) ||
147 (!video_enable && clwm > 519)) {
148 fifo->valid = false;
149 found = !mclk_extra;
150 mclk_extra--;
151 }
152 if (clwm < 384)
153 clwm = 384;
154 if (vlwm < 128)
155 vlwm = 128;
156 fifo->graphics_lwm = clwm;
157 fifo->graphics_burst_size = 128;
158 fifo->video_lwm = vlwm + 15;
159 fifo->video_burst_size = vbs;
160 }
161}
162
163static void nv10CalcArbitration(struct nv_fifo_info *fifo, struct nv_sim_state *arb)
164{
165 int pagemiss, width, video_enable, bpp;
166 int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
167 int nvclk_fill;
168 int found, mclk_extra, mclk_loop, cbs, m1;
169 int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
170 int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
171 int vus_m;
172 int vpm_us, us_video, cpm_us, us_crt, clwm;
173 int clwm_rnd_down;
174 int m2us, us_pipe_min, p1clk, p2;
175 int min_mclk_extra;
176 int us_min_mclk_extra;
177
178 pclk_freq = arb->pclk_khz; /* freq in KHz */
179 mclk_freq = arb->mclk_khz;
180 nvclk_freq = arb->nvclk_khz;
181 pagemiss = arb->mem_page_miss;
182 width = arb->memory_width / 64;
183 video_enable = arb->enable_video;
184 bpp = arb->pix_bpp;
185 mp_enable = arb->enable_mp;
186 clwm = 0;
187 cbs = 512;
188 pclks = 4; /* lwm detect. */
189 nvclks = 3; /* lwm -> sync. */
190 nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
191 mclks = 1; /* 2 edge sync. may be very close to edge so just put one. */
192 mclks += 1; /* arb_hp_req */
193 mclks += 5; /* ap_hp_req tiling pipeline */
194 mclks += 2; /* tc_req latency fifo */
195 mclks += 2; /* fb_cas_n_ memory request to fbio block */
196 mclks += 7; /* sm_d_rdv data returned from fbio block */
197
198 /* fb.rd.d.Put_gc need to accumulate 256 bits for read */
199 if (arb->memory_type == 0) {
200 if (arb->memory_width == 64) /* 64 bit bus */
201 mclks += 4;
202 else
203 mclks += 2;
204 } else if (arb->memory_width == 64) /* 64 bit bus */
205 mclks += 2;
206 else
207 mclks += 1;
208
209 if (!video_enable && arb->memory_width == 128) {
210 mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
211 min_mclk_extra = 17;
212 } else {
213 mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
214 /* mclk_extra = 4; *//* Margin of error */
215 min_mclk_extra = 18;
216 }
217
218 nvclks += 1; /* 2 edge sync. may be very close to edge so just put one. */
219 nvclks += 1; /* fbi_d_rdv_n */
220 nvclks += 1; /* Fbi_d_rdata */
221 nvclks += 1; /* crtfifo load */
222
223 if (mp_enable)
224 mclks += 4; /* Mp can get in with a burst of 8. */
225 /* Extra clocks determined by heuristics */
226
227 nvclks += 0;
228 pclks += 0;
229 found = 0;
230 while (found != 1) {
231 fifo->valid = true;
232 found = 1;
233 mclk_loop = mclks + mclk_extra;
234 us_m = mclk_loop * 1000 * 1000 / mclk_freq; /* Mclk latency in us */
235 us_m_min = mclks * 1000 * 1000 / mclk_freq; /* Minimum Mclk latency in us */
236 us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
237 us_n = nvclks * 1000 * 1000 / nvclk_freq; /* nvclk latency in us */
238 us_p = pclks * 1000 * 1000 / pclk_freq; /* nvclk latency in us */
239 us_pipe_min = us_m_min + us_n + us_p;
240
241 vus_m = mclk_loop * 1000 * 1000 / mclk_freq; /* Mclk latency in us */
242
243 if (video_enable) {
244 crtc_drain_rate = pclk_freq * bpp / 8; /* MB/s */
245
246 vpagemiss = 1; /* self generating page miss */
247 vpagemiss += 1; /* One higher priority before */
248
249 crtpagemiss = 2; /* self generating page miss */
250 if (mp_enable)
251 crtpagemiss += 1; /* if MA0 conflict */
252
253 vpm_us = vpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
254
255 us_video = vpm_us + vus_m; /* Video has separate read return path */
256
257 cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
258 us_crt = us_video /* Wait for video */
259 + cpm_us /* CRT Page miss */
260 + us_m + us_n + us_p; /* other latency */
261
262 clwm = us_crt * crtc_drain_rate / (1000 * 1000);
263 clwm++; /* fixed point <= float_point - 1. Fixes that */
264 } else {
265 crtc_drain_rate = pclk_freq * bpp / 8; /* bpp * pclk/8 */
266
267 crtpagemiss = 1; /* self generating page miss */
268 crtpagemiss += 1; /* MA0 page miss */
269 if (mp_enable)
270 crtpagemiss += 1; /* if MA0 conflict */
271 cpm_us = crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
272 us_crt = cpm_us + us_m + us_n + us_p;
273 clwm = us_crt * crtc_drain_rate / (1000 * 1000);
274 clwm++; /* fixed point <= float_point - 1. Fixes that */
275
276 /* Finally, a heuristic check when width == 64 bits */
277 if (width == 1) {
278 nvclk_fill = nvclk_freq * 8;
279 if (crtc_drain_rate * 100 >= nvclk_fill * 102)
280 clwm = 0xfff; /* Large number to fail */
281 else if (crtc_drain_rate * 100 >= nvclk_fill * 98) {
282 clwm = 1024;
283 cbs = 512;
284 }
285 }
286 }
287
288 /*
289 * Overfill check:
290 */
291
292 clwm_rnd_down = (clwm / 8) * 8;
293 if (clwm_rnd_down < clwm)
294 clwm += 8;
295
296 m1 = clwm + cbs - 1024; /* Amount of overfill */
297 m2us = us_pipe_min + us_min_mclk_extra;
298
299 /* pclk cycles to drain */
300 p1clk = m2us * pclk_freq / (1000 * 1000);
301 p2 = p1clk * bpp / 8; /* bytes drained. */
302
303 if (p2 < m1 && m1 > 0) {
304 fifo->valid = false;
305 found = 0;
306 if (min_mclk_extra == 0) {
307 if (cbs <= 32)
308 found = 1; /* Can't adjust anymore! */
309 else
310 cbs = cbs / 2; /* reduce the burst size */
311 } else
312 min_mclk_extra--;
313 } else if (clwm > 1023) { /* Have some margin */
314 fifo->valid = false;
315 found = 0;
316 if (min_mclk_extra == 0)
317 found = 1; /* Can't adjust anymore! */
318 else
319 min_mclk_extra--;
320 }
321
322 if (clwm < (1024 - cbs + 8))
323 clwm = 1024 - cbs + 8;
324 /* printf("CRT LWM: prog: 0x%x, bs: 256\n", clwm); */
325 fifo->graphics_lwm = clwm;
326 fifo->graphics_burst_size = cbs;
327
328 fifo->video_lwm = 1024;
329 fifo->video_burst_size = 512;
330 }
331}
332
333void nv4_10UpdateArbitrationSettings(ScrnInfoPtr pScrn, int VClk, int bpp, int *burst, int *lwm)
334{
335 NVPtr pNv = NVPTR(pScrn);
336 struct nv_fifo_info fifo_data;
337 struct nv_sim_state sim_data;
338 int MClk = nouveau_hw_get_clock(pScrn, MPLL);
339 int NVClk = nouveau_hw_get_clock(pScrn, NVPLL);
340 uint32_t cfg1 = nvReadFB(pNv, NV_PFB_CFG1);
341
342 sim_data.pclk_khz = VClk;
343 sim_data.mclk_khz = MClk;
344 sim_data.nvclk_khz = NVClk;
345 sim_data.pix_bpp = bpp;
346 sim_data.enable_mp = false;
347 if ((pNv->Chipset & 0xffff) == CHIPSET_NFORCE ||
348 (pNv->Chipset & 0xffff) == CHIPSET_NFORCE2) {
349 struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 1);
350 uint32_t data;
351
352 pci_device_cfg_read_u32(dev, &data, 0x7c);
353
354 sim_data.enable_video = false;
355 sim_data.memory_type = (data >> 12) & 1;
356 sim_data.memory_width = 64;
357 sim_data.mem_latency = 3;
358 sim_data.mem_page_miss = 10;
359 } else {
360 sim_data.enable_video = (pNv->Architecture != NV_ARCH_04);
361 sim_data.memory_type = nvReadFB(pNv, NV_PFB_CFG0) & 0x1;
362 sim_data.memory_width = (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
363 sim_data.mem_latency = cfg1 & 0xf;
364 sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
365 }
366
367 if (pNv->Architecture == NV_ARCH_04)
368 nv4CalcArbitration(&fifo_data, &sim_data);
369 else
370 nv10CalcArbitration(&fifo_data, &sim_data);
371
372 if (fifo_data.valid) {
373 int b = fifo_data.graphics_burst_size >> 4;
374 *burst = 0;
375 while (b >>= 1)
376 (*burst)++;
377 *lwm = fifo_data.graphics_lwm >> 3;
378 }
379}
380
381void nv30UpdateArbitrationSettings(int *burst, int *lwm)
382{
383 unsigned int fifo_size, burst_size, graphics_lwm;
384
385 fifo_size = 2048;
386 burst_size = 512;
387 graphics_lwm = fifo_size - burst_size;
388
389 *burst = 0;
390 burst_size >>= 5;
391 while (burst_size >>= 1)
392 (*burst)++;
393 *lwm = graphics_lwm >> 3;
394}
395
396void
397nouveau_calc_arb(ScrnInfoPtr pScrn, int vclk, int bpp, int *burst, int *lwm)
398{
399 NVPtr pNv = NVPTR(pScrn);
400
401 if (pNv->Architecture < NV_ARCH_30)
402 nv4_10UpdateArbitrationSettings(pScrn, vclk, bpp, burst, lwm);
403 else if ((pNv->Chipset & 0xfff0) == CHIPSET_C51 ||
404 (pNv->Chipset & 0xfff0) == CHIPSET_C512) {
405 *burst = 128;
406 *lwm = 0x0480;
407 } else
408 nv30UpdateArbitrationSettings(burst, lwm);
409}
410
411static int getMNP_single(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
412 struct nouveau_pll_vals *bestpv)
413{
414 /* Find M, N and P for a single stage PLL
415 *
416 * Note that some bioses (NV3x) have lookup tables of precomputed MNP
417 * values, but we're too lazy to use those atm
418 *
419 * "clk" parameter in kHz
420 * returns calculated clock
421 */
422
423 int cv = NVPTR(pScrn)->vbios->chip_version;
424 int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq;
425 int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m;
426 int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n;
427 int minU = pll_lim->vco1.min_inputfreq, maxU = pll_lim->vco1.max_inputfreq;
428 int maxlog2P = pll_lim->max_usable_log2p;
429 int crystal = pll_lim->refclk;
430 int M, N, log2P, P;
431 int clkP, calcclk;
432 int delta, bestdelta = INT_MAX;
433 int bestclk = 0;
434
435 /* this division verified for nv20, nv18, nv28 (Haiku), and nv34 */
436 /* possibly correlated with introduction of 27MHz crystal */
437 if (cv < 0x17 || cv == 0x1a || cv == 0x20) {
438 if (clk > 250000)
439 maxM = 6;
440 if (clk > 340000)
441 maxM = 2;
442 } else if (cv < 0x40) {
443 if (clk > 150000)
444 maxM = 6;
445 if (clk > 200000)
446 maxM = 4;
447 if (clk > 340000)
448 maxM = 2;
449 }
450
451 if ((clk << maxlog2P) < minvco) {
452 minvco = clk << maxlog2P;
453 maxvco = minvco * 2;
454 }
455 if (clk + clk/200 > maxvco) /* +0.5% */
456 maxvco = clk + clk/200;
457
458 /* NV34 goes maxlog2P->0, NV20 goes 0->maxlog2P */
459 for (log2P = 0; log2P <= maxlog2P; log2P++) {
460 P = 1 << log2P;
461 clkP = clk * P;
462
463 if (clkP < minvco)
464 continue;
465 if (clkP > maxvco)
466 return bestclk;
467
468 for (M = minM; M <= maxM; M++) {
469 if (crystal/M < minU)
470 return bestclk;
471 if (crystal/M > maxU)
472 continue;
473
474 /* add crystal/2 to round better */
475 N = (clkP * M + crystal/2) / crystal;
476
477 if (N < minN)
478 continue;
479 if (N > maxN)
480 break;
481
482 /* more rounding additions */
483 calcclk = ((N * crystal + P/2) / P + M/2) / M;
484 delta = abs(calcclk - clk);
485 /* we do an exhaustive search rather than terminating
486 * on an optimality condition...
487 */
488 if (delta < bestdelta) {
489 bestdelta = delta;
490 bestclk = calcclk;
491 bestpv->N1 = N;
492 bestpv->M1 = M;
493 bestpv->log2P = log2P;
494 if (delta == 0) /* except this one */
495 return bestclk;
496 }
497 }
498 }
499
500 return bestclk;
501}
502
503static int getMNP_double(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
504 struct nouveau_pll_vals *bestpv)
505{
506 /* Find M, N and P for a two stage PLL
507 *
508 * Note that some bioses (NV30+) have lookup tables of precomputed MNP
509 * values, but we're too lazy to use those atm
510 *
511 * "clk" parameter in kHz
512 * returns calculated clock
513 */
514
515 int chip_version = NVPTR(pScrn)->vbios->chip_version;
516 int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
517 int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq;
518 int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
519 int maxU1 = pll_lim->vco1.max_inputfreq, maxU2 = pll_lim->vco2.max_inputfreq;
520 int minM1 = pll_lim->vco1.min_m, maxM1 = pll_lim->vco1.max_m;
521 int minN1 = pll_lim->vco1.min_n, maxN1 = pll_lim->vco1.max_n;
522 int minM2 = pll_lim->vco2.min_m, maxM2 = pll_lim->vco2.max_m;
523 int minN2 = pll_lim->vco2.min_n, maxN2 = pll_lim->vco2.max_n;
524 int maxlog2P = pll_lim->max_usable_log2p;
525 int crystal = pll_lim->refclk;
526 bool fixedgain2 = (minM2 == maxM2 && minN2 == maxN2);
527 int M1, N1, M2, N2, log2P;
528 int clkP, calcclk1, calcclk2, calcclkout;
529 int delta, bestdelta = INT_MAX;
530 int bestclk = 0;
531
532 int vco2 = (maxvco2 - maxvco2/200) / 2;
533 for (log2P = 0; clk && log2P < maxlog2P && clk <= (vco2 >> log2P); log2P++)
534 ;
535 clkP = clk << log2P;
536
537 if (maxvco2 < clk + clk/200) /* +0.5% */
538 maxvco2 = clk + clk/200;
539
540 for (M1 = minM1; M1 <= maxM1; M1++) {
541 if (crystal/M1 < minU1)
542 return bestclk;
543 if (crystal/M1 > maxU1)
544 continue;
545
546 for (N1 = minN1; N1 <= maxN1; N1++) {
547 calcclk1 = crystal * N1 / M1;
548 if (calcclk1 < minvco1)
549 continue;
550 if (calcclk1 > maxvco1)
551 break;
552
553 for (M2 = minM2; M2 <= maxM2; M2++) {
554 if (calcclk1/M2 < minU2)
555 break;
556 if (calcclk1/M2 > maxU2)
557 continue;
558
559 /* add calcclk1/2 to round better */
560 N2 = (clkP * M2 + calcclk1/2) / calcclk1;
561 if (N2 < minN2)
562 continue;
563 if (N2 > maxN2)
564 break;
565
566 if (!fixedgain2) {
567 if (chip_version < 0x60)
568 if (N2/M2 < 4 || N2/M2 > 10)
569 continue;
570
571 calcclk2 = calcclk1 * N2 / M2;
572 if (calcclk2 < minvco2)
573 break;
574 if (calcclk2 > maxvco2)
575 continue;
576 } else
577 calcclk2 = calcclk1;
578
579 calcclkout = calcclk2 >> log2P;
580 delta = abs(calcclkout - clk);
581 /* we do an exhaustive search rather than terminating
582 * on an optimality condition...
583 */
584 if (delta < bestdelta) {
585 bestdelta = delta;
586 bestclk = calcclkout;
587 bestpv->N1 = N1;
588 bestpv->M1 = M1;
589 bestpv->N2 = N2;
590 bestpv->M2 = M2;
591 bestpv->log2P = log2P;
592 if (delta == 0) /* except this one */
593 return bestclk;
594 }
595 }
596 }
597 }
598
599 return bestclk;
600}
601
602int nouveau_calc_pll_mnp(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
603 struct nouveau_pll_vals *pv)
604{
605 int outclk;
606
607 if (!pll_lim->vco2.maxfreq)
608 outclk = getMNP_single(pScrn, pll_lim, clk, pv);
609 else
610 outclk = getMNP_double(pScrn, pll_lim, clk, pv);
611
612 if (!outclk)
613 NV_ERROR(pScrn,
614 "Could not find a compatible set of PLL values\n");
615
616 return outclk;
617}
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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_CONNECTOR_H_
24#define __NOUVEAU_CONNECTOR_H_
25
26#include "nv_include.h"
27#include "nouveau_modeset.h"
28#include "nouveau_crtc.h"
29#include "nouveau_output.h"
30
31/* I have yet to find specific information on connectors, so it's all derived from outputs. */
32typedef enum {
33 CONNECTOR_NONE = 4,
34 CONNECTOR_VGA = 0,
35 CONNECTOR_DVI = 1,
36 CONNECTOR_TV = 2,
37 CONNECTOR_PANEL = 3
38} NVConnectorType;
39
40#define MAX_OUTPUTS_PER_CONNECTOR 2
41
42typedef struct nouveauConnector {
43 ScrnInfoPtr scrn;
44 int index;
45
46 char *name;
47 Bool active;
48
49 NVConnectorType type;
50
51 I2CBusPtr pDDCBus;
52 int i2c_index;
53
54 /* For load detect amongst other things. */
55 nouveauOutputPtr outputs[MAX_OUTPUTS_PER_CONNECTOR];
56 int connected_output;
57
58 Bool hotplug_detected; /* better name? */
59 /* Function pointers. */
60 Bool (*HotplugDetect) (nouveauConnectorPtr connector);
61 xf86MonPtr (*DDCDetect) (nouveauConnectorPtr connector);
62 DisplayModePtr (*GetDDCModes) (nouveauConnectorPtr connector);
63} nouveauConnectorRec;
64
65#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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_CRTC_H_
24#define __NOUVEAU_CRTC_H_
25
26#include "nv_include.h"
27#include "nouveau_modeset.h"
28
29typedef struct nouveauCrtc {
30 ScrnInfoPtr scrn;
31
32 char *name;
33 uint8_t index;
34 Bool active;
35 Bool blanked;
36
37 /* Scanout area. */
38 struct nouveau_bo * front_buffer;
39 uint32_t fb_pitch;
40 uint32_t x; /* relative to the frontbuffer */
41 uint32_t y;
42
43 /* Gamma */
44 struct nouveau_bo *lut;
45 struct {
46 uint16_t red;
47 uint16_t green;
48 uint16_t blue;
49 uint16_t unused;
50 } lut_values[256];
51 bool lut_values_valid;
52
53 /* Options and some state. */
54 Bool modeset_lock;
55 Bool dithering;
56 Bool cursor_visible;
57 Bool use_native_mode;
58 int scale_mode;
59 int pixel_clock;
60
61 /* Mode info. */
62 DisplayModePtr cur_mode;
63 DisplayModePtr native_mode;
64 DisplayModePtr mode_list;
65
66 /* Function pointers. */
67 Bool (*ModeValid) (nouveauCrtcPtr crtc, DisplayModePtr mode);
68 void (*ModeSet) (nouveauCrtcPtr crtc, DisplayModePtr mode);
69 void (*SetPixelClock) (nouveauCrtcPtr crtc, int clock);
70 void (*SetClockMode) (nouveauCrtcPtr crtc, int clock); /* maybe another name? */
71
72 void (*SetFB) (nouveauCrtcPtr crtc, struct nouveau_bo * buffer);
73 void (*SetFBOffset) (nouveauCrtcPtr crtc, uint32_t x, uint32_t y);
74
75 void (*Blank) (nouveauCrtcPtr crtc, Bool blanked);
76 void (*SetDither) (nouveauCrtcPtr crtc);
77
78 void (*SetScaleMode) (nouveauCrtcPtr crtc, int scale);
79
80 void (*ShowCursor) (nouveauCrtcPtr crtc, Bool forced_lock);
81 void (*HideCursor) (nouveauCrtcPtr crtc, Bool forced_lock);
82 void (*SetCursorPosition) (nouveauCrtcPtr crtc, int x, int y);
83 void (*LoadCursor) (nouveauCrtcPtr crtc, Bool argb, uint32_t *src);
84
85 void (*GammaSet) (nouveauCrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size);
86
87 void (*Save) (nouveauCrtcPtr crtc);
88 void (*Load) (nouveauCrtcPtr crtc);
89} nouveauCrtcRec;
90
91#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)
724 724
725 if (!exaDriverInit(pScreen, exa)) 725 if (!exaDriverInit(pScreen, exa))
726 return FALSE; 726 return FALSE;
727 else
728 /* EXA init catches this, but only for xserver >= 1.4 */
729 if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) {
730 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n");
731 return FALSE;
732 }
733 727
734 pNv->EXADriverPtr = exa; 728 pNv->EXADriverPtr = exa;
735 return TRUE; 729 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 @@
1/*
2 * Copyright 2006 Dave Airlie
3 * Copyright 2007 Maarten Maathuis
4 * Copyright 2007-2009 Stuart Bennett
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "nv_include.h"
26
27/*
28 * misc hw access wrappers/control functions
29 */
30
31void NVWriteVgaSeq(NVPtr pNv, int head, uint8_t index, uint8_t value)
32{
33 NVWritePRMVIO(pNv, head, NV_PRMVIO_SRX, index);
34 NVWritePRMVIO(pNv, head, NV_PRMVIO_SR, value);
35}
36
37uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index)
38{
39 NVWritePRMVIO(pNv, head, NV_PRMVIO_SRX, index);
40 return NVReadPRMVIO(pNv, head, NV_PRMVIO_SR);
41}
42
43void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value)
44{
45 NVWritePRMVIO(pNv, head, NV_PRMVIO_GRX, index);
46 NVWritePRMVIO(pNv, head, NV_PRMVIO_GX, value);
47}
48
49uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index)
50{
51 NVWritePRMVIO(pNv, head, NV_PRMVIO_GRX, index);
52 return NVReadPRMVIO(pNv, head, NV_PRMVIO_GX);
53}
54
55/* CR44 takes values 0 (head A), 3 (head B) and 4 (heads tied)
56 * it affects only the 8 bit vga io regs, which we access using mmio at
57 * 0xc{0,2}3c*, 0x60{1,3}3*, and 0x68{1,3}3d*
58 * in general, the set value of cr44 does not matter: reg access works as
59 * expected and values can be set for the appropriate head by using a 0x2000
60 * offset as required
61 * however:
62 * a) pre nv40, the head B range of PRMVIO regs at 0xc23c* was not exposed and
63 * cr44 must be set to 0 or 3 for accessing values on the correct head
64 * through the common 0xc03c* addresses
65 * b) in tied mode (4) head B is programmed to the values set on head A, and
66 * access using the head B addresses can have strange results, ergo we leave
67 * tied mode in init once we know to what cr44 should be restored on exit
68 *
69 * the owner parameter is slightly abused:
70 * 0 and 1 are treated as head values and so the set value is (owner * 3)
71 * other values are treated as literal values to set
72 */
73void NVSetOwner(NVPtr pNv, int owner)
74{
75 if (owner == 1)
76 owner *= 3;
77 /* CR44 is always changed on CRTC0 */
78 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_44, owner);
79 if (pNv->NVArch == 0x11) { /* set me harder */
80 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_2E, owner);
81 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_2E, owner);
82 }
83}
84
85/*
86 * on nv11 this may not be reliable
87 * returned value is suitable for directly programming back into cr44
88 */
89int nouveau_hw_get_current_head(ScrnInfoPtr pScrn)
90{
91 NVPtr pNv = NVPTR(pScrn);
92 int cr44;
93
94 if (pNv->NVArch != 0x11)
95 return NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44);
96
97 /* reading CR44 is broken on nv11, so we attempt to infer it */
98 if (nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28)) /* heads tied, restore both */
99 cr44 = 0x4;
100 else {
101 bool slaved_on_A, tvA = false;
102 bool slaved_on_B, tvB = false;
103 bool waslocked;
104
105 waslocked = NVLockVgaCrtcs(pNv, false);
106
107 slaved_on_A = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
108 if (slaved_on_A)
109 tvA = !(NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_LCD__INDEX) & MASK(NV_CIO_CRE_LCD_LCD_SELECT));
110
111 slaved_on_B = NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_PIXEL_INDEX) & 0x80;
112 if (slaved_on_B)
113 tvB = !(NVReadVgaCrtc(pNv, 1, NV_CIO_CRE_LCD__INDEX) & MASK(NV_CIO_CRE_LCD_LCD_SELECT));
114
115 if (waslocked)
116 NVLockVgaCrtcs(pNv, true);
117
118 if (slaved_on_A && !tvA)
119 cr44 = 0x0;
120 else if (slaved_on_B && !tvB)
121 cr44 = 0x3;
122 else if (slaved_on_A)
123 cr44 = 0x0;
124 else if (slaved_on_B)
125 cr44 = 0x3;
126 else
127 cr44 = 0x0;
128 }
129
130 return cr44;
131}
132
133void NVBlankScreen(NVPtr pNv, int head, bool blank)
134{
135 unsigned char seq1;
136
137 if (pNv->twoHeads)
138 NVSetOwner(pNv, head);
139
140 seq1 = NVReadVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX);
141
142 NVVgaSeqReset(pNv, head, true);
143 if (blank)
144 NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
145 else
146 NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20);
147 NVVgaSeqReset(pNv, head, false);
148}
149
150/*
151 * PLL setting
152 */
153
154static int powerctrl_1_shift(int chip_version, int reg)
155{
156 int shift = -4;
157
158 if (chip_version < 0x17 || chip_version == 0x1a || chip_version == 0x20)
159 return shift;
160
161 switch (reg) {
162 case NV_RAMDAC_VPLL2:
163 shift += 4;
164 case NV_PRAMDAC_VPLL_COEFF:
165 shift += 4;
166 case NV_PRAMDAC_MPLL_COEFF:
167 shift += 4;
168 case NV_PRAMDAC_NVPLL_COEFF:
169 shift += 4;
170 }
171
172 /*
173 * the shift for vpll regs is only used for nv3x chips with a single
174 * stage pll
175 */
176 if (shift > 4 && (chip_version < 0x32 || chip_version == 0x35 ||
177 chip_version == 0x36 || chip_version >= 0x40))
178 shift = -4;
179
180 return shift;
181}
182
183static void setPLL_single(ScrnInfoPtr pScrn, uint32_t reg,
184 struct nouveau_pll_vals *pv)
185{
186 NVPtr pNv = NVPTR(pScrn);
187 int chip_version = pNv->vbios->chip_version;
188 uint32_t oldpll = NVReadRAMDAC(pNv, 0, reg);
189 int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff;
190 uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1;
191 uint32_t saved_powerctrl_1 = 0;
192 int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg);
193
194 if (oldpll == pll)
195 return; /* already set */
196
197 if (shift_powerctrl_1 >= 0) {
198 saved_powerctrl_1 = nvReadMC(pNv, NV_PBUS_POWERCTRL_1);
199 nvWriteMC(pNv, NV_PBUS_POWERCTRL_1,
200 (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) |
201 1 << shift_powerctrl_1);
202 }
203
204 if (oldM && pv->M1 && (oldN / oldM < pv->N1 / pv->M1))
205 /* upclock -- write new post divider first */
206 NVWriteRAMDAC(pNv, 0, reg, pv->log2P << 16 | (oldpll & 0xffff));
207 else
208 /* downclock -- write new NM first */
209 NVWriteRAMDAC(pNv, 0, reg, (oldpll & 0xffff0000) | pv->NM1);
210
211 if (chip_version < 0x17 && chip_version != 0x11)
212 /* wait a bit on older chips */
213 usleep(64000);
214 NVReadRAMDAC(pNv, 0, reg);
215
216 /* then write the other half as well */
217 NVWriteRAMDAC(pNv, 0, reg, pll);
218
219 if (shift_powerctrl_1 >= 0)
220 nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, saved_powerctrl_1);
221}
222
223static uint32_t new_ramdac580(uint32_t reg1, bool ss, uint32_t ramdac580)
224{
225 bool head_a = (reg1 == NV_PRAMDAC_VPLL_COEFF);
226
227 if (ss) /* single stage pll mode */
228 ramdac580 |= head_a ? NV_RAMDAC_580_VPLL1_ACTIVE :
229 NV_RAMDAC_580_VPLL2_ACTIVE;
230 else
231 ramdac580 &= head_a ? ~NV_RAMDAC_580_VPLL1_ACTIVE :
232 ~NV_RAMDAC_580_VPLL2_ACTIVE;
233
234 return ramdac580;
235}
236
237static void setPLL_double_highregs(ScrnInfoPtr pScrn, uint32_t reg1,
238 struct nouveau_pll_vals *pv)
239{
240 NVPtr pNv = NVPTR(pScrn);
241 int chip_version = pNv->vbios->chip_version;
242 bool nv3035 = chip_version == 0x30 || chip_version == 0x35;
243 uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70);
244 uint32_t oldpll1 = NVReadRAMDAC(pNv, 0, reg1);
245 uint32_t oldpll2 = !nv3035 ? NVReadRAMDAC(pNv, 0, reg2) : 0;
246 uint32_t pll1 = (oldpll1 & 0xfff80000) | pv->log2P << 16 | pv->NM1;
247 uint32_t pll2 = (oldpll2 & 0x7fff0000) | 1 << 31 | pv->NM2;
248 uint32_t oldramdac580 = 0, ramdac580 = 0;
249 bool single_stage = !pv->NM2 || pv->N2 == pv->M2; /* nv41+ only */
250 uint32_t saved_powerctrl_1 = 0, savedc040 = 0;
251 int shift_powerctrl_1 = powerctrl_1_shift(chip_version, reg1);
252
253 /* model specific additions to generic pll1 and pll2 set up above */
254 if (nv3035) {
255 pll1 = (pll1 & 0xfcc7ffff) | (pv->N2 & 0x18) << 21 |
256 (pv->N2 & 0x7) << 19 | 8 << 4 | (pv->M2 & 7) << 4;
257 pll2 = 0;
258 }
259 if (chip_version > 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { /* !nv40 */
260 oldramdac580 = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_580);
261 ramdac580 = new_ramdac580(reg1, single_stage, oldramdac580);
262 if (oldramdac580 != ramdac580)
263 oldpll1 = ~0; /* force mismatch */
264 if (single_stage)
265 /* magic value used by nvidia in single stage mode */
266 pll2 |= 0x011f;
267 }
268 if (chip_version > 0x70)
269 /* magic bits set by the blob (but not the bios) on g71-73 */
270 pll1 = (pll1 & 0x7fffffff) | (single_stage ? 0x4 : 0xc) << 28;
271
272 if (oldpll1 == pll1 && oldpll2 == pll2)
273 return; /* already set */
274
275 if (shift_powerctrl_1 >= 0) {
276 saved_powerctrl_1 = nvReadMC(pNv, NV_PBUS_POWERCTRL_1);
277 nvWriteMC(pNv, NV_PBUS_POWERCTRL_1,
278 (saved_powerctrl_1 & ~(0xf << shift_powerctrl_1)) |
279 1 << shift_powerctrl_1);
280 }
281
282 if (chip_version >= 0x40) {
283 int shift_c040 = 14;
284
285 switch (reg1) {
286 case NV_PRAMDAC_MPLL_COEFF:
287 shift_c040 += 2;
288 case NV_PRAMDAC_NVPLL_COEFF:
289 shift_c040 += 2;
290 case NV_RAMDAC_VPLL2:
291 shift_c040 += 2;
292 case NV_PRAMDAC_VPLL_COEFF:
293 shift_c040 += 2;
294 }
295
296 savedc040 = nvReadMC(pNv, 0xc040);
297 if (shift_c040 != 14)
298 nvWriteMC(pNv, 0xc040, savedc040 & ~(3 << shift_c040));
299 }
300
301 if (oldramdac580 != ramdac580)
302 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_580, ramdac580);
303
304 if (!nv3035)
305 NVWriteRAMDAC(pNv, 0, reg2, pll2);
306 NVWriteRAMDAC(pNv, 0, reg1, pll1);
307
308 if (shift_powerctrl_1 >= 0)
309 nvWriteMC(pNv, NV_PBUS_POWERCTRL_1, saved_powerctrl_1);
310 if (chip_version >= 0x40)
311 nvWriteMC(pNv, 0xc040, savedc040);
312}
313
314static void setPLL_double_lowregs(ScrnInfoPtr pScrn, uint32_t NMNMreg,
315 struct nouveau_pll_vals *pv)
316{
317 /* When setting PLLs, there is a merry game of disabling and enabling
318 * various bits of hardware during the process. This function is a
319 * synthesis of six nv4x traces, nearly each card doing a subtly
320 * different thing. With luck all the necessary bits for each card are
321 * combined herein. Without luck it deviates from each card's formula
322 * so as to not work on any :)
323 */
324
325 NVPtr pNv = NVPTR(pScrn);
326 uint32_t Preg = NMNMreg - 4;
327 bool mpll = Preg == 0x4020;
328 uint32_t oldPval = nvReadMC(pNv, Preg);
329 uint32_t NMNM = pv->NM2 << 16 | pv->NM1;
330 uint32_t Pval = (oldPval & (mpll ? ~(0x11 << 16) : ~(1 << 16))) |
331 0xc << 28 | pv->log2P << 16;
332 uint32_t saved4600 = 0;
333 /* some cards have different maskc040s */
334 uint32_t maskc040 = ~(3 << 14), savedc040;
335 bool single_stage = !pv->NM2 || pv->N2 == pv->M2;
336
337 if (nvReadMC(pNv, NMNMreg) == NMNM && (oldPval & 0xc0070000) == Pval)
338 return;
339
340 if (Preg == 0x4000)
341 maskc040 = ~0x333;
342 if (Preg == 0x4058)
343 maskc040 = ~(0xc << 24);
344
345 if (mpll) {
346 struct pll_lims pll_lim;
347 uint8_t Pval2;
348
349 if (get_pll_limits(pScrn, Preg, &pll_lim))
350 return;
351
352 Pval2 = pv->log2P + pll_lim.log2p_bias;
353 if (Pval2 > pll_lim.max_log2p)
354 Pval2 = pll_lim.max_log2p;
355 Pval |= 1 << 28 | Pval2 << 20;
356
357 saved4600 = nvReadMC(pNv, 0x4600);
358 nvWriteMC(pNv, 0x4600, saved4600 | 8 << 28);
359 }
360 if (single_stage)
361 Pval |= mpll ? 1 << 12 : 1 << 8;
362
363 nvWriteMC(pNv, Preg, oldPval | 1 << 28);
364 nvWriteMC(pNv, Preg, Pval & ~(4 << 28));
365 if (mpll) {
366 Pval |= 8 << 20;
367 nvWriteMC(pNv, 0x4020, Pval & ~(0xc << 28));
368 nvWriteMC(pNv, 0x4038, Pval & ~(0xc << 28));
369 }
370
371 savedc040 = nvReadMC(pNv, 0xc040);
372 nvWriteMC(pNv, 0xc040, savedc040 & maskc040);
373
374 nvWriteMC(pNv, NMNMreg, NMNM);
375 if (NMNMreg == 0x4024)
376 nvWriteMC(pNv, 0x403c, NMNM);
377
378 nvWriteMC(pNv, Preg, Pval);
379 if (mpll) {
380 Pval &= ~(8 << 20);
381 nvWriteMC(pNv, 0x4020, Pval);
382 nvWriteMC(pNv, 0x4038, Pval);
383 nvWriteMC(pNv, 0x4600, saved4600);
384 }
385
386 nvWriteMC(pNv, 0xc040, savedc040);
387
388 if (mpll) {
389 nvWriteMC(pNv, 0x4020, Pval & ~(1 << 28));
390 nvWriteMC(pNv, 0x4038, Pval & ~(1 << 28));
391 }
392}
393
394void nouveau_hw_setpll(ScrnInfoPtr pScrn, uint32_t reg1,
395 struct nouveau_pll_vals *pv)
396{
397 int cv = NVPTR(pScrn)->vbios->chip_version;
398
399 if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
400 cv >= 0x40) {
401 if (reg1 > 0x405c)
402 setPLL_double_highregs(pScrn, reg1, pv);
403 else
404 setPLL_double_lowregs(pScrn, reg1, pv);
405 } else
406 setPLL_single(pScrn, reg1, pv);
407}
408
409/*
410 * PLL getting
411 */
412
413static void nouveau_hw_decode_pll(NVPtr pNv, uint32_t reg1,
414 uint32_t pll1, uint32_t pll2,
415 struct nouveau_pll_vals *pllvals)
416{
417 /* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */
418
419 /* log2P is & 0x7 as never more than 7, and nv30/35 only uses 3 bits */
420 pllvals->log2P = (pll1 >> 16) & 0x7;
421 pllvals->N2 = pllvals->M2 = 1;
422
423 if (reg1 <= 0x405c) {
424 pllvals->NM1 = pll2 & 0xffff;
425 /* single stage NVPLL and VPLLs use 1 << 8, MPLL uses 1 << 12 */
426 if (!(pll1 & 0x1100))
427 pllvals->NM2 = pll2 >> 16;
428 } else {
429 pllvals->NM1 = pll1 & 0xffff;
430 if (pNv->two_reg_pll && pll2 & NV31_RAMDAC_ENABLE_VCO2)
431 pllvals->NM2 = pll2 & 0xffff;
432 else if (pNv->NVArch == 0x30 || pNv->NVArch == 0x35) {
433 pllvals->M1 &= 0xf; /* only 4 bits */
434 if (pll1 & NV30_RAMDAC_ENABLE_VCO2) {
435 pllvals->M2 = (pll1 >> 4) & 0x7;
436 pllvals->N2 = ((pll1 >> 21) & 0x18) |
437 ((pll1 >> 19) & 0x7);
438 }
439 }
440 }
441}
442
443int nouveau_hw_get_pllvals(ScrnInfoPtr pScrn, enum pll_types plltype,
444 struct nouveau_pll_vals *pllvals)
445{
446 NVPtr pNv = NVPTR(pScrn);
447 const uint32_t nv04_regs[MAX_PLL_TYPES] = { NV_PRAMDAC_NVPLL_COEFF,
448 NV_PRAMDAC_MPLL_COEFF,
449 NV_PRAMDAC_VPLL_COEFF,
450 NV_RAMDAC_VPLL2 };
451 const uint32_t nv40_regs[MAX_PLL_TYPES] = { 0x4000,
452 0x4020,
453 NV_PRAMDAC_VPLL_COEFF,
454 NV_RAMDAC_VPLL2 };
455 uint32_t reg1, pll1, pll2 = 0;
456 struct pll_lims pll_lim;
457 int ret;
458
459 if (pNv->Architecture < NV_ARCH_40)
460 reg1 = nv04_regs[plltype];
461 else
462 reg1 = nv40_regs[plltype];
463
464 pll1 = nvReadMC(pNv, reg1);
465
466 if (reg1 <= 0x405c)
467 pll2 = nvReadMC(pNv, reg1 + 4);
468 else if (pNv->two_reg_pll) {
469 uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70);
470
471 pll2 = nvReadMC(pNv, reg2);
472 }
473
474 if (pNv->Architecture == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) {
475 uint32_t ramdac580 = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_580);
476
477 /* check whether vpll has been forced into single stage mode */
478 if (reg1 == NV_PRAMDAC_VPLL_COEFF) {
479 if (ramdac580 & NV_RAMDAC_580_VPLL1_ACTIVE)
480 pll2 = 0;
481 } else
482 if (ramdac580 & NV_RAMDAC_580_VPLL2_ACTIVE)
483 pll2 = 0;
484 }
485
486 nouveau_hw_decode_pll(pNv, reg1, pll1, pll2, pllvals);
487
488 if ((ret = get_pll_limits(pScrn, plltype, &pll_lim)))
489 return ret;
490
491 pllvals->refclk = pll_lim.refclk;
492
493 return 0;
494}
495
496int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pv)
497{
498 /* Avoid divide by zero if called at an inappropriate time */
499 if (!pv->M1 || !pv->M2)
500 return 0;
501
502 return (pv->N1 * pv->N2 * pv->refclk / (pv->M1 * pv->M2) >> pv->log2P);
503}
504
505int nouveau_hw_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype)
506{
507 NVPtr pNv = NVPTR(pScrn);
508 struct nouveau_pll_vals pllvals;
509
510 if (plltype == MPLL && (pNv->Chipset & 0x0ff0) == CHIPSET_NFORCE) {
511 struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 3);
512 uint32_t mpllP;
513
514 pci_device_cfg_read_u32(dev, &mpllP, 0x6c);
515 mpllP = (mpllP >> 8) & 0xf;
516
517 if (!mpllP)
518 mpllP = 4;
519 return 400000 / mpllP;
520 } else
521 if (plltype == MPLL && (pNv->Chipset & 0xff0) == CHIPSET_NFORCE2) {
522 struct pci_device *dev = pci_device_find_by_slot(0, 0, 0, 5);
523 uint32_t data;
524
525 pci_device_cfg_read_u32(dev, &data, 0x4c);
526
527 return data / 1000;
528 }
529
530 nouveau_hw_get_pllvals(pScrn, plltype, &pllvals);
531
532 return nouveau_hw_pllvals_to_clk(&pllvals);
533}
534
535static void nouveau_hw_fix_bad_vpll(ScrnInfoPtr pScrn, int head)
536{
537 /* the vpll on an unused head can come up with a random value, way
538 * beyond the pll limits. for some reason this causes the chip to
539 * lock up when reading the dac palette regs, so set a valid pll here
540 * when such a condition detected. only seen on nv11 to date
541 */
542
543 struct pll_lims pll_lim;
544 struct nouveau_pll_vals pv;
545 uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
546
547 if (get_pll_limits(pScrn, head ? VPLL2 : VPLL1, &pll_lim))
548 return;
549 nouveau_hw_get_pllvals(pScrn, head ? VPLL2 : VPLL1, &pv);
550
551 if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m &&
552 pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n &&
553 pv.log2P <= pll_lim.max_log2p)
554 return;
555
556 NV_WARN(pScrn, "VPLL %d outwith limits, attempting to fix\n", head + 1);
557
558 /* set lowest clock within static limits */
559 pv.M1 = pll_lim.vco1.max_m;
560 pv.N1 = pll_lim.vco1.min_n;
561 pv.log2P = pll_lim.max_usable_log2p;
562 nouveau_hw_setpll(pScrn, pllreg, &pv);
563}
564
565/*
566 * vga font save/restore
567 */
568
569void nouveau_hw_save_vga_fonts(ScrnInfoPtr pScrn, bool save)
570{
571 NVPtr pNv = NVPTR(pScrn);
572 bool graphicsmode;
573 uint8_t misc, gr4, gr5, gr6, seq2, seq4;
574 int i;
575
576 if (pNv->twoHeads)
577 NVSetOwner(pNv, 0);
578
579 NVSetEnablePalette(pNv, 0, true);
580 graphicsmode = NVReadVgaAttr(pNv, 0, NV_CIO_AR_MODE_INDEX) & 1;
581 NVSetEnablePalette(pNv, 0, false);
582
583 if (graphicsmode) /* graphics mode => framebuffer => no need to save */
584 return;
585
586 NV_TRACE(pScrn, "%sing VGA fonts\n", save ? "Sav" : "Restor");
587 if (pNv->twoHeads)
588 NVBlankScreen(pNv, 1, true);
589 NVBlankScreen(pNv, 0, true);
590
591 /* save control regs */
592 misc = NVReadPRMVIO(pNv, 0, NV_PRMVIO_MISC__READ);
593 seq2 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX);
594 seq4 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX);
595 gr4 = NVReadVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX);
596 gr5 = NVReadVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX);
597 gr6 = NVReadVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX);
598
599 NVWritePRMVIO(pNv, 0, NV_PRMVIO_MISC__WRITE, 0x67);
600 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX, 0x6);
601 NVWriteVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX, 0x0);
602 NVWriteVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX, 0x5);
603
604 /* store font in plane 0 */
605 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x1);
606 NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x0);
607 for (i = 0; i < 16384; i++)
608 if (save)
609 pNv->saved_vga_font[0][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
610 else
611 MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[0][i]);
612
613 /* store font in plane 1 */
614 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x2);
615 NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x1);
616 for (i = 0; i < 16384; i++)
617 if (save)
618 pNv->saved_vga_font[1][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
619 else
620 MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[1][i]);
621
622 /* store font in plane 2 */
623 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x4);
624 NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x2);
625 for (i = 0; i < 16384; i++)
626 if (save)
627 pNv->saved_vga_font[2][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
628 else
629 MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[2][i]);
630
631 /* store font in plane 3 */
632 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, 0x8);
633 NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, 0x3);
634 for (i = 0; i < 16384; i++)
635 if (save)
636 pNv->saved_vga_font[3][i] = MMIO_IN32(pNv->FB_BAR, i * 4);
637 else
638 MMIO_OUT32(pNv->FB_BAR, i * 4, pNv->saved_vga_font[3][i]);
639
640 /* restore control regs */
641 NVWritePRMVIO(pNv, 0, NV_PRMVIO_MISC__WRITE, misc);
642 NVWriteVgaGr(pNv, 0, NV_VIO_GX_READ_MAP_INDEX, gr4);
643 NVWriteVgaGr(pNv, 0, NV_VIO_GX_MODE_INDEX, gr5);
644 NVWriteVgaGr(pNv, 0, NV_VIO_GX_MISC_INDEX, gr6);
645 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_PLANE_MASK_INDEX, seq2);
646 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_MEM_MODE_INDEX, seq4);
647
648 if (pNv->twoHeads)
649 NVBlankScreen(pNv, 1, false);
650 NVBlankScreen(pNv, 0, false);
651}
652
653/*
654 * mode state save/load
655 */
656
657static void rd_cio_state(NVPtr pNv, int head,
658 struct nouveau_crtc_state *crtcstate, int index)
659{
660 crtcstate->CRTC[index] = NVReadVgaCrtc(pNv, head, index);
661}
662
663static void wr_cio_state(NVPtr pNv, int head,
664 struct nouveau_crtc_state *crtcstate, int index)
665{
666 NVWriteVgaCrtc(pNv, head, index, crtcstate->CRTC[index]);
667}
668
669static void
670nv_save_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *state)
671{
672 NVPtr pNv = NVPTR(pScrn);
673 struct nouveau_crtc_state *regp = &state->head[head];
674 int i;
675
676 if (pNv->Architecture >= NV_ARCH_10)
677 regp->nv10_cursync = NVReadRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC);
678
679 nouveau_hw_get_pllvals(pScrn, head ? VPLL2 : VPLL1, &regp->pllvals);
680 state->pllsel = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT);
681 if (pNv->twoHeads)
682 state->sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK);
683 if (pNv->NVArch == 0x11)
684 regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11);
685
686 regp->ramdac_gen_ctrl = NVReadRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL);
687
688 if (pNv->gf4_disp_arch)
689 regp->ramdac_630 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_630);
690 if (pNv->NVArch >= 0x30)
691 regp->ramdac_634 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_634);
692
693 for (i = 0; i < 7; i++) {
694 uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
695
696 regp->fp_vert_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg);
697 regp->fp_horiz_regs[i] = NVReadRAMDAC(pNv, head, ramdac_reg + 0x20);
698 }
699
700 if (pNv->gf4_disp_arch) {
701 regp->dither = NVReadRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER);
702 for (i = 0; i < 3; i++) {
703 regp->dither_regs[i] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4);
704 regp->dither_regs[i + 3] = NVReadRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4);
705 }
706 }
707
708 regp->fp_control = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
709 regp->fp_debug_0 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0);
710 if (!pNv->gf4_disp_arch && head == 0)
711 /* early chips don't allow access to PRAMDAC_TMDS_* without
712 * the head A FPCLK on (nv11 even locks up) */
713 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0 &
714 ~NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK);
715 regp->fp_debug_1 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1);
716 regp->fp_debug_2 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2);
717
718 if (pNv->Architecture == NV_ARCH_40) {
719 regp->ramdac_a20 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A20);
720 regp->ramdac_a24 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A24);
721 regp->ramdac_a34 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_A34);
722 }
723}
724
725static void nv_load_state_ramdac(ScrnInfoPtr pScrn, int head, struct nouveau_mode_state *state)
726{
727 NVPtr pNv = NVPTR(pScrn);
728 struct nouveau_crtc_state *regp = &state->head[head];
729 uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF;
730 int i;
731
732 if (pNv->Architecture >= NV_ARCH_10)
733 NVWriteRAMDAC(pNv, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync);
734
735 nouveau_hw_setpll(pScrn, pllreg, &regp->pllvals);
736 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel);
737 if (pNv->twoHeads)
738 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk);
739 if (pNv->NVArch == 0x11)
740 NVWriteRAMDAC(pNv, head, NV_RAMDAC_DITHER_NV11, regp->dither);
741
742 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl);
743
744 if (pNv->gf4_disp_arch)
745 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_630, regp->ramdac_630);
746 if (pNv->NVArch >= 0x30)
747 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_634, regp->ramdac_634);
748
749 for (i = 0; i < 7; i++) {
750 uint32_t ramdac_reg = NV_PRAMDAC_FP_VDISPLAY_END + (i * 4);
751
752 NVWriteRAMDAC(pNv, head, ramdac_reg, regp->fp_vert_regs[i]);
753 NVWriteRAMDAC(pNv, head, ramdac_reg + 0x20, regp->fp_horiz_regs[i]);
754 }
755
756 if (pNv->gf4_disp_arch) {
757 NVWriteRAMDAC(pNv, head, NV_RAMDAC_FP_DITHER, regp->dither);
758 for (i = 0; i < 3; i++) {
759 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_850 + i * 4, regp->dither_regs[i]);
760 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_85C + i * 4, regp->dither_regs[i + 3]);
761 }
762 }
763
764 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL, regp->fp_control);
765 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_0, regp->fp_debug_0);
766 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_1, regp->fp_debug_1);
767 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_DEBUG_2, regp->fp_debug_2);
768
769 if (pNv->Architecture == NV_ARCH_40) {
770 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A20, regp->ramdac_a20);
771 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A24, regp->ramdac_a24);
772 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_A34, regp->ramdac_a34);
773 }
774}
775
776static void
777nv_save_state_vga(NVPtr pNv, int head, struct nouveau_mode_state *state)
778{
779 struct nouveau_crtc_state *regp = &state->head[head];
780 int i;
781
782 regp->MiscOutReg = NVReadPRMVIO(pNv, head, NV_PRMVIO_MISC__READ);
783
784 for (i = 0; i < 25; i++)
785 rd_cio_state(pNv, head, regp, i);
786
787 NVSetEnablePalette(pNv, head, true);
788 for (i = 0; i < 21; i++)
789 regp->Attribute[i] = NVReadVgaAttr(pNv, head, i);
790 NVSetEnablePalette(pNv, head, false);
791
792 for (i = 0; i < 9; i++)
793 regp->Graphics[i] = NVReadVgaGr(pNv, head, i);
794
795 for (i = 0; i < 5; i++)
796 regp->Sequencer[i] = NVReadVgaSeq(pNv, head, i);
797}
798
799static void nv_load_state_vga(NVPtr pNv, int head, struct nouveau_mode_state *state)
800{
801 struct nouveau_crtc_state *regp = &state->head[head];
802 int i;
803
804 NVWritePRMVIO(pNv, head, NV_PRMVIO_MISC__WRITE, regp->MiscOutReg);
805
806 for (i = 0; i < 5; i++)
807 NVWriteVgaSeq(pNv, head, i, regp->Sequencer[i]);
808
809 nv_lock_vga_crtc_base(pNv, head, false);
810 for (i = 0; i < 25; i++)
811 wr_cio_state(pNv, head, regp, i);
812 nv_lock_vga_crtc_base(pNv, head, true);
813
814 for (i = 0; i < 9; i++)
815 NVWriteVgaGr(pNv, head, i, regp->Graphics[i]);
816
817 NVSetEnablePalette(pNv, head, true);
818 for (i = 0; i < 21; i++)
819 NVWriteVgaAttr(pNv, head, i, regp->Attribute[i]);
820 NVSetEnablePalette(pNv, head, false);
821}
822
823static void
824nv_save_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *state)
825{
826 struct nouveau_crtc_state *regp = &state->head[head];
827 int i;
828
829 rd_cio_state(pNv, head, regp, NV_CIO_CRE_LCD__INDEX);
830 rd_cio_state(pNv, head, regp, NV_CIO_CRE_RPC0_INDEX);
831 rd_cio_state(pNv, head, regp, NV_CIO_CRE_RPC1_INDEX);
832 rd_cio_state(pNv, head, regp, NV_CIO_CRE_LSR_INDEX);
833 rd_cio_state(pNv, head, regp, NV_CIO_CRE_PIXEL_INDEX);
834 rd_cio_state(pNv, head, regp, NV_CIO_CRE_HEB__INDEX);
835 rd_cio_state(pNv, head, regp, NV_CIO_CRE_ENH_INDEX);
836
837 rd_cio_state(pNv, head, regp, NV_CIO_CRE_FF_INDEX);
838 rd_cio_state(pNv, head, regp, NV_CIO_CRE_FFLWM__INDEX);
839 rd_cio_state(pNv, head, regp, NV_CIO_CRE_21);
840 if (pNv->Architecture >= NV_ARCH_30)
841 rd_cio_state(pNv, head, regp, NV_CIO_CRE_47);
842 rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
843 rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
844 rd_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
845 rd_cio_state(pNv, head, regp, NV_CIO_CRE_ILACE__INDEX);
846
847 if (pNv->Architecture >= NV_ARCH_10) {
848 regp->crtc_830 = NVReadCRTC(pNv, head, NV_PCRTC_830);
849 regp->crtc_834 = NVReadCRTC(pNv, head, NV_PCRTC_834);
850 if (pNv->Architecture == NV_ARCH_40) {
851 regp->crtc_850 = NVReadCRTC(pNv, head, NV_PCRTC_850);
852 regp->gpio_ext = NVReadCRTC(pNv, head, NV_PCRTC_GPIO_EXT);
853 }
854 if (pNv->twoHeads)
855 regp->crtc_eng_ctrl = NVReadCRTC(pNv, head, NV_PCRTC_ENGINE_CTRL);
856 regp->cursor_cfg = NVReadCRTC(pNv, head, NV_PCRTC_CURSOR_CONFIG);
857 }
858
859 regp->crtc_cfg = NVReadCRTC(pNv, head, NV_PCRTC_CONFIG);
860
861 rd_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
862 rd_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
863 if (pNv->Architecture >= NV_ARCH_10) {
864 rd_cio_state(pNv, head, regp, NV_CIO_CRE_EBR_INDEX);
865 rd_cio_state(pNv, head, regp, NV_CIO_CRE_CSB);
866 rd_cio_state(pNv, head, regp, NV_CIO_CRE_4B);
867 rd_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
868 }
869 if (pNv->gf4_disp_arch) {
870 rd_cio_state(pNv, head, regp, NV_CIO_CRE_53);
871 rd_cio_state(pNv, head, regp, NV_CIO_CRE_54);
872
873 for (i = 0; i < 0x10; i++)
874 regp->CR58[i] = NVReadVgaCrtc5758(pNv, head, i);
875 rd_cio_state(pNv, head, regp, NV_CIO_CRE_59);
876 rd_cio_state(pNv, head, regp, NV_CIO_CRE_5B);
877
878 rd_cio_state(pNv, head, regp, NV_CIO_CRE_85);
879 rd_cio_state(pNv, head, regp, NV_CIO_CRE_86);
880 }
881
882 regp->fb_start = NVReadCRTC(pNv, head, NV_PCRTC_START);
883}
884
885static void nv_load_state_ext(NVPtr pNv, int head, struct nouveau_mode_state *state)
886{
887 struct nouveau_crtc_state *regp = &state->head[head];
888 int i;
889
890 if (pNv->Architecture >= NV_ARCH_10) {
891 if (pNv->twoHeads)
892 /* setting ENGINE_CTRL (EC) *must* come before
893 * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in
894 * EC that should not be overwritten by writing stale EC
895 */
896 NVWriteCRTC(pNv, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl);
897
898 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
899 nvWriteVIDEO(pNv, NV_PVIDEO_INTR_EN, 0);
900 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(0), 0);
901 nvWriteVIDEO(pNv, NV_PVIDEO_OFFSET_BUFF(1), 0);
902 nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(0), pNv->VRAMPhysicalSize - 1);
903 nvWriteVIDEO(pNv, NV_PVIDEO_LIMIT(1), pNv->VRAMPhysicalSize - 1);
904 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(0), pNv->VRAMPhysicalSize - 1);
905 nvWriteVIDEO(pNv, NV_PVIDEO_UVPLANE_LIMIT(1), pNv->VRAMPhysicalSize - 1);
906 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0);
907
908 NVWriteCRTC(pNv, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg);
909 NVWriteCRTC(pNv, head, NV_PCRTC_830, regp->crtc_830);
910 NVWriteCRTC(pNv, head, NV_PCRTC_834, regp->crtc_834);
911 if (pNv->Architecture == NV_ARCH_40) {
912 NVWriteCRTC(pNv, head, NV_PCRTC_850, regp->crtc_850);
913 NVWriteCRTC(pNv, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext);
914 }
915
916 if (pNv->Architecture == NV_ARCH_40) {
917 uint32_t reg900 = NVReadRAMDAC(pNv, head, NV_PRAMDAC_900);
918 if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC)
919 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_900, reg900 | 0x10000);
920 else
921 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_900, reg900 & ~0x10000);
922 }
923 }
924
925 NVWriteCRTC(pNv, head, NV_PCRTC_CONFIG, regp->crtc_cfg);
926
927 wr_cio_state(pNv, head, regp, NV_CIO_CRE_RPC0_INDEX);
928 wr_cio_state(pNv, head, regp, NV_CIO_CRE_RPC1_INDEX);
929 wr_cio_state(pNv, head, regp, NV_CIO_CRE_LSR_INDEX);
930 wr_cio_state(pNv, head, regp, NV_CIO_CRE_PIXEL_INDEX);
931 wr_cio_state(pNv, head, regp, NV_CIO_CRE_LCD__INDEX);
932 wr_cio_state(pNv, head, regp, NV_CIO_CRE_HEB__INDEX);
933 wr_cio_state(pNv, head, regp, NV_CIO_CRE_ENH_INDEX);
934 wr_cio_state(pNv, head, regp, NV_CIO_CRE_FF_INDEX);
935 wr_cio_state(pNv, head, regp, NV_CIO_CRE_FFLWM__INDEX);
936 if (pNv->Architecture >= NV_ARCH_30)
937 wr_cio_state(pNv, head, regp, NV_CIO_CRE_47);
938
939 wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX);
940 wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX);
941 wr_cio_state(pNv, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX);
942 if (pNv->Architecture == NV_ARCH_40)
943 nv_fix_nv40_hw_cursor(pNv, head);
944 wr_cio_state(pNv, head, regp, NV_CIO_CRE_ILACE__INDEX);
945
946 wr_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH3__INDEX);
947 wr_cio_state(pNv, head, regp, NV_CIO_CRE_SCRATCH4__INDEX);
948 if (pNv->Architecture >= NV_ARCH_10) {
949 wr_cio_state(pNv, head, regp, NV_CIO_CRE_EBR_INDEX);
950 wr_cio_state(pNv, head, regp, NV_CIO_CRE_CSB);
951 wr_cio_state(pNv, head, regp, NV_CIO_CRE_4B);
952 wr_cio_state(pNv, head, regp, NV_CIO_CRE_TVOUT_LATENCY);
953 }
954 if (pNv->gf4_disp_arch) {
955 wr_cio_state(pNv, head, regp, NV_CIO_CRE_53);
956 wr_cio_state(pNv, head, regp, NV_CIO_CRE_54);
957
958 for (i = 0; i < 0x10; i++)
959 NVWriteVgaCrtc5758(pNv, head, i, regp->CR58[i]);
960 wr_cio_state(pNv, head, regp, NV_CIO_CRE_59);
961 wr_cio_state(pNv, head, regp, NV_CIO_CRE_5B);
962
963 wr_cio_state(pNv, head, regp, NV_CIO_CRE_85);
964 wr_cio_state(pNv, head, regp, NV_CIO_CRE_86);
965 }
966
967 NVWriteCRTC(pNv, head, NV_PCRTC_START, regp->fb_start);
968
969 /* Setting 1 on this value gives you interrupts for every vblank period. */
970 NVWriteCRTC(pNv, head, NV_PCRTC_INTR_EN_0, 0);
971 NVWriteCRTC(pNv, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK);
972}
973
974static void
975nv_save_state_palette(NVPtr pNv, int head, struct nouveau_mode_state *state)
976{
977 int head_offset = head * NV_PRMDIO_SIZE, i;
978
979 VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK);
980 VGA_WR08(pNv->REGS, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0);
981
982 for (i = 0; i < 768; i++) {
983 state->head[head].DAC[i] = NV_RD08(pNv->REGS, NV_PRMDIO_PALETTE_DATA + head_offset);
984 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]);
985 }
986
987 NVSetEnablePalette(pNv, head, false);
988}
989
990void nouveau_hw_load_state_palette(NVPtr pNv, int head,
991 struct nouveau_mode_state *state)
992{
993 int head_offset = head * NV_PRMDIO_SIZE, i;
994
995 VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK + head_offset, NV_PRMDIO_PIXEL_MASK_MASK);
996 VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0);
997
998 for (i = 0; i < 768; i++) {
999 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]);
1000 NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA + head_offset, state->head[head].DAC[i]);
1001 }
1002
1003 NVSetEnablePalette(pNv, head, false);
1004}
1005
1006void nouveau_hw_save_state(ScrnInfoPtr pScrn, int head,
1007 struct nouveau_mode_state *state)
1008{
1009 NVPtr pNv = NVPTR(pScrn);
1010
1011 if (pNv->NVArch == 0x11)
1012 /* NB: no attempt is made to restore the bad pll later on */
1013 nouveau_hw_fix_bad_vpll(pScrn, head);
1014 nv_save_state_ramdac(pScrn, head, state);
1015 nv_save_state_vga(pNv, head, state);
1016 nv_save_state_palette(pNv, head, state);
1017 nv_save_state_ext(pNv, head, state);
1018}
1019
1020void nouveau_hw_load_state(ScrnInfoPtr pScrn, int head,
1021 struct nouveau_mode_state *state)
1022{
1023 NVPtr pNv = NVPTR(pScrn);
1024
1025 NVVgaProtect(pNv, head, true);
1026 nv_load_state_ramdac(pScrn, head, state);
1027 nv_load_state_ext(pNv, head, state);
1028 nouveau_hw_load_state_palette(pNv, head, state);
1029 nv_load_state_vga(pNv, head, state);
1030 NVVgaProtect(pNv, head, false);
1031}
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 @@
1/*
2 * Copyright 2008 Stuart Bennett
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_HW_H__
24#define __NOUVEAU_HW_H__
25
26#define MASK(field) ((0xffffffff >> (31 - ((1?field) - (0?field)))) << (0?field))
27#define XLATE(src, srclowbit, outfield) ((((src) >> (srclowbit)) << (0?outfield)) & MASK(outfield))
28
29#define nvReadMC(pNv, reg) DDXMMIOW("nvReadMC: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg))
30#define nvWriteMC(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteMC: reg %08x val %08x\n", reg, val))
31
32#define nvReadVIDEO(pNv, reg) DDXMMIOW("nvReadVIDEO: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg))
33#define nvWriteVIDEO(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteVIDEO: reg %08x val %08x\n", reg, val))
34
35#define nvReadFB(pNv, reg) DDXMMIOW("nvReadFB: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg))
36#define nvWriteFB(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteFB: reg %08x val %08x\n", reg, val))
37
38#define nvReadEXTDEV(pNv, reg) DDXMMIOW("nvReadEXTDEV: reg %08x val %08x\n", reg, (uint32_t)MMIO_IN32(pNv->REGS, reg))
39#define nvWriteEXTDEV(pNv, reg, val) MMIO_OUT32(pNv->REGS, reg, DDXMMIOW("nvWriteEXTDEV: reg %08x val %08x\n", reg, val))
40
41static inline uint32_t NVRead(NVPtr pNv, uint32_t reg)
42{
43 DDXMMIOW("NVRead: reg %08x val %08x\n", reg, (uint32_t)NV_RD32(pNv->REGS, reg));
44 return NV_RD32(pNv->REGS, reg);
45}
46
47static inline void NVWrite(NVPtr pNv, uint32_t reg, uint32_t val)
48{
49 DDXMMIOW("NVWrite: reg %08x val %08x\n", reg, NV_WR32(pNv->REGS, reg, val));
50}
51
52static inline uint32_t NVReadCRTC(NVPtr pNv, int head, uint32_t reg)
53{
54 if (head)
55 reg += NV_PCRTC0_SIZE;
56 DDXMMIOH("NVReadCRTC: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg));
57 return NV_RD32(pNv->REGS, reg);
58}
59
60static inline void NVWriteCRTC(NVPtr pNv, int head, uint32_t reg, uint32_t val)
61{
62 if (head)
63 reg += NV_PCRTC0_SIZE;
64 DDXMMIOH("NVWriteCRTC: head %d reg %08x val %08x\n", head, reg, val);
65 NV_WR32(pNv->REGS, reg, val);
66}
67
68static inline uint32_t NVReadRAMDAC(NVPtr pNv, int head, uint32_t reg)
69{
70 if (head)
71 reg += NV_PRAMDAC0_SIZE;
72 DDXMMIOH("NVReadRamdac: head %d reg %08x val %08x\n", head, reg, (uint32_t)NV_RD32(pNv->REGS, reg));
73 return NV_RD32(pNv->REGS, reg);
74}
75
76static inline void
77NVWriteRAMDAC(NVPtr pNv, int head, uint32_t reg, uint32_t val)
78{
79 if (head)
80 reg += NV_PRAMDAC0_SIZE;
81 DDXMMIOH("NVWriteRamdac: head %d reg %08x val %08x\n", head, reg, val);
82 NV_WR32(pNv->REGS, reg, val);
83}
84
85static inline uint8_t nv_read_tmds(NVPtr pNv, int or, int dl, uint8_t address)
86{
87 int ramdac = (or & OUTPUT_C) >> 2;
88
89 NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8,
90 NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | address);
91 return NVReadRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8);
92}
93
94static inline void
95nv_write_tmds(NVPtr pNv, int or, int dl, uint8_t address, uint8_t data)
96{
97 int ramdac = (or & OUTPUT_C) >> 2;
98
99 NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA + dl * 8, data);
100 NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL + dl * 8, address);
101}
102
103static inline void
104NVWriteVgaCrtc(NVPtr pNv, int head, uint8_t index, uint8_t value)
105{
106 DDXMMIOH("NVWriteVgaCrtc: head %d index 0x%02x data 0x%02x\n", head, index, value);
107 NV_WR08(pNv->REGS, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
108 NV_WR08(pNv->REGS, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value);
109}
110
111static inline uint8_t NVReadVgaCrtc(NVPtr pNv, int head, uint8_t index)
112{
113 NV_WR08(pNv->REGS, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index);
114 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));
115 return NV_RD08(pNv->REGS, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE);
116}
117
118/* CR57 and CR58 are a fun pair of regs. CR57 provides an index (0-0xf) for CR58
119 * I suspect they in fact do nothing, but are merely a way to carry useful
120 * per-head variables around
121 *
122 * Known uses:
123 * CR57 CR58
124 * 0x00 index to the appropriate dcb entry (or 7f for inactive)
125 * 0x02 dcb entry's "or" value (or 00 for inactive)
126 * 0x03 bit0 set for dual link (LVDS, possibly elsewhere too)
127 * 0x08 or 0x09 pxclk in MHz
128 * 0x0f laptop panel info - low nibble for PEXTDEV_BOOT_0 strap
129 * high nibble for xlat strap value
130 */
131
132static inline void
133NVWriteVgaCrtc5758(NVPtr pNv, int head, uint8_t index, uint8_t value)
134{
135 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_57, index);
136 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_58, value);
137}
138
139static inline uint8_t NVReadVgaCrtc5758(NVPtr pNv, int head, uint8_t index)
140{
141 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_57, index);
142 return NVReadVgaCrtc(pNv, head, NV_CIO_CRE_58);
143}
144
145static inline uint8_t NVReadPRMVIO(NVPtr pNv, int head, uint32_t reg)
146{
147 /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
148 * NVSetOwner for the relevant head to be programmed */
149 if (head && pNv->Architecture == NV_ARCH_40)
150 reg += NV_PRMVIO_SIZE;
151
152 DDXMMIOH("NVReadPRMVIO: head %d reg %08x val %02x\n", head, reg, NV_RD08(pNv->REGS, reg));
153 return NV_RD08(pNv->REGS, reg);
154}
155
156static inline void
157NVWritePRMVIO(NVPtr pNv, int head, uint32_t reg, uint8_t value)
158{
159 /* Only NV4x have two pvio ranges; other twoHeads cards MUST call
160 * NVSetOwner for the relevant head to be programmed */
161 if (head && pNv->Architecture == NV_ARCH_40)
162 reg += NV_PRMVIO_SIZE;
163
164 DDXMMIOH("NVWritePRMVIO: head %d reg %08x val %02x\n", head, reg, value);
165 NV_WR08(pNv->REGS, reg, value);
166}
167
168static inline void NVSetEnablePalette(NVPtr pNv, int head, bool enable)
169{
170 VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
171 VGA_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE,
172 enable ? 0 : 0x20);
173}
174
175static inline bool NVGetEnablePalette(NVPtr pNv, int head)
176{
177 VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
178 return !(VGA_RD08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) &
179 0x20);
180}
181
182static inline void NVWriteVgaAttr(NVPtr pNv, int head, uint8_t index, uint8_t value)
183{
184 if (NVGetEnablePalette(pNv, head))
185 index &= ~0x20;
186 else
187 index |= 0x20;
188
189 NV_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
190 DDXMMIOH("NVWriteVgaAttr: head %d index 0x%02x data 0x%02x\n", head, index, value);
191 NV_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
192 NV_WR08(pNv->REGS, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value);
193}
194
195static inline uint8_t NVReadVgaAttr(NVPtr pNv, int head, uint8_t index)
196{
197 if (NVGetEnablePalette(pNv, head))
198 index &= ~0x20;
199 else
200 index |= 0x20;
201
202 NV_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE);
203 NV_WR08(pNv->REGS, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index);
204 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));
205 return NV_RD08(pNv->REGS, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE);
206}
207
208static inline void NVVgaSeqReset(NVPtr pNv, int head, bool start)
209{
210 NVWriteVgaSeq(pNv, head, NV_VIO_SR_RESET_INDEX, start ? 0x1 : 0x3);
211}
212
213static inline void NVVgaProtect(NVPtr pNv, int head, bool protect)
214{
215 uint8_t seq1 = NVReadVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX);
216
217 if (protect) {
218 NVVgaSeqReset(pNv, head, true);
219 NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 | 0x20);
220 } else {
221 /* Reenable sequencer, then turn on screen */
222 NVWriteVgaSeq(pNv, head, NV_VIO_SR_CLOCK_INDEX, seq1 & ~0x20); /* reenable display */
223 NVVgaSeqReset(pNv, head, false);
224 }
225 NVSetEnablePalette(pNv, head, protect);
226}
227
228static inline bool nv_heads_tied(NVPtr pNv)
229{
230 if (pNv->NVArch == 0x11)
231 return !!(nvReadMC(pNv, NV_PBUS_DEBUG_1) & (1 << 28));
232
233 return (NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_44) & 0x4);
234}
235
236/* makes cr0-7 on the specified head read-only */
237static inline bool nv_lock_vga_crtc_base(NVPtr pNv, int head, bool lock)
238{
239 uint8_t cr11 = NVReadVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX);
240 bool waslocked = cr11 & 0x80;
241
242 if (lock)
243 cr11 |= 0x80;
244 else
245 cr11 &= ~0x80;
246 NVWriteVgaCrtc(pNv, head, NV_CIO_CR_VRE_INDEX, cr11);
247
248 return waslocked;
249}
250
251static inline void nv_lock_vga_crtc_shadow(NVPtr pNv, int head, int lock)
252{
253 /* shadow lock: connects 0x60?3d? regs to "real" 0x3d? regs
254 * bit7: unlocks HDT, HBS, HBE, HRS, HRE, HEB
255 * bit6: seems to have some effect on CR09 (double scan, VBS_9)
256 * bit5: unlocks HDE
257 * bit4: unlocks VDE
258 * bit3: unlocks VDT, OVL, VRS, ?VRE?, VBS, VBE, LSR, EBR
259 * bit2: same as bit 1 of 0x60?804
260 * bit0: same as bit 0 of 0x60?804
261 */
262
263 uint8_t cr21 = lock;
264
265 if (lock < 0)
266 /* 0xfa is generic "unlock all" mask */
267 cr21 = NVReadVgaCrtc(pNv, head, NV_CIO_CRE_21) | 0xfa;
268
269 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_21, cr21);
270}
271
272/* renders the extended crtc regs (cr19+) on all crtcs impervious:
273 * immutable and unreadable
274 */
275static inline bool NVLockVgaCrtcs(NVPtr pNv, bool lock)
276{
277 bool waslocked = !NVReadVgaCrtc(pNv, 0, NV_CIO_SR_LOCK_INDEX);
278
279 NVWriteVgaCrtc(pNv, 0, NV_CIO_SR_LOCK_INDEX,
280 lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE);
281 /* NV11 has independently lockable extended crtcs, except when tied */
282 if (pNv->NVArch == 0x11 && !nv_heads_tied(pNv))
283 NVWriteVgaCrtc(pNv, 1, NV_CIO_SR_LOCK_INDEX,
284 lock ? NV_CIO_SR_LOCK_VALUE :
285 NV_CIO_SR_UNLOCK_RW_VALUE);
286
287 return waslocked;
288}
289
290/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
291#define NV04_CURSOR_SIZE 32
292/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
293#define NV10_CURSOR_SIZE 64
294
295static inline int nv_cursor_width(NVPtr pNv)
296{
297 return pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
298}
299
300static inline int nv_cursor_pixels(NVPtr pNv)
301{
302 int width = nv_cursor_width(pNv);
303
304 return width * width;
305}
306
307static inline void nv_fix_nv40_hw_cursor(NVPtr pNv, int head)
308{
309 /* on some nv40 (such as the "true" (in the NV_PFB_BOOT_0 sense) nv40,
310 * the gf6800gt) a hardware bug requires a write to PRAMDAC_CURSOR_POS
311 * for changes to the CRTC CURCTL regs to take effect, whether changing
312 * the pixmap location, or just showing/hiding the cursor
313 */
314 volatile uint32_t curpos = NVReadRAMDAC(pNv, head,
315 NV_PRAMDAC_CU_START_POS);
316 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_CU_START_POS, curpos);
317}
318
319static inline void nv_show_cursor(NVPtr pNv, int head, bool show)
320{
321 uint8_t *curctl1 =
322 &pNv->set_state.head[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX];
323
324 if (show)
325 *curctl1 |= MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
326 else
327 *curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE);
328 NVWriteVgaCrtc(pNv, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1);
329
330 if (pNv->Architecture == NV_ARCH_40)
331 nv_fix_nv40_hw_cursor(pNv, head);
332}
333
334static inline uint32_t nv_pitch_align(NVPtr pNv, uint32_t width, int bpp)
335{
336 int mask;
337
338 if (bpp == 15)
339 bpp = 16;
340 if (bpp == 24 || bpp == 30)
341 bpp = 8;
342
343 /* Alignment requirements taken from the Haiku driver */
344 if (pNv->Architecture == NV_ARCH_04)
345 mask = 128 / bpp - 1;
346 else
347 mask = 512 / bpp - 1;
348
349 return (width + mask) & ~mask;
350}
351
352#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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_MODESET_H_
24#define __NOUVEAU_MODESET_H_
25
26/* Forward declarations. */
27typedef struct nouveauCrtc *nouveauCrtcPtr;
28typedef struct nouveauConnector *nouveauConnectorPtr;
29typedef struct nouveauOutput *nouveauOutputPtr;
30
31#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 @@
1/*
2 * Copyright 2006 Dave Airlie
3 * Copyright 2007 Maarten Maathuis
4 * Copyright 2007-2009 Stuart Bennett
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef __NOUVEAU_MS_H__
27#define __NOUVEAU_MS_H__
28
29//#define NOUVEAU_DEBUG
30#ifdef NOUVEAU_DEBUG
31#define NV_DEBUG(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_INFO, fmt, ##arg)
32#else
33#define NV_DEBUG(d, fmt, arg...)
34#endif
35#define NV_ERROR(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_ERROR, fmt, ##arg)
36#define NV_INFO(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_PROBED, fmt, ##arg)
37#define NV_TRACEWARN(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_NOTICE, fmt, ##arg)
38#define NV_TRACE(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_INFO, fmt, ##arg)
39#define NV_WARN(d, fmt, arg...) xf86DrvMsg(d->scrnIndex, X_WARNING, fmt, ##arg)
40
41#define NV_DPMS_CLEARED 0x80
42
43enum scaling_modes {
44 SCALE_PANEL,
45 SCALE_FULLSCREEN,
46 SCALE_ASPECT,
47 SCALE_NOSCALE,
48 SCALE_INVALID
49};
50
51struct nouveau_pll_vals {
52 union {
53 struct {
54#if X_BYTE_ORDER == X_BIG_ENDIAN
55 uint8_t N1, M1, N2, M2;
56#else
57 uint8_t M1, N1, M2, N2;
58#endif
59 };
60 struct {
61 uint16_t NM1, NM2;
62 } __attribute__((packed));
63 };
64 int log2P;
65
66 int refclk;
67};
68
69struct nouveau_crtc_state {
70 uint8_t MiscOutReg;
71 uint8_t CRTC[0x9f];
72 uint8_t CR58[0x10];
73 uint8_t Sequencer[5];
74 uint8_t Graphics[9];
75 uint8_t Attribute[21];
76 uint8_t DAC[768];
77
78 /* PCRTC regs */
79 uint32_t fb_start;
80 uint32_t crtc_cfg;
81 uint32_t cursor_cfg;
82 uint32_t gpio_ext;
83 uint32_t crtc_830;
84 uint32_t crtc_834;
85 uint32_t crtc_850;
86 uint32_t crtc_eng_ctrl;
87
88 /* PRAMDAC regs */
89 uint32_t nv10_cursync;
90 struct nouveau_pll_vals pllvals;
91 uint32_t ramdac_gen_ctrl;
92 uint32_t ramdac_630;
93 uint32_t ramdac_634;
94 uint32_t fp_horiz_regs[7];
95 uint32_t fp_vert_regs[7];
96 uint32_t dither;
97 uint32_t fp_control;
98 uint32_t dither_regs[6];
99 uint32_t fp_debug_0;
100 uint32_t fp_debug_1;
101 uint32_t fp_debug_2;
102 uint32_t ramdac_a20;
103 uint32_t ramdac_a24;
104 uint32_t ramdac_a34;
105};
106
107struct nouveau_encoder_state {
108 uint32_t output;
109 int head;
110};
111
112struct nouveau_mode_state
113{
114 uint32_t pllsel;
115 uint32_t sel_clk;
116
117 struct nouveau_crtc_state head[2];
118};
119
120struct nouveau_crtc {
121 int head;
122 uint8_t last_dpms;
123 int fp_users;
124 uint32_t dpms_saved_fp_control;
125 int saturation, sharpness;
126
127 /* convenient pointer to pNv->set_state.head[head_nr] */
128 struct nouveau_crtc_state *state;
129
130 uint32_t cursor_fg, cursor_bg;
131
132 struct nouveau_bo *bo;
133 ExaOffscreenArea *shadow;
134 unsigned shadow_pitch;
135};
136
137struct nouveau_encoder {
138 uint8_t last_dpms;
139 struct dcb_entry *dcb;
140 DisplayModePtr native_mode;
141 uint8_t scaling_mode;
142 bool dithering;
143 bool dual_link;
144 struct nouveau_encoder_state restore;
145};
146
147struct nouveau_connector {
148 xf86MonPtr edid;
149 I2CBusPtr pDDCBus;
150 uint16_t possible_encoders;
151 struct nouveau_encoder *detected_encoder;
152 struct nouveau_encoder *nv_encoder;
153};
154
155#define to_nouveau_connector(x) ((struct nouveau_connector *)(x)->driver_private)
156#define to_nouveau_crtc(x) ((struct nouveau_crtc *)(x)->driver_private)
157#define to_nouveau_encoder(x) ((struct nouveau_connector *)(x)->driver_private)->nv_encoder
158
159#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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NOUVEAU_OUTPUT_H_
24#define __NOUVEAU_OUTPUT_H_
25
26#include "nv_include.h"
27#include "nouveau_modeset.h"
28#include "nouveau_crtc.h"
29#include "nouveau_connector.h"
30
31typedef struct nouveauOutput {
32 ScrnInfoPtr scrn;
33
34 char *name;
35 Bool active;
36 nouveauOutputPtr next;
37
38 nouveauCrtcPtr crtc;
39 nouveauConnectorPtr connector; /* the one that is currently in use, not all possibilities. */
40
41 /* This can change in rare circumstances, when an output resource is shared. */
42 struct dcb_entry *dcb;
43 int type;
44 uint8_t allowed_crtc; /* bit0: crtc0, bit1: crtc1 */
45 int scale_mode;
46 Bool dithering;
47
48 /* Mode stuff. */
49 DisplayModePtr native_mode;
50
51 /* Function pointers. */
52 int (*ModeValid) (nouveauOutputPtr output, DisplayModePtr mode);
53 void (*ModeSet) (nouveauOutputPtr output, DisplayModePtr mode);
54 void (*SetClockMode) (nouveauOutputPtr output, int clock); /* maybe another name? */
55
56 /* This will handle the case where output resources are shared. */
57 int (*Sense) (nouveauOutputPtr output); /* this is not for ddc or load detect, and will often just return a fixed type. */
58 Bool (*Detect) (nouveauOutputPtr output); /* everything that isn't hotplug detect or ddc */
59
60 void (*SetPowerMode) (nouveauOutputPtr output, int mode);
61
62 /* Get the last associated crtc of the output. */
63 nouveauCrtcPtr (*GetCurrentCrtc) (nouveauOutputPtr output);
64
65 void (*Save) (nouveauOutputPtr output);
66 void (*Load) (nouveauOutputPtr output);
67} nouveauOutputRec;
68
69#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)
285 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 285 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
286 286
287 NVFreePortMemory(pScrn, pPriv); 287 NVFreePortMemory(pScrn, pPriv);
288 288#if NVOVL_SUPPORT
289 /* "power cycle" the overlay */ 289 /* "power cycle" the overlay */
290 nvWriteMC(pNv, NV_PMC_ENABLE, 290 nvWriteMC(pNv, NV_PMC_ENABLE,
291 (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF)); 291 (nvReadMC(pNv, NV_PMC_ENABLE) & 0xEFFFFFFF));
292 nvWriteMC(pNv, NV_PMC_ENABLE, 292 nvWriteMC(pNv, NV_PMC_ENABLE,
293 (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000)); 293 (nvReadMC(pNv, NV_PMC_ENABLE) | 0x10000000));
294#endif
294} 295}
295 296
296/** 297/**
@@ -805,6 +806,7 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
805 } 806 }
806#endif 807#endif
807 808
809#ifdef NVOVL_SUPPORT
808 if (USING_OVERLAY) { 810 if (USING_OVERLAY) {
809 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y, 811 char crtc = nv_window_belongs_to_crtc(pScrn, drw_x, drw_y,
810 drw_w, drw_h); 812 drw_w, drw_h);
@@ -845,6 +847,7 @@ NV_set_action_flags(ScrnInfoPtr pScrn, DrawablePtr pDraw, NVPortPrivPtr pPriv,
845 ->rotation != RR_Rotate_0) 847 ->rotation != RR_Rotate_0)
846 *action_flags &= ~USE_OVERLAY; 848 *action_flags &= ~USE_OVERLAY;
847 } 849 }
850#endif
848 851
849 /* At this point the adapter we're going to use is _known_. 852 /* At this point the adapter we're going to use is _known_.
850 * You cannot change it now. 853 * You cannot change it now.
@@ -991,6 +994,7 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
991 994
992 /* The overlay supports hardware double buffering. We handle this here*/ 995 /* The overlay supports hardware double buffering. We handle this here*/
993 offset = 0; 996 offset = 0;
997#ifdef NVOVL_SUPPORT
994 if (pPriv->doubleBuffer) { 998 if (pPriv->doubleBuffer) {
995 int mask = 1 << (pPriv->currentBuffer << 2); 999 int mask = 1 << (pPriv->currentBuffer << 2);
996 1000
@@ -1004,6 +1008,7 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x,
1004 offset += newFBSize >> 1; 1008 offset += newFBSize >> 1;
1005 } 1009 }
1006 } 1010 }
1011#endif
1007 1012
1008 /* Now we take a decision regarding the way we send the data to the 1013 /* Now we take a decision regarding the way we send the data to the
1009 * card. 1014 * card.
@@ -1601,7 +1606,7 @@ NVSetupBlitVideo (ScreenPtr pScreen)
1601 for(i = 0; i < NUM_BLIT_PORTS; i++) 1606 for(i = 0; i < NUM_BLIT_PORTS; i++)
1602 adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 1607 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1603 1608
1604 if(pNv->WaitVSyncPossible) { 1609 if (pNv->NVArch >= 0x11) {
1605 adapt->pAttributes = NVBlitAttributes; 1610 adapt->pAttributes = NVBlitAttributes;
1606 adapt->nAttributes = NUM_BLIT_ATTRIBUTES; 1611 adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
1607 } else { 1612 } else {
@@ -1628,7 +1633,7 @@ NVSetupBlitVideo (ScreenPtr pScreen)
1628 pPriv->texture = FALSE; 1633 pPriv->texture = FALSE;
1629 pPriv->bicubic = FALSE; 1634 pPriv->bicubic = FALSE;
1630 pPriv->doubleBuffer = FALSE; 1635 pPriv->doubleBuffer = FALSE;
1631 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 1636 pPriv->SyncToVBlank = (pNv->NVArch >= 0x11);
1632 1637
1633 pNv->blitAdaptor = adapt; 1638 pNv->blitAdaptor = adapt;
1634 1639
@@ -1771,7 +1776,7 @@ NVChipsetHasOverlay(NVPtr pNv)
1771 case NV_ARCH_30: 1776 case NV_ARCH_30:
1772 return TRUE; 1777 return TRUE;
1773 case NV_ARCH_40: 1778 case NV_ARCH_40:
1774 if ((pNv->Chipset & 0xfff0) == CHIPSET_NV40) 1779 if (pNv->NVArch == 0x40)
1775 return TRUE; 1780 return TRUE;
1776 break; 1781 break;
1777 default: 1782 default:
@@ -1798,7 +1803,7 @@ NVSetupOverlayVideo(ScreenPtr pScreen)
1798 XF86VideoAdaptorPtr overlayAdaptor = NULL; 1803 XF86VideoAdaptorPtr overlayAdaptor = NULL;
1799 NVPtr pNv = NVPTR(pScrn); 1804 NVPtr pNv = NVPTR(pScrn);
1800 1805
1801 if (pNv->kms_enable || !NVChipsetHasOverlay(pNv)) 1806 if (1 /*pNv->kms_enable*/ || !NVChipsetHasOverlay(pNv))
1802 return NULL; 1807 return NULL;
1803 1808
1804 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen); 1809 overlayAdaptor = NVSetupOverlayVideoAdapter(pScreen);
@@ -1868,14 +1873,8 @@ NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1868 for(i = 0; i < NUM_TEXTURE_PORTS; i++) 1873 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1869 adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 1874 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1870 1875
1871 if (pNv->WaitVSyncPossible) { 1876 adapt->pAttributes = NVTexturedAttributes;
1872 adapt->pAttributes = NVTexturedAttributes; 1877 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1873 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1874 } else {
1875 adapt->pAttributes = NULL;
1876 adapt->nAttributes = 0;
1877 }
1878
1879 adapt->pImages = NV30TexturedImages; 1878 adapt->pImages = NV30TexturedImages;
1880 adapt->nImages = NUM_FORMAT_TEXTURED; 1879 adapt->nImages = NUM_FORMAT_TEXTURED;
1881 adapt->PutVideo = NULL; 1880 adapt->PutVideo = NULL;
@@ -1895,7 +1894,7 @@ NV30SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1895 pPriv->texture = TRUE; 1894 pPriv->texture = TRUE;
1896 pPriv->bicubic = bicubic; 1895 pPriv->bicubic = bicubic;
1897 pPriv->doubleBuffer = FALSE; 1896 pPriv->doubleBuffer = FALSE;
1898 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 1897 pPriv->SyncToVBlank = TRUE;
1899 1898
1900 if (bicubic) 1899 if (bicubic)
1901 pNv->textureAdaptor[1] = adapt; 1900 pNv->textureAdaptor[1] = adapt;
@@ -1955,14 +1954,8 @@ NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1955 for(i = 0; i < NUM_TEXTURE_PORTS; i++) 1954 for(i = 0; i < NUM_TEXTURE_PORTS; i++)
1956 adapt->pPortPrivates[i].ptr = (pointer)(pPriv); 1955 adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
1957 1956
1958 if(pNv->WaitVSyncPossible) { 1957 adapt->pAttributes = NVTexturedAttributes;
1959 adapt->pAttributes = NVTexturedAttributes; 1958 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1960 adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
1961 } else {
1962 adapt->pAttributes = NULL;
1963 adapt->nAttributes = 0;
1964 }
1965
1966 adapt->pImages = NV40TexturedImages; 1959 adapt->pImages = NV40TexturedImages;
1967 adapt->nImages = NUM_FORMAT_TEXTURED; 1960 adapt->nImages = NUM_FORMAT_TEXTURED;
1968 adapt->PutVideo = NULL; 1961 adapt->PutVideo = NULL;
@@ -1982,7 +1975,7 @@ NV40SetupTexturedVideo (ScreenPtr pScreen, Bool bicubic)
1982 pPriv->texture = TRUE; 1975 pPriv->texture = TRUE;
1983 pPriv->bicubic = bicubic; 1976 pPriv->bicubic = bicubic;
1984 pPriv->doubleBuffer = FALSE; 1977 pPriv->doubleBuffer = FALSE;
1985 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 1978 pPriv->SyncToVBlank = TRUE;
1986 1979
1987 if (bicubic) 1980 if (bicubic)
1988 pNv->textureAdaptor[1] = adapt; 1981 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 @@
36 36
37#define FOURCC_RGB 0x0000003 37#define FOURCC_RGB 0x0000003
38 38
39#define VSYNC_POSSIBLE (pNv->NVArch >= 0x11)
40
39extern Atom xvSetDefaults, xvSyncToVBlank; 41extern Atom xvSetDefaults, xvSyncToVBlank;
40 42
41/** 43/**
@@ -139,7 +141,7 @@ NVPutBlitImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int src_offset,
139 NVWaitVSync(pScrn, 1); 141 NVWaitVSync(pScrn, 1);
140 } 142 }
141 143
142 if(pNv->BlendingPossible) { 144 if ((pNv->Chipset & 0xffff) > CHIPSET_NV04) {
143 BEGIN_RING(chan, sifm, 145 BEGIN_RING(chan, sifm,
144 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2); 146 NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 2);
145 OUT_RING (chan, src_format); 147 OUT_RING (chan, src_format);
@@ -214,13 +216,13 @@ NVSetBlitPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
214 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 216 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
215 NVPtr pNv = NVPTR(pScrn); 217 NVPtr pNv = NVPTR(pScrn);
216 218
217 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { 219 if ((attribute == xvSyncToVBlank) && VSYNC_POSSIBLE) {
218 if ((value < 0) || (value > 1)) 220 if ((value < 0) || (value > 1))
219 return BadValue; 221 return BadValue;
220 pPriv->SyncToVBlank = value; 222 pPriv->SyncToVBlank = value;
221 } else 223 } else
222 if (attribute == xvSetDefaults) { 224 if (attribute == xvSetDefaults) {
223 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 225 pPriv->SyncToVBlank = VSYNC_POSSIBLE;
224 } else 226 } else
225 return BadMatch; 227 return BadMatch;
226 228
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,
43 short src_w, short src_h, short drw_w, short drw_h, 43 short src_w, short src_h, short drw_w, short drw_h,
44 RegionPtr clipBoxes) 44 RegionPtr clipBoxes)
45{ 45{
46 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
47 NVPtr pNv = NVPTR(pScrn); 46 NVPtr pNv = NVPTR(pScrn);
48 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 47 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
48#if NVOVL_SUPPORT
49 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
49 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC]; 50 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC];
50 51
51 /*This may not work with NV04 overlay according to rivatv source*/ 52 /*This may not work with NV04 overlay according to rivatv source*/
@@ -103,6 +104,7 @@ NV04PutOverlayImage(ScrnInfoPtr pScrn, struct nouveau_bo *src, int offset,
103 nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, 0x111); 104 nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, 0x111);
104 105
105 nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, (nvReadVIDEO(pNv, NV_PVIDEO_SU_STATE) ^ (1 << 16))); 106 nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, (nvReadVIDEO(pNv, NV_PVIDEO_SU_STATE) ^ (1 << 16)));
107#endif
106 108
107 pPriv->videoStatus = CLIENT_VIDEO_ON; 109 pPriv->videoStatus = CLIENT_VIDEO_ON;
108} 110}
@@ -183,11 +185,13 @@ NV04GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
183void 185void
184NV04StopOverlay (ScrnInfoPtr pScrn) 186NV04StopOverlay (ScrnInfoPtr pScrn)
185{ 187{
188#ifdef NVOVL_SUPPORT
186 NVPtr pNv = NVPTR(pScrn); 189 NVPtr pNv = NVPTR(pScrn);
187 190
188 nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, nvReadVIDEO(pNv, NV_PVIDEO_OVERLAY) &~ 0x1); 191 nvWriteVIDEO(pNv, NV_PVIDEO_OVERLAY, nvReadVIDEO(pNv, NV_PVIDEO_OVERLAY) &~ 0x1);
189 nvWriteVIDEO(pNv, NV_PVIDEO_OE_STATE, 0); 192 nvWriteVIDEO(pNv, NV_PVIDEO_OE_STATE, 0);
190 nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, 0); 193 nvWriteVIDEO(pNv, NV_PVIDEO_SU_STATE, 0);
191 nvWriteVIDEO(pNv, NV_PVIDEO_RM_STATE, 0); 194 nvWriteVIDEO(pNv, NV_PVIDEO_RM_STATE, 0);
195#endif
192} 196}
193 197
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)
725 NVPtr pNv = NVPTR(pScrn); 725 NVPtr pNv = NVPTR(pScrn);
726 struct nouveau_channel *chan = pNv->chan; 726 struct nouveau_channel *chan = pNv->chan;
727 struct nouveau_grobj *celsius; 727 struct nouveau_grobj *celsius;
728 uint32_t class = 0, chipset; 728 uint32_t class = 0;
729 int i; 729 int i;
730 730
731 chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; 731 if (((pNv->NVArch & 0xf0) != NV_ARCH_10) &&
732 if (((chipset & 0xf0) != NV_ARCH_10) && ((chipset & 0xf0) != NV_ARCH_20)) 732 ((pNv->NVArch & 0xf0) != NV_ARCH_20))
733 return FALSE; 733 return FALSE;
734 734
735 if (chipset >= 0x20 || chipset == 0x1a) 735 if (pNv->NVArch >= 0x20 || pNv->NVArch == 0x1a)
736 class = NV11TCL; 736 class = NV11TCL;
737 else if (chipset >= 0x17) 737 else if (pNv->NVArch >= 0x17)
738 class = NV17TCL; 738 class = NV17TCL;
739 else if (chipset >= 0x11) 739 else if (pNv->NVArch >= 0x11)
740 class = NV11TCL; 740 class = NV11TCL;
741 else 741 else
742 class = NV10TCL; 742 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,
68{ 68{
69 NVPtr pNv = NVPTR(pScrn); 69 NVPtr pNv = NVPTR(pScrn);
70 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv); 70 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
71#ifdef NVOVL_SUPPORT
71 int buffer = pPriv->currentBuffer; 72 int buffer = pPriv->currentBuffer;
72 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); 73 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
73 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC]; 74 xf86CrtcPtr crtc = xf86_config->crtc[pPriv->overlayCRTC];
@@ -125,6 +126,7 @@ NV10PutOverlayImage(ScrnInfoPtr pScrn,
125 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch); 126 nvWriteVIDEO(pNv, NV_PVIDEO_FORMAT(buffer), dstPitch);
126 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0); 127 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 0);
127 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1); 128 nvWriteVIDEO(pNv, NV_PVIDEO_BUFFER, buffer ? 0x10 : 0x1);
129#endif
128 130
129 pPriv->videoStatus = CLIENT_VIDEO_ON; 131 pPriv->videoStatus = CLIENT_VIDEO_ON;
130} 132}
@@ -148,7 +150,6 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
148 INT32 value, pointer data) 150 INT32 value, pointer data)
149{ 151{
150 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 152 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
151 NVPtr pNv = NVPTR(pScrn);
152 153
153 if (attribute == xvBrightness) { 154 if (attribute == xvBrightness) {
154 if ((value < -512) || (value > 512)) 155 if ((value < -512) || (value > 512))
@@ -193,7 +194,10 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
193 if (attribute == xvSetDefaults) { 194 if (attribute == xvSetDefaults) {
194 NVSetPortDefaults(pScrn, pPriv); 195 NVSetPortDefaults(pScrn, pPriv);
195 } else 196 } else
197#ifdef NVOVL_SUPPORT
196 if ( attribute == xvOnCRTCNb) { 198 if ( attribute == xvOnCRTCNb) {
199 NVPtr pNv = NVPTR(pScrn);
200
197 if ((value < 0) || (value > 1)) 201 if ((value < 0) || (value > 1))
198 return BadValue; 202 return BadValue;
199 pPriv->overlayCRTC = value; 203 pPriv->overlayCRTC = value;
@@ -202,6 +206,7 @@ NV10SetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
202 NVWriteCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL, 206 NVWriteCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL,
203 NVReadCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL) & ~NV_CRTC_FSEL_OVERLAY); 207 NVReadCRTC(pNv, !value, NV_PCRTC_ENGINE_CTRL) & ~NV_CRTC_FSEL_OVERLAY);
204 } else 208 } else
209#endif
205 return BadMatch; 210 return BadMatch;
206 211
207 NV10WriteOverlayParameters(pScrn); 212 NV10WriteOverlayParameters(pScrn);
@@ -255,8 +260,10 @@ NV10GetOverlayPortAttribute(ScrnInfoPtr pScrn, Atom attribute,
255void 260void
256NV10StopOverlay (ScrnInfoPtr pScrn) 261NV10StopOverlay (ScrnInfoPtr pScrn)
257{ 262{
263#ifdef NVOVL_SUPPORT
258 NVPtr pNv = NVPTR(pScrn); 264 NVPtr pNv = NVPTR(pScrn);
259 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1); 265 nvWriteVIDEO(pNv, NV_PVIDEO_STOP, 1);
266#endif
260} 267}
261 268
262/** 269/**
@@ -281,6 +288,7 @@ NV10WriteOverlayParameters (ScrnInfoPtr pScrn)
281 if (satCosine < -1024) 288 if (satCosine < -1024)
282 satCosine = -1024; 289 satCosine = -1024;
283 290
291#ifdef NVOVL_SUPPORT
284 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) | 292 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(0), (pPriv->brightness << 16) |
285 pPriv->contrast); 293 pPriv->contrast);
286 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) | 294 nvWriteVIDEO(pNv, NV_PVIDEO_LUMINANCE(1), (pPriv->brightness << 16) |
@@ -290,6 +298,6 @@ NV10WriteOverlayParameters (ScrnInfoPtr pScrn)
290 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) | 298 nvWriteVIDEO(pNv, NV_PVIDEO_CHROMINANCE(1), (satSine << 16) |
291 (satCosine & 0xffff)); 299 (satCosine & 0xffff));
292 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey); 300 nvWriteVIDEO(pNv, NV_PVIDEO_COLOR_KEY, pPriv->colorKey);
293 301#endif
294} 302}
295 303
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)
679#define NV35TCL_CHIPSET_3X_MASK 0x000001e0 679#define NV35TCL_CHIPSET_3X_MASK 0x000001e0
680#define NV34TCL_CHIPSET_3X_MASK 0x00000010 680#define NV34TCL_CHIPSET_3X_MASK 0x00000010
681 681
682 chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; 682 chipset = pNv->NVArch;
683 if ((chipset & 0xf0) != NV_ARCH_30) 683 if ((chipset & 0xf0) != NV_ARCH_30)
684 return TRUE; 684 return TRUE;
685 chipset &= 0xf; 685 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,
430 INT32 value, pointer data) 430 INT32 value, pointer data)
431{ 431{
432 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 432 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
433 NVPtr pNv = NVPTR(pScrn);
434 433
435 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { 434 if (attribute == xvSyncToVBlank) {
436 if ((value < 0) || (value > 1)) 435 if ((value < 0) || (value > 1))
437 return BadValue; 436 return BadValue;
438 pPriv->SyncToVBlank = value; 437 pPriv->SyncToVBlank = value;
439 } else 438 } else
440 if (attribute == xvSetDefaults) { 439 if (attribute == xvSetDefaults) {
441 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 440 pPriv->SyncToVBlank = TRUE;
442 } else 441 } else
443 return BadMatch; 442 return BadMatch;
444 443
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)
612 if (!nv40_fp_map_a8[0]) 612 if (!nv40_fp_map_a8[0])
613 NV40EXAHackupA8Shaders(pScrn); 613 NV40EXAHackupA8Shaders(pScrn);
614 614
615 chipset = (nvReadMC(pNv, NV_PMC_BOOT_0) >> 20) & 0xff; 615 chipset = pNv->NVArch;
616
617 if ( (chipset & 0xf0) == NV_ARCH_40) { 616 if ( (chipset & 0xf0) == NV_ARCH_40) {
618 chipset &= 0xf; 617 chipset &= 0xf;
619 if (NV40TCL_CHIPSET_4X_MASK & (1<<chipset)) 618 if (NV40TCL_CHIPSET_4X_MASK & (1<<chipset))
diff --git a/src/nv40_xv_tex.c b/src/nv40_xv_tex.c
index 463b178..7679019 100644
--- a/src/nv40_xv_tex.c
+++ b/src/nv40_xv_tex.c
@@ -407,15 +407,14 @@ NV40SetTexturePortAttribute(ScrnInfoPtr pScrn, Atom attribute,
407 INT32 value, pointer data) 407 INT32 value, pointer data)
408{ 408{
409 NVPortPrivPtr pPriv = (NVPortPrivPtr)data; 409 NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
410 NVPtr pNv = NVPTR(pScrn);
411 410
412 if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) { 411 if (attribute == xvSyncToVBlank) {
413 if ((value < 0) || (value > 1)) 412 if ((value < 0) || (value > 1))
414 return BadValue; 413 return BadValue;
415 pPriv->SyncToVBlank = value; 414 pPriv->SyncToVBlank = value;
416 } else 415 } else
417 if (attribute == xvSetDefaults) { 416 if (attribute == xvSetDefaults) {
418 pPriv->SyncToVBlank = pNv->WaitVSyncPossible; 417 pPriv->SyncToVBlank = TRUE;
419 } else 418 } else
420 return BadMatch; 419 return BadMatch;
421 420
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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include "nouveau_modeset.h"
24#include "nouveau_crtc.h"
25#include "nouveau_output.h"
26#include "nouveau_connector.h"
27
28static xf86MonPtr
29NV50ConnectorGetEDID(nouveauConnectorPtr connector)
30{
31 ScrnInfoPtr pScrn = connector->scrn;
32 xf86MonPtr mon = NULL;
33
34#ifdef EDID_COMPLETE_RAWDATA
35 mon = xf86DoEEDID(pScrn->scrnIndex, connector->pDDCBus, TRUE);
36#else
37 mon = xf86DoEDID_DDC2(pScrn->scrnIndex, connector->pDDCBus);
38#endif
39
40 if (mon)
41 xf86DDCApplyQuirks(pScrn->scrnIndex, mon);
42
43 return mon;
44}
45
46static xf86MonPtr
47NV50ConnectorDDCDetect(nouveauConnectorPtr connector)
48{
49 ScrnInfoPtr pScrn = connector->scrn;
50 xf86MonPtr ddc_mon;
51
52 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50ConnectorDDCDetect is called.\n");
53
54 if (!connector->pDDCBus)
55 return FALSE;
56
57 ddc_mon = NV50ConnectorGetEDID(connector);
58
59 return ddc_mon;
60}
61
62static DisplayModePtr
63NV50ConnectorGetDDCModes(nouveauConnectorPtr connector)
64{
65 ScrnInfoPtr pScrn = connector->scrn;
66 xf86MonPtr ddc_mon;
67
68 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50ConnectorGetDDCModes is called.\n");
69
70 if (!connector->pDDCBus)
71 return FALSE;
72
73 ddc_mon = NV50ConnectorGetEDID(connector);
74 if (!ddc_mon)
75 return NULL;
76
77 return xf86DDCGetModes(pScrn->scrnIndex, ddc_mon);
78}
79
80void
81NV50ConnectorInit(ScrnInfoPtr pScrn)
82{
83 int i;
84 NVPtr pNv = NVPTR(pScrn);
85
86 /* Maybe a bit overdone, because often only 3 or 4 connectors are present. */
87 for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) {
88 nouveauConnectorPtr connector = xnfcalloc(sizeof(nouveauConnectorRec), 1);
89 connector->scrn = pScrn;
90 connector->index = i;
91
92 char connector_name[20];
93 sprintf(connector_name, "Connector-%d", i);
94 connector->name = xstrdup(connector_name);
95
96 /* Function pointers. */
97 connector->DDCDetect = NV50ConnectorDDCDetect;
98 connector->GetDDCModes = NV50ConnectorGetDDCModes;
99 connector->HotplugDetect = NULL;
100
101 pNv->connector[i] = connector;
102 }
103}
104
105void
106NV50ConnectorDestroy(ScrnInfoPtr pScrn)
107{
108 int i;
109 NVPtr pNv = NVPTR(pScrn);
110
111 /* Maybe a bit overdone, because often only 3 or 4 connectors are present. */
112 for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) {
113 nouveauConnectorPtr connector = pNv->connector[i];
114
115 if (!connector)
116 continue;
117
118 xfree(connector->name);
119 xfree(connector);
120 pNv->connector[i] = NULL;
121 }
122}
123
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 @@
1/*
2 * Copyright 2007 NVIDIA, Corporation
3 * Copyright 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "nouveau_modeset.h"
25#include "nouveau_crtc.h"
26#include "nouveau_output.h"
27#include "nouveau_connector.h"
28
29/* Check if the card wants us to update the any of the video clocks.
30 * Maybe it would be enough to check only after method 0x80? */
31static void
32NV50CheckWriteVClk(ScrnInfoPtr pScrn)
33{
34 NVPtr pNv = NVPTR(pScrn);
35 int t_start = GetTimeInMillis();
36
37 while (NVRead(pNv, NV50_DISPLAY_CTRL_STATE) & NV50_DISPLAY_CTRL_STATE_PENDING) {
38 /* An educated guess. */
39 const uint32_t supervisor = NVRead(pNv, NV50_DISPLAY_SUPERVISOR);
40
41 if ((GetTimeInMillis() - t_start) > 5000) {
42 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "NV50CheckWriteVClk() timed out.\n");
43 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "A reboot is probably required now.\n");
44 break;
45 }
46
47 /* Simply acknowledge it, maybe we should do more? */
48 if (supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn) {
49 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, supervisor & NV50_DISPLAY_SUPERVISOR_CRTCn);
50 }
51
52 if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) {
53 if (supervisor & NV50_DISPLAY_SUPERVISOR_CLK_UPDATE) {
54 const uint32_t clockvar = NVRead(pNv, NV50_DISPLAY_UNK30_CTRL);
55 int i;
56
57 for(i = 0; i < 2; i++) {
58 nouveauCrtcPtr crtc = pNv->crtc[i];
59 uint32_t mask = 0;
60
61 if (crtc->index == 1)
62 mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK1;
63 else
64 mask = NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK0;
65
66 if (clockvar & mask)
67 crtc->SetPixelClock(crtc, crtc->pixel_clock);
68 /* Always do something if the supervisor wants a clock change. */
69 /* This is needed because you get a deadlock if you don't kick the NV50_CRTC0_CLK_CTRL2 register. */
70 if (crtc->modeset_lock) {
71 crtc->SetClockMode(crtc, crtc->pixel_clock);
72
73 nouveauOutputPtr output;
74 for (output = pNv->output; output != NULL; output = output->next) {
75 if (output->crtc == crtc)
76 output->SetClockMode(output, crtc->pixel_clock);
77 }
78 }
79 }
80 }
81
82 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 1 << (ffs(supervisor & NV50_DISPLAY_SUPERVISOR_CLK_MASK) - 1));
83 NVWrite(pNv, NV50_DISPLAY_UNK30_CTRL, NV50_DISPLAY_UNK30_CTRL_PENDING);
84 }
85 }
86}
87
88void NV50DisplayCommand(ScrnInfoPtr pScrn, uint32_t addr, uint32_t value)
89{
90 DDXMMIOH("NV50DisplayCommand: head %d addr 0x%X value 0x%X\n", 0, addr, value);
91 NVPtr pNv = NVPTR(pScrn);
92 NVWrite(pNv, NV50_DISPLAY_CTRL_VAL, value);
93 NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, addr | 0x10000 | NV50_DISPLAY_CTRL_STATE_ENABLE | NV50_DISPLAY_CTRL_STATE_PENDING);
94 NV50CheckWriteVClk(pScrn);
95}
96
97void NV50CrtcCommand(nouveauCrtcPtr crtc, uint32_t addr, uint32_t value)
98{
99 ScrnInfoPtr pScrn = crtc->scrn;
100
101 /* This head dependent offset is only for crtc commands. */
102 NV50DisplayCommand(pScrn, addr + 0x400 * crtc->index, value);
103}
104
105static Bool
106NV50CrtcModeValid(nouveauCrtcPtr crtc, DisplayModePtr mode)
107{
108 return TRUE;
109}
110
111static void
112NV50CrtcModeSet(nouveauCrtcPtr crtc, DisplayModePtr mode)
113{
114 ScrnInfoPtr pScrn = crtc->scrn;
115 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcModeSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
116
117 /* Anyone know a more appropriate name? */
118 DisplayModePtr desired_mode = crtc->use_native_mode ? crtc->native_mode : mode;
119
120 /* Save the pixel clock for posterity. */
121 crtc->pixel_clock = desired_mode->Clock;
122 crtc->cur_mode = mode;
123
124 uint32_t hsync_dur = desired_mode->CrtcHSyncEnd - desired_mode->CrtcHSyncStart;
125 uint32_t vsync_dur = desired_mode->CrtcVSyncEnd - desired_mode->CrtcVSyncStart;
126 uint32_t hsync_start_to_end = desired_mode->CrtcHBlankEnd - desired_mode->CrtcHSyncStart;
127 uint32_t vsync_start_to_end = desired_mode->CrtcVBlankEnd - desired_mode->CrtcVSyncStart;
128 /* I can't give this a proper name, anyone else can? */
129 uint32_t hunk1 = desired_mode->CrtcHTotal - desired_mode->CrtcHSyncStart + desired_mode->CrtcHBlankStart;
130 uint32_t vunk1 = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart;
131 /* Another strange value, this time only for interlaced modes. */
132 uint32_t vunk2a = 2*desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankStart;
133 uint32_t vunk2b = desired_mode->CrtcVTotal - desired_mode->CrtcVSyncStart + desired_mode->CrtcVBlankEnd;
134
135 if (desired_mode->Flags & V_INTERLACE) {
136 vsync_dur /= 2;
137 vsync_start_to_end /= 2;
138 vunk1 /= 2;
139 vunk2a /= 2;
140 vunk2b /= 2;
141 /* magic */
142 if (desired_mode->Flags & V_DBLSCAN) {
143 vsync_start_to_end -= 1;
144 vunk1 -= 1;
145 vunk2a -= 1;
146 vunk2b -= 1;
147 }
148 }
149
150 /* NV50CrtcCommand includes head offset */
151 /* This is the native mode when DFP && !SCALE_PANEL */
152 NV50CrtcCommand(crtc, NV50_CRTC0_CLOCK, desired_mode->Clock | 0x800000);
153 NV50CrtcCommand(crtc, NV50_CRTC0_INTERLACE, (desired_mode->Flags & V_INTERLACE) ? 2 : 0);
154 NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_START, 0);
155 NV50CrtcCommand(crtc, NV50_CRTC0_UNK82C, 0);
156 NV50CrtcCommand(crtc, NV50_CRTC0_DISPLAY_TOTAL, desired_mode->CrtcVTotal << 16 | desired_mode->CrtcHTotal);
157 NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_DURATION, (vsync_dur - 1) << 16 | (hsync_dur - 1));
158 NV50CrtcCommand(crtc, NV50_CRTC0_SYNC_START_TO_BLANK_END, (vsync_start_to_end - 1) << 16 | (hsync_start_to_end - 1));
159 NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK1, (vunk1 - 1) << 16 | (hunk1 - 1));
160 if (desired_mode->Flags & V_INTERLACE) {
161 NV50CrtcCommand(crtc, NV50_CRTC0_MODE_UNK2, (vunk2b - 1) << 16 | (vunk2a - 1));
162 }
163 NV50CrtcCommand(crtc, NV50_CRTC0_FB_SIZE, pScrn->virtualY << 16 | pScrn->virtualX);
164
165 /* Maybe move this calculation elsewhere? */
166 crtc->fb_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
167 NV50CrtcCommand(crtc, NV50_CRTC0_FB_PITCH, crtc->fb_pitch | 0x100000);
168
169 switch (pScrn->depth) {
170 case 8:
171 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_8BPP);
172 break;
173 case 15:
174 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_15BPP);
175 break;
176 case 16:
177 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_16BPP);
178 break;
179 case 24:
180 NV50CrtcCommand(crtc, NV50_CRTC0_DEPTH, NV50_CRTC0_DEPTH_24BPP);
181 break;
182 }
183 crtc->SetDither(crtc);
184 NV50CrtcCommand(crtc, NV50_CRTC0_COLOR_CTRL, NV50_CRTC_COLOR_CTRL_MODE_COLOR);
185 NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, (crtc->y << 16) | (crtc->x));
186 /* This is the actual resolution of the mode. */
187 NV50CrtcCommand(crtc, NV50_CRTC0_REAL_RES, (mode->VDisplay << 16) | mode->HDisplay);
188 NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CENTER_OFFSET, NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0));
189
190 /* Maybe move this as well? */
191 crtc->Blank(crtc, FALSE);
192}
193
194static void
195NV50CrtcSetPixelClock(nouveauCrtcPtr crtc, int clock)
196{
197 ScrnInfoPtr pScrn = crtc->scrn;
198 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetPixelClock is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
199
200 NVPtr pNv = NVPTR(pScrn);
201
202 /* I don't know why exactly, but these were in my table. */
203 uint32_t pll_reg = crtc->index ? NV50_CRTC1_CLK_CTRL1 : NV50_CRTC0_CLK_CTRL1;
204 struct pll_lims pll_lim;
205 struct nouveau_pll_vals pllvals;
206
207 get_pll_limits(pScrn, pll_reg, &pll_lim);
208
209 /* NV5x hardware doesn't seem to support a single vco mode, otherwise the blob is hiding it well. */
210 if (!nouveau_calc_pll_mnp(pScrn, &pll_lim, clock, &pllvals))
211 return;
212
213 uint32_t reg1 = NVRead(pNv, pll_reg + 4);
214 uint32_t reg2 = NVRead(pNv, pll_reg + 8);
215
216 /* bit0: The blob (and bios) seem to have this on (almost) always.
217 * I'm hoping this (experiment) will fix my image stability issues.
218 */
219 NVWrite(pNv, NV50_CRTC0_CLK_CTRL1 + crtc->index * 0x800, NV50_CRTC_CLK_CTRL1_CONNECTED | 0x10000011);
220
221 /* Eventually we should learn ourselves what all the bits should be. */
222 reg1 &= 0xff00ff00;
223 reg2 &= 0x8000ff00;
224
225 reg1 |= (pllvals.M1 << 16) | pllvals.N1;
226 reg2 |= (pllvals.log2P << 28) | (pllvals.M2 << 16) | pllvals.N2;
227
228 NVWrite(pNv, pll_reg + 4, reg1);
229 NVWrite(pNv, pll_reg + 8, reg2);
230}
231
232static void
233NV50CrtcSetClockMode(nouveauCrtcPtr crtc, int clock)
234{
235 ScrnInfoPtr pScrn = crtc->scrn;
236 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetClockMode is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
237
238 NVPtr pNv = NVPTR(pScrn);
239
240 /* There seem to be a few indicator bits, which are similar to the SOR_CTRL bits. */
241 NVWrite(pNv, NV50_CRTC0_CLK_CTRL2 + crtc->index * 0x800, 0);
242}
243
244static void
245NV50CrtcSetFB(nouveauCrtcPtr crtc, struct nouveau_bo * buffer)
246{
247 if (crtc->front_buffer)
248 nouveau_bo_unpin(crtc->front_buffer);
249
250 /* For the moment the actual hardware settings stays in ModeSet(). */
251 nouveau_bo_pin(buffer, NOUVEAU_BO_VRAM);
252 crtc->front_buffer = buffer;
253}
254
255static void
256NV50CrtcSetFBOffset(nouveauCrtcPtr crtc, uint32_t x, uint32_t y)
257{
258 crtc->x = x;
259 crtc->y = y;
260
261 NV50CrtcCommand(crtc, NV50_CRTC0_FB_POS, (crtc->y << 16) | (crtc->x));
262}
263
264static void
265NV50CrtcBlank(nouveauCrtcPtr crtc, Bool blanked)
266{
267 ScrnInfoPtr pScrn = crtc->scrn;
268 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcBlank is called (%s) for %s.\n", blanked ? "blanked" : "unblanked", crtc->index ? "CRTC1" : "CRTC0");
269
270 NVPtr pNv = NVPTR(pScrn);
271
272 if (blanked) {
273 crtc->HideCursor(crtc, TRUE);
274
275 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE, NV50_CRTC0_CLUT_MODE_BLANK);
276 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, 0);
277 if (pNv->NVArch != 0x50)
278 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_BLANK);
279 NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
280 if (pNv->NVArch != 0x50)
281 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_BLANK);
282 } else {
283 struct nouveau_device *dev = crtc->front_buffer->device;
284 uint32_t fb = crtc->front_buffer->offset - dev->vm_vram_base;
285 uint32_t clut = crtc->lut->offset - dev->vm_vram_base;
286 uint32_t cursor;
287
288 if (crtc->index)
289 cursor = pNv->Cursor2->offset - dev->vm_vram_base;
290 else
291 cursor = pNv->Cursor->offset - dev->vm_vram_base;
292
293 NV50CrtcCommand(crtc, NV50_CRTC0_FB_OFFSET, fb >> 8);
294 NV50CrtcCommand(crtc, 0x864, 0);
295 NVWrite(pNv, NV50_DISPLAY_UNK_380, 0);
296 /* RAM is clamped to 256 MiB. */
297 NVWrite(pNv, NV50_DISPLAY_RAM_AMOUNT, pNv->RamAmountKBytes * 1024 - 1);
298 NVWrite(pNv, NV50_DISPLAY_UNK_388, 0x150000);
299 NVWrite(pNv, NV50_DISPLAY_UNK_38C, 0);
300 NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_OFFSET, cursor >> 8);
301 if(pNv->NVArch != 0x50)
302 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK2, NV84_CRTC0_BLANK_UNK2_UNBLANK);
303
304 if (crtc->cursor_visible)
305 crtc->ShowCursor(crtc, TRUE);
306
307 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_MODE,
308 pScrn->depth == 8 ? NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON);
309 /* Each CRTC has it's own CLUT. */
310 NV50CrtcCommand(crtc, NV50_CRTC0_CLUT_OFFSET, clut >> 8);
311 if (pNv->NVArch != 0x50)
312 NV50CrtcCommand(crtc, NV84_CRTC0_BLANK_UNK1, NV84_CRTC0_BLANK_UNK1_UNBLANK);
313 NV50CrtcCommand(crtc, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_UNBLANK);
314 }
315
316 crtc->blanked = blanked;
317}
318
319static void
320NV50CrtcSetDither(nouveauCrtcPtr crtc)
321{
322 ScrnInfoPtr pScrn = crtc->scrn;
323 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetDither is called (%s).\n", !crtc->modeset_lock ? "update" : "no update");
324
325 NV50CrtcCommand(crtc, NV50_CRTC0_DITHERING_CTRL, crtc->dithering ?
326 NV50_CRTC0_DITHERING_CTRL_ON : NV50_CRTC0_DITHERING_CTRL_OFF);
327
328 if (!crtc->modeset_lock)
329 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
330}
331
332static void
333ComputeAspectScale(DisplayModePtr mode, DisplayModePtr adjusted_mode, int *outX, int *outY)
334{
335 float scaleX, scaleY, scale;
336
337 scaleX = adjusted_mode->HDisplay / (float)mode->HDisplay;
338 scaleY = adjusted_mode->VDisplay / (float)mode->VDisplay;
339
340 if (scaleX > scaleY)
341 scale = scaleY;
342 else
343 scale = scaleX;
344
345 *outX = mode->HDisplay * scale;
346 *outY = mode->VDisplay * scale;
347}
348
349static void
350NV50CrtcSetScaleMode(nouveauCrtcPtr crtc, int scale)
351{
352 ScrnInfoPtr pScrn = crtc->scrn;
353 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcSetScale is called with mode %d for %s.\n", scale, crtc->index ? "CRTC1" : "CRTC0");
354
355 uint32_t scale_val = 0;
356 int outX = 0, outY = 0;
357
358 switch(scale) {
359 case SCALE_ASPECT:
360 ComputeAspectScale(crtc->cur_mode, crtc->native_mode, &outX, &outY);
361 break;
362 case SCALE_FULLSCREEN:
363 outX = crtc->native_mode->HDisplay;
364 outY = crtc->native_mode->VDisplay;
365 break;
366 case SCALE_NOSCALE:
367 case SCALE_PANEL:
368 default:
369 outX = crtc->cur_mode->HDisplay;
370 outY = crtc->cur_mode->VDisplay;
371 break;
372 }
373
374 /* Got a better name for SCALER_ACTIVE? */
375 if ((crtc->cur_mode->Flags & V_DBLSCAN) || (crtc->cur_mode->Flags & V_INTERLACE) ||
376 crtc->cur_mode->HDisplay != outX || crtc->cur_mode->VDisplay != outY) {
377 scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_ACTIVE;
378 } else {
379 scale_val = NV50_CRTC0_SCALE_CTRL_SCALER_INACTIVE;
380 }
381
382 NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_CTRL, scale_val);
383 NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES1, outY << 16 | outX);
384 NV50CrtcCommand(crtc, NV50_CRTC0_SCALE_RES2, outY << 16 | outX);
385}
386
387/*
388 * Cursor stuff.
389 */
390
391static void
392NV50CrtcShowCursor(nouveauCrtcPtr crtc, Bool forced_lock)
393{
394 ScrnInfoPtr pScrn = crtc->scrn;
395 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcShowCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
396
397 if (!crtc->modeset_lock)
398 crtc->cursor_visible = TRUE;
399
400 NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_SHOW);
401
402 /* Calling this during modeset will lock things up. */
403 if (!crtc->modeset_lock && !forced_lock)
404 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
405}
406
407static void
408NV50CrtcHideCursor(nouveauCrtcPtr crtc, Bool forced_lock)
409{
410 ScrnInfoPtr pScrn = crtc->scrn;
411 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcHideCursor is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
412
413 if (!crtc->modeset_lock)
414 crtc->cursor_visible = FALSE;
415
416 NV50CrtcCommand(crtc, NV50_CRTC0_CURSOR_CTRL, NV50_CRTC0_CURSOR_CTRL_HIDE);
417
418 /* Calling this during modeset will lock things up. */
419 if (!crtc->modeset_lock && !forced_lock)
420 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
421}
422
423static void
424NV50CrtcSetCursorPosition(nouveauCrtcPtr crtc, int x, int y)
425{
426 ScrnInfoPtr pScrn = crtc->scrn;
427 NVPtr pNv = NVPTR(pScrn);
428 NVWrite(pNv, NV50_CRTC0_CURSOR_POS + crtc->index * 0x1000, (y & 0xFFFF) << 16 | (x & 0xFFFF));
429
430 /* This is needed to allow the cursor to move. */
431 NVWrite(pNv, NV50_CRTC0_CURSOR_POS_CTRL + crtc->index * 0x1000, 0);
432}
433
434static void
435NV50CrtcLoadCursor(nouveauCrtcPtr crtc, Bool argb, uint32_t *src)
436{
437 NVPtr pNv = NVPTR(crtc->scrn);
438 struct nouveau_bo *cursor = NULL;
439
440 if (!argb) /* FIXME */
441 return;
442
443 nouveau_bo_ref(crtc->index ? pNv->Cursor2 : pNv->Cursor, &cursor);
444 nouveau_bo_map(cursor, NOUVEAU_BO_WR);
445 /* Assume cursor is 64x64 */
446 memcpy(cursor->map, src, 64 * 64 * 4);
447 nouveau_bo_unmap(cursor);
448}
449
450/*
451 * Gamma stuff.
452 */
453
454/*
455 * The indices are a bit strange, but i'll assume it's correct (taken from nv).
456 * The LUT resolution seems to be 14 bits on NV50 as opposed to the 8 bits of previous hardware.
457 */
458static void
459NV50CrtcGammaSet(nouveauCrtcPtr crtc, uint16_t *red, uint16_t *green, uint16_t *blue, int size)
460{
461 ScrnInfoPtr pScrn = crtc->scrn;
462 uint32_t i;
463
464 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50CrtcGammaSet is called for %s.\n", crtc->index ? "CRTC1" : "CRTC0");
465
466 for (i = 0; i < 256; i++) {
467 crtc->lut_values[i].red = red[i] >> 2;
468 crtc->lut_values[i].green = green[i] >> 2;
469 crtc->lut_values[i].blue = blue[i] >> 2;
470 }
471
472 crtc->lut_values_valid = true;
473
474 /* This is pre-init, we don't have access to the lut bo now. */
475 if (!crtc->lut)
476 return;
477
478 nouveau_bo_map(crtc->lut, NOUVEAU_BO_WR);
479 memcpy(crtc->lut->map, crtc->lut_values, 4*256*sizeof(uint16_t));
480 nouveau_bo_unmap(crtc->lut);
481}
482
483void
484NV50CrtcInit(ScrnInfoPtr pScrn)
485{
486 int i;
487 NVPtr pNv = NVPTR(pScrn);
488
489 for (i=0; i < 2; i++) {
490 nouveauCrtcPtr crtc = xnfcalloc(sizeof(nouveauCrtcRec), 1);
491 crtc->scrn = pScrn;
492 crtc->index = i;
493
494 /* Function pointers. */
495 crtc->ModeValid = NV50CrtcModeValid;
496 crtc->ModeSet = NV50CrtcModeSet;
497 crtc->SetPixelClock = NV50CrtcSetPixelClock;
498 crtc->SetClockMode = NV50CrtcSetClockMode;
499
500 crtc->SetFB = NV50CrtcSetFB;
501 crtc->SetFBOffset = NV50CrtcSetFBOffset;
502
503 crtc->Blank = NV50CrtcBlank;
504 crtc->SetDither = NV50CrtcSetDither;
505
506 crtc->SetScaleMode = NV50CrtcSetScaleMode;
507
508 crtc->ShowCursor = NV50CrtcShowCursor;
509 crtc->HideCursor = NV50CrtcHideCursor;
510 crtc->SetCursorPosition = NV50CrtcSetCursorPosition;
511 crtc->LoadCursor = NV50CrtcLoadCursor;
512
513 crtc->GammaSet = NV50CrtcGammaSet;
514
515 pNv->crtc[i] = crtc;
516 }
517}
518
519void
520NV50CrtcDestroy(ScrnInfoPtr pScrn)
521{
522 int i;
523 NVPtr pNv = NVPTR(pScrn);
524
525 for (i=0; i < 2; i++) {
526 nouveauCrtcPtr crtc = pNv->crtc[i];
527
528 if (!crtc)
529 continue;
530
531 xfree(crtc->name);
532 xfree(crtc);
533 pNv->crtc[i] = NULL;
534 }
535}
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 @@
1/*
2 * Copyright (c) 2007 NVIDIA, Corporation
3 * Copyright (c) 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <string.h>
26
27#include <cursorstr.h>
28
29#include "nv_include.h"
30
31Bool NV50CursorAcquire(ScrnInfoPtr pScrn)
32{
33 NVPtr pNv = NVPTR(pScrn);
34 int i;
35
36 if (!pNv->HWCursor) return TRUE;
37
38 /* Initialize the cursor on each head */
39 for (i = 0; i < 2; i++) {
40 nouveauCrtcPtr crtc = pNv->crtc[i];
41 const int headOff = 0x10 * crtc->index;
42
43 NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, 0x2000);
44 while (NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK);
45
46 NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, NV50_CRTC_CURSOR_CTRL2_ON);
47 while ((NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK) != NV50_CRTC_CURSOR_CTRL2_STATUS_ACTIVE);
48 }
49
50 return TRUE;
51}
52
53void NV50CursorRelease(ScrnInfoPtr pScrn)
54{
55 NVPtr pNv = NVPTR(pScrn);
56 int i;
57
58 if (!pNv->HWCursor) return;
59
60 /* Release the cursor on each head */
61 for (i = 0; i < 2; i++) {
62 nouveauCrtcPtr crtc = pNv->crtc[i];
63 const int headOff = 0x10 * crtc->index;
64
65 NVWrite(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff, NV50_CRTC_CURSOR_CTRL2_OFF);
66 while (NVRead(pNv, NV50_CRTC0_CURSOR_CTRL2 + headOff) & NV50_CRTC_CURSOR_CTRL2_STATUS_MASK);
67 }
68}
69
70Bool NV50CursorInit(ScreenPtr pScreen)
71{
72 return xf86_cursors_init(pScreen, 64, 64,
73 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
74 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
75 HARDWARE_CURSOR_ARGB);
76}
77
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 @@
1/*
2 * Copyright 2007 NVIDIA, Corporation
3 * Copyright 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "nouveau_modeset.h"
25#include "nouveau_crtc.h"
26#include "nouveau_output.h"
27#include "nouveau_connector.h"
28
29static int
30NV50DacModeValid(nouveauOutputPtr output, DisplayModePtr mode)
31{
32 if (mode->Clock > 400000)
33 return MODE_CLOCK_HIGH;
34
35 if (mode->Clock < 25000)
36 return MODE_CLOCK_LOW;
37
38 return MODE_OK;
39}
40
41static void
42NV50DacModeSet(nouveauOutputPtr output, DisplayModePtr mode)
43{
44 ScrnInfoPtr pScrn = output->scrn;
45 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacModeSet is called.\n");
46
47 const int dacOff = 0x80 * NV50OrOffset(output);
48 uint32_t mode_ctl = NV50_DAC_MODE_CTRL_OFF;
49 uint32_t mode_ctl2 = 0;
50
51 if (!mode) {
52 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting DAC.\n");
53 NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl);
54 return;
55 }
56
57 /* Anyone know a more appropriate name? */
58 DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode;
59
60 if (output->crtc) {
61 if (output->crtc->index == 1)
62 mode_ctl |= NV50_DAC_MODE_CTRL_CRTC1;
63 else
64 mode_ctl |= NV50_DAC_MODE_CTRL_CRTC0;
65 } else {
66 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n");
67 return;
68 }
69
70 if (output->type == OUTPUT_ANALOG) {
71 /* What is this? */
72 mode_ctl |= 0x40;
73 } else if (output->type == OUTPUT_TV) {
74 mode_ctl |= 0x100;
75 }
76
77 if (desired_mode->Flags & V_NHSYNC)
78 mode_ctl2 |= NV50_DAC_MODE_CTRL2_NHSYNC;
79
80 if (desired_mode->Flags & V_NVSYNC)
81 mode_ctl2 |= NV50_DAC_MODE_CTRL2_NVSYNC;
82
83 // This wouldn't be necessary, but the server is stupid and calls
84 // nv50_dac_dpms after the output is disconnected, even though the hardware
85 // turns it off automatically.
86 output->SetPowerMode(output, DPMSModeOn);
87
88 NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL + dacOff, mode_ctl);
89
90 NV50DisplayCommand(pScrn, NV50_DAC0_MODE_CTRL2 + dacOff, mode_ctl2);
91
92 output->crtc->SetScaleMode(output->crtc, output->scale_mode);
93}
94
95static void
96NV50DacSetClockMode(nouveauOutputPtr output, int clock)
97{
98 ScrnInfoPtr pScrn = output->scrn;
99 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetClockMode is called.\n");
100
101 NVPtr pNv = NVPTR(pScrn);
102 NVWrite(pNv, NV50_DAC0_CLK_CTRL2 + NV50OrOffset(output) * 0x800, 0);
103}
104
105static int
106NV50DacSense(nouveauOutputPtr output)
107{
108 switch (output->type) {
109 case OUTPUT_ANALOG:
110 case OUTPUT_TV:
111 return output->type;
112 default:
113 return OUTPUT_NONE;
114 }
115}
116
117static Bool
118NV50DacDetect (nouveauOutputPtr output)
119{
120 ScrnInfoPtr pScrn = output->scrn;
121 NVPtr pNv = NVPTR(pScrn);
122 const int scrnIndex = pScrn->scrnIndex;
123 int sigstate;
124 uint32_t load, dactestval, tmp;
125
126 NVWrite(pNv, NV50_DAC0_CLK_CTRL1 + NV50OrOffset(output) * 0x800, 0x00000001);
127 tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
128
129 NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
130 while (NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING);
131
132 dactestval = 340;
133 if (pNv->vbios->dactestval) {
134 dactestval = pNv->vbios->dactestval;
135 xf86DrvMsg(scrnIndex, X_INFO, "Using bios provided load value of %d\n", dactestval);
136 } else {
137 xf86DrvMsg(scrnIndex, X_INFO, "Using default load value of %d\n", dactestval);
138 }
139
140 NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, dactestval | NV50_DAC_LOAD_CTRL_ACTIVE);
141 /* Why is this needed, load detect is almost instantanious and seemingly reliable for me. */
142 sigstate = xf86BlockSIGIO();
143 usleep(45000);
144 xf86UnblockSIGIO(sigstate);
145 load = NVRead(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800);
146 NVWrite(pNv, NV50_DAC0_LOAD_CTRL + NV50OrOffset(output) * 0x800, 0);
147 NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, NV50_DAC_DPMS_CTRL_PENDING | tmp);
148
149 // Use this DAC if all three channels show load.
150 if ((load & NV50_DAC_LOAD_CTRL_PRESENT) == NV50_DAC_LOAD_CTRL_PRESENT) {
151 xf86DrvMsg(scrnIndex, X_PROBED, "Load present on DAC-%i\n", NV50OrOffset(output));
152 return TRUE;
153 }
154
155 xf86DrvMsg(scrnIndex, X_PROBED, "No Load present on DAC-%i\n", NV50OrOffset(output));
156 return FALSE;
157}
158
159static void
160NV50DacSetPowerMode(nouveauOutputPtr output, int mode)
161{
162 ScrnInfoPtr pScrn = output->scrn;
163 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacSetPowerMode is called with mode %d.\n", mode);
164
165 uint32_t tmp;
166 NVPtr pNv = NVPTR(pScrn);
167
168 /*
169 * DPMSModeOn everything on
170 * DPMSModeStandby hsync disabled, vsync enabled
171 * DPMSModeSuspend hsync enabled, vsync disabled
172 * DPMSModeOff sync disabled
173 */
174 while(NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_DAC_DPMS_CTRL_PENDING);
175
176 tmp = NVRead(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
177 tmp &= ~0x7f;
178 tmp |= NV50_DAC_DPMS_CTRL_PENDING;
179
180 if (mode == DPMSModeStandby || mode == DPMSModeOff)
181 tmp |= NV50_DAC_DPMS_CTRL_HSYNC_OFF;
182 if (mode == DPMSModeSuspend || mode == DPMSModeOff)
183 tmp |= NV50_DAC_DPMS_CTRL_VSYNC_OFF;
184 if (mode != DPMSModeOn)
185 tmp |= NV50_DAC_DPMS_CTRL_BLANKED;
186 if (mode == DPMSModeOff)
187 tmp |= NV50_DAC_DPMS_CTRL_OFF;
188
189 NVWrite(pNv, NV50_DAC0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp);
190}
191
192static nouveauCrtcPtr
193NV50DacGetCurrentCrtc(nouveauOutputPtr output)
194{
195 ScrnInfoPtr pScrn = output->scrn;
196 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DacGetCurrentCrtc is called.\n");
197
198 NVPtr pNv = NVPTR(pScrn);
199 uint32_t mode_ctrl = NVRead(pNv, NV50_DAC0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8);
200
201 /*
202 * MODE_CTRL values only contain one instance of crtc0 and of crtc1.
203 * This is because we disconnect outputs upon modeset.
204 * Crtc might be off even if we get a positive return.
205 * But we are still associated with that crtc.
206 */
207 if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC0)
208 return pNv->crtc[0];
209 else if (mode_ctrl & NV50_DAC_MODE_CTRL_CRTC1)
210 return pNv->crtc[1];
211
212 return NULL;
213}
214
215void
216NV50DacSetFunctionPointers(nouveauOutputPtr output)
217{
218 output->ModeValid = NV50DacModeValid;
219 output->ModeSet = NV50DacModeSet;
220 output->SetClockMode = NV50DacSetClockMode;
221 output->Sense = NV50DacSense;
222 output->Detect = NV50DacDetect;
223 output->SetPowerMode = NV50DacSetPowerMode;
224 output->GetCurrentCrtc = NV50DacGetCurrentCrtc;
225}
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 @@
1/*
2 * Copyright (c) 2007 NVIDIA, Corporation
3 * Copyright (c) 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <float.h>
26#include <math.h>
27#include <strings.h>
28#include <unistd.h>
29
30#include "nv_include.h"
31
32Bool
33NV50DispPreInit(ScrnInfoPtr pScrn)
34{
35 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispPreInit is called.\n");
36
37 NVPtr pNv = NVPTR(pScrn);
38 /*
39 * I get the strange feeling that the 0x006101XX range is some kind of master modesetting control.
40 * Maybe this what triggers it to be enabled.
41 */
42 NVWrite(pNv, 0x00610184, NVRead(pNv, 0x00614004));
43 /* CRTC related? */
44 NVWrite(pNv, 0x00610190 + 0 * 0x10, NVRead(pNv, 0x00616100 + 0 * 0x800));
45 NVWrite(pNv, 0x00610190 + 1 * 0x10, NVRead(pNv, 0x00616100 + 1 * 0x800));
46 NVWrite(pNv, 0x00610194 + 0 * 0x10, NVRead(pNv, 0x00616104 + 0 * 0x800));
47 NVWrite(pNv, 0x00610194 + 1 * 0x10, NVRead(pNv, 0x00616104 + 1 * 0x800));
48 NVWrite(pNv, 0x00610198 + 0 * 0x10, NVRead(pNv, 0x00616108 + 0 * 0x800));
49 NVWrite(pNv, 0x00610198 + 1 * 0x10, NVRead(pNv, 0x00616108 + 1 * 0x800));
50 NVWrite(pNv, 0x0061019c + 0 * 0x10, NVRead(pNv, 0x0061610c + 0 * 0x800));
51 NVWrite(pNv, 0x0061019c + 1 * 0x10, NVRead(pNv, 0x0061610c + 1 * 0x800));
52 NVWrite(pNv, 0x006101d0 + DAC0 * 0x4, NVRead(pNv, 0x0061a000 + DAC0 * 0x800));
53 NVWrite(pNv, 0x006101d0 + DAC1 * 0x4, NVRead(pNv, 0x0061a000 + DAC1 * 0x800));
54 NVWrite(pNv, 0x006101d0 + DAC2 * 0x4, NVRead(pNv, 0x0061a000 + DAC2 * 0x800));
55 NVWrite(pNv, 0x006101e0 + SOR0 * 0x4, NVRead(pNv, 0x0061c000 + SOR0 * 0x800));
56 NVWrite(pNv, 0x006101e0 + SOR1 * 0x4, NVRead(pNv, 0x0061c000 + SOR1 * 0x800));
57 NVWrite(pNv, 0x006101e0 + SOR2 * 0x4, NVRead(pNv, 0x0061c000 + SOR2 * 0x800));
58 /* Maybe TV-out related, or something more generic? */
59 /* These are not in nv, so it must be something nv does not use. */
60 NVWrite(pNv, 0x006101f0 + 0 * 0x4, NVRead(pNv, 0x0061e000 + 0 * 0x800));
61 NVWrite(pNv, 0x006101f0 + 1 * 0x4, NVRead(pNv, 0x0061e000 + 1 * 0x800));
62 NVWrite(pNv, 0x006101f0 + 2 * 0x4, NVRead(pNv, 0x0061e000 + 2 * 0x800));
63 /* 0x00150000 seems to be the default state on many cards. why the extra bit is needed on some is unknown. */
64 NVWrite(pNv, NV50_DAC0_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
65 NVWrite(pNv, NV50_DAC0_CLK_CTRL1, 0x00000001);
66 NVWrite(pNv, NV50_DAC1_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
67 NVWrite(pNv, NV50_DAC1_CLK_CTRL1, 0x00000001);
68 NVWrite(pNv, NV50_DAC2_DPMS_CTRL, 0x00400000 | NV50_DAC_DPMS_CTRL_DEFAULT_STATE | NV50_DAC_DPMS_CTRL_PENDING);
69 NVWrite(pNv, NV50_DAC2_CLK_CTRL1, 0x00000001);
70
71 return TRUE;
72}
73
74Bool
75NV50DispInit(ScrnInfoPtr pScrn)
76{
77 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispInit is called.\n");
78
79 NVPtr pNv = NVPTR(pScrn);
80 uint32_t val;
81 if (NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & 0x100) {
82 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, 0x100);
83 NVWrite(pNv, 0x006194e8, NVRead(pNv, 0x006194e8) & ~1);
84 while (NVRead(pNv, 0x006194e8) & 2);
85 }
86
87 NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x2b00);
88 /* A bugfix (#12637) from the nv driver, to unlock the driver if it's left in a poor state */
89 do {
90 val = NVRead(pNv, NV50_DISPLAY_UNK200_CTRL);
91 if ((val & 0x9f0000) == 0x20000)
92 NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x800000);
93
94 if ((val & 0x3f0000) == 0x30000)
95 NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, val | 0x200000);
96 } while ((val & 0x1e0000) != 0);
97 NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_ENABLE);
98 NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x1000b03);
99 while (!(NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x40000000));
100
101 NV50DisplayCommand(pScrn, NV50_UNK84, 0);
102 NV50DisplayCommand(pScrn, NV50_UNK88, 0);
103 /* The GetLVDSNativeMode() function is proof that more than crtc0 is used by the bios. */
104 NV50DisplayCommand(pScrn, NV50_CRTC0_BLANK_CTRL, NV50_CRTC0_BLANK_CTRL_BLANK);
105 NV50DisplayCommand(pScrn, NV50_CRTC0_UNK800, 0);
106 NV50DisplayCommand(pScrn, NV50_CRTC0_DISPLAY_START, 0);
107 NV50DisplayCommand(pScrn, NV50_CRTC0_UNK82C, 0);
108
109 return TRUE;
110}
111
112void
113NV50DispShutdown(ScrnInfoPtr pScrn)
114{
115 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50DispShutdown is called.\n");
116 NVPtr pNv = NVPTR(pScrn);
117 int i;
118
119 for(i = 0; i < 2; i++) {
120 nouveauCrtcPtr crtc = pNv->crtc[i];
121
122 crtc->Blank(crtc, TRUE);
123 }
124
125 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
126
127 for(i = 0; i < 2; i++) {
128 nouveauCrtcPtr crtc = pNv->crtc[i];
129
130 /* This is like acknowledging a vblank, maybe this is in the spirit of cleaning up? */
131 /* The blob doesn't do it quite this way, it seems to do 0x30C as init and end. */
132 /* It doesn't wait for a non-zero value either. */
133 if (crtc->active) {
134 uint32_t mask = 0;
135 if (crtc->index == 1)
136 mask = NV50_DISPLAY_SUPERVISOR_CRTC1;
137 else
138 mask = NV50_DISPLAY_SUPERVISOR_CRTC0;
139
140 NVWrite(pNv, NV50_DISPLAY_SUPERVISOR, mask);
141 while(!(NVRead(pNv, NV50_DISPLAY_SUPERVISOR) & mask));
142 }
143 }
144
145 NVWrite(pNv, NV50_DISPLAY_UNK200_CTRL, 0x0);
146 NVWrite(pNv, NV50_DISPLAY_CTRL_STATE, NV50_DISPLAY_CTRL_STATE_DISABLE);
147 while ((NVRead(pNv, NV50_DISPLAY_UNK200_CTRL) & 0x1e0000) != 0);
148 while ((NVRead(pNv, NV50_SOR0_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT));
149 while ((NVRead(pNv, NV50_SOR1_DPMS_STATE) & NV50_SOR_DPMS_STATE_WAIT));
150}
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 @@
1/*
2 * Copyright (c) 2007 NVIDIA, Corporation
3 * Copyright (c) 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#include <string.h>
26
27#include "nv_include.h"
28
29#include <xf86DDC.h>
30
31#include "nouveau_crtc.h"
32#include "nouveau_output.h"
33#include "nouveau_connector.h"
34
35int
36NV50OrOffset(nouveauOutputPtr output)
37{
38 return ffs(output->dcb->or) - 1;
39}
40
41static void
42NV50OutputInit(ScrnInfoPtr pScrn, struct dcb_entry *dcbent)
43{
44 NVPtr pNv = NVPTR(pScrn);
45 nouveauConnectorPtr connector = pNv->connector[dcbent->i2c_index];
46 nouveauOutputPtr output = NULL;
47 char name[20];
48 int i;
49
50 switch (dcbent->type) {
51 case OUTPUT_LVDS:
52 case OUTPUT_TMDS:
53 sprintf(name, "SOR-%d", ffs(dcbent->or) - 1);
54 break;
55 case OUTPUT_ANALOG:
56 sprintf(name, "DAC-%d", ffs(dcbent->or) - 1);
57 break;
58 default:
59 return;
60 }
61
62 output = xnfcalloc(sizeof(nouveauOutputRec), 1);
63 output->name = xstrdup(name);
64 output->dcb = dcbent;
65 output->type = dcbent->type;
66 output->scrn = pScrn;
67
68 /* Put the output in the connector's list of outputs. */
69 for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) {
70 if (connector->outputs[i])
71 continue;
72 connector->outputs[i] = output;
73
74 break;
75 }
76
77 /* Put ourselves in the main output list. */
78 if (!pNv->output) {
79 pNv->output = output;
80 } else {
81 nouveauOutputPtr output_link = pNv->output;
82 if (output_link->next) {
83 do {
84 output_link = output_link->next;
85 } while (output_link->next);
86 }
87 output_link->next = output;
88 }
89
90 /* Output property for tmds and lvds. */
91 output->dithering = (pNv->FPDither || output->type == OUTPUT_LVDS);
92
93 if (output->type == OUTPUT_LVDS || output->type == OUTPUT_TMDS) {
94 if (pNv->FpScale) /* GPU Scaling */
95 output->scale_mode = SCALE_ASPECT;
96 else if (output->type == OUTPUT_LVDS)
97 output->scale_mode = SCALE_NOSCALE;
98 else
99 output->scale_mode = SCALE_PANEL;
100
101 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
102 output->scale_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
103 if (output->scale_mode == SCALE_INVALID)
104 output->scale_mode = SCALE_ASPECT; /* default */
105 }
106 }
107
108 /* NV5x scaling hardware seems to work fine for analog too. */
109 if (output->type == OUTPUT_ANALOG) {
110 output->scale_mode = SCALE_PANEL;
111
112 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
113 output->scale_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
114 if (output->scale_mode == SCALE_INVALID)
115 output->scale_mode = SCALE_PANEL; /* default */
116 }
117 }
118
119 /* Usually 3, which means both crtc's. */
120 output->allowed_crtc = output->dcb->heads;
121
122 if (output->type == OUTPUT_TMDS) {
123 NVWrite(pNv, NV50_SOR0_UNK00C + NV50OrOffset(output) * 0x800, 0x03010700);
124 NVWrite(pNv, NV50_SOR0_UNK010 + NV50OrOffset(output) * 0x800, 0x0000152f);
125 NVWrite(pNv, NV50_SOR0_UNK014 + NV50OrOffset(output) * 0x800, 0x00000000);
126 NVWrite(pNv, NV50_SOR0_UNK018 + NV50OrOffset(output) * 0x800, 0x00245af8);
127 }
128
129#if 0
130 if (output->type == OUTPUT_LVDS) {
131 /* now fpindex should be known, so reread the table here. */
132 /* not that we do a lot with the information. */
133 parse_lvds_manufacturer_table(pScrn, 0);
134 }
135#endif
136
137 /* This needs to be handled in the same way as pre-NV5x on the long run. */
138 //if (output->type == OUTPUT_LVDS)
139 // pNv->vbios->fp.native_mode = GetLVDSNativeMode(pScrn);
140
141 /* Function pointers. */
142 if (output->type == OUTPUT_TMDS || output->type == OUTPUT_LVDS) {
143 NV50SorSetFunctionPointers(output);
144 } else if (output->type == OUTPUT_ANALOG || output->type == OUTPUT_TV) {
145 NV50DacSetFunctionPointers(output);
146 }
147}
148
149#define MULTIPLE_ENCODERS(e) ((e) & ((e) - 1))
150void
151NV50OutputSetup(ScrnInfoPtr pScrn)
152{
153 NVPtr pNv = NVPTR(pScrn);
154 struct parsed_dcb *dcb = pNv->vbios->dcb;
155 int lvds = 0, dvi_i = 0, dvi_d = 0, vga = 0;
156 uint16_t connector[16] = {};
157 char name[20];
158 int i;
159
160 for (i = 0; i < dcb->entries; i++) {
161 struct dcb_entry *dcbent = &dcb->entry[i];
162
163 switch (dcbent->type) {
164 case OUTPUT_ANALOG:
165 case OUTPUT_TMDS:
166 case OUTPUT_LVDS:
167 break;
168 default:
169 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
170 "DCB encoder type %d not known\n",
171 dcbent->type);
172 continue;
173 }
174
175 connector[dcbent->i2c_index] |= (1 << i);
176 NV50OutputInit(pScrn, dcbent);
177 }
178
179 for (i = 0; i < dcb->entries; i++) {
180 struct dcb_entry *dcbent = &dcb->entry[i];
181 nouveauConnectorPtr c = pNv->connector[dcbent->i2c_index];
182 uint16_t encoders;
183
184 encoders = connector[dcbent->i2c_index];
185 connector[dcbent->i2c_index] = 0;
186
187 if (!encoders)
188 continue;
189
190 switch (dcbent->type) {
191 case OUTPUT_ANALOG:
192 if (!MULTIPLE_ENCODERS(encoders))
193 sprintf(name, "VGA-%d", vga++);
194 else
195 sprintf(name, "DVI-I-%d", dvi_i++);
196 break;
197 case OUTPUT_TMDS:
198 if (!MULTIPLE_ENCODERS(encoders))
199 sprintf(name, "DVI-D-%d", dvi_d++);
200 else
201 sprintf(name, "DVI-I-%d", dvi_i++);
202 break;
203 case OUTPUT_LVDS:
204 sprintf(name, "LVDS-%d", lvds++);
205 break;
206 default:
207 continue;
208 }
209
210 if (dcbent->i2c_index != 0xf) {
211 NV_I2CInit(pScrn, &pNv->pI2CBus[dcbent->i2c_index],
212 &dcb->i2c[dcbent->i2c_index],
213 xstrdup(name));
214 }
215
216 xfree(c->name);
217 c->name = xstrdup(name);
218 c->i2c_index = dcbent->i2c_index;
219 c->pDDCBus = pNv->pI2CBus[dcbent->i2c_index];
220 }
221}
222
223void
224NV50OutputDestroy(ScrnInfoPtr pScrn)
225{
226 NVPtr pNv = NVPTR(pScrn);
227 nouveauOutputPtr output, next;
228
229 for (output = pNv->output; output != NULL; output = next) {
230 next = output->next;
231 xfree(output->name);
232 xfree(output);
233 }
234
235 pNv->output = NULL;
236}
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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include "nv50_randr.h"
24#include "X11/Xatom.h"
25
26/*
27 * A randr-1.2 wrapper around the NV50 driver.
28 */
29
30/*
31 * CRTC stuff.
32 */
33
34static void
35nv50_crtc_dpms(xf86CrtcPtr crtc, int mode)
36{
37 ScrnInfoPtr pScrn = crtc->scrn;
38 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
39 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_dpms is called with mode %d for %s.\n", mode, nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
40
41 switch (mode) {
42 case DPMSModeOn:
43 nv_crtc->crtc->active = TRUE;
44 break;
45 case DPMSModeSuspend:
46 case DPMSModeStandby:
47 case DPMSModeOff:
48 default:
49 nv_crtc->crtc->active = FALSE;
50 break;
51 }
52}
53
54static Bool
55nv50_crtc_lock(xf86CrtcPtr crtc)
56{
57 return FALSE;
58}
59
60static Bool
61nv50_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
62 DisplayModePtr adjusted_mode)
63{
64 return TRUE;
65}
66
67static void
68nv50_crtc_prepare(xf86CrtcPtr crtc)
69{
70 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
71 ScrnInfoPtr pScrn = crtc->scrn;
72 NVPtr pNv = NVPTR(pScrn);
73 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
74 nouveauOutputPtr output;
75 int i;
76
77 /* Rewire internal stucts to match randr-1.2... yet again.. */
78 for (i = 0; i < xf86_config->num_output; i++) {
79 xf86OutputPtr output = xf86_config->output[i];
80 NV50OutputPrivatePtr nv50_output = output->driver_private;
81 nouveauOutputPtr nv_output = nv50_output->output;
82
83 if (output->crtc) {
84 NV50CrtcPrivatePtr nv50_crtc =
85 output->crtc->driver_private;
86 nv_output->crtc = nv50_crtc->crtc;
87 } else {
88 nv_output->crtc = NULL;
89 }
90 }
91
92 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
93 "nv50_crtc_prepare is called for %s.\n",
94 nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
95
96 nv_crtc->crtc->active = TRUE;
97 nv_crtc->crtc->modeset_lock = TRUE;
98
99 /* Detach any unused outputs. */
100 for (output = pNv->output; output != NULL; output = output->next) {
101 if (!output->crtc)
102 output->ModeSet(output, NULL);
103 }
104}
105
106static void
107nv50_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
108 DisplayModePtr adjusted_mode, int x, int y)
109{
110 ScrnInfoPtr pScrn = crtc->scrn;
111 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
112 struct nouveau_bo *bo;
113
114 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
115 "nv50_crtc_mode_set is called for %s.\n",
116 nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
117
118 NVPtr pNv = NVPTR(pScrn);
119
120 bo = pNv->scanout;
121 if (crtc->rotatedData) {
122 bo = nv_crtc->shadow;
123 x = 0;
124 y = 0;
125 }
126
127 nv_crtc->crtc->SetFB(nv_crtc->crtc, bo);
128 nv_crtc->crtc->SetFBOffset(nv_crtc->crtc, x, y);
129 nv_crtc->crtc->ModeSet(nv_crtc->crtc, mode);
130}
131
132static void
133nv50_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, int size)
134{
135 ScrnInfoPtr pScrn = crtc->scrn;
136 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
137 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_gamma_set is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
138
139 nv_crtc->crtc->GammaSet(nv_crtc->crtc, (uint16_t *) red, (uint16_t *) green, (uint16_t *) blue, size);
140}
141
142static void
143nv50_crtc_commit(xf86CrtcPtr crtc)
144{
145 ScrnInfoPtr pScrn = crtc->scrn;
146 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
147 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_commit is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
148
149 NVPtr pNv = NVPTR(pScrn);
150
151 /* Let's detect any outputs and connectors that have gone inactive. */
152 uint8_t crtc_active_mask = 0;
153 int i, j;
154 nouveauOutputPtr output;
155
156 for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) {
157 Bool connector_active = FALSE;
158 for (j = 0; j < MAX_OUTPUTS_PER_CONNECTOR; j++) {
159 output = pNv->connector[i]->outputs[j];
160 if (output) {
161 if (output->crtc) {
162 crtc_active_mask |= 1 << output->crtc->index;
163 connector_active = TRUE;
164 } else {
165 output->active = FALSE;
166 }
167 }
168 }
169
170 pNv->connector[i]->active = connector_active;
171 }
172
173 /* Blank any crtc's that are inactive. */
174 if (!(crtc_active_mask & (1 << 0)))
175 pNv->crtc[0]->Blank(pNv->crtc[0], TRUE);
176
177 if (!(crtc_active_mask & (1 << 1)))
178 pNv->crtc[1]->Blank(pNv->crtc[1], TRUE);
179
180 xf86_reload_cursors(pScrn->pScreen);
181
182 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
183
184 nv_crtc->crtc->modeset_lock = FALSE;
185}
186
187/*
188 * Cursor CRTC stuff.
189 */
190
191static void
192nv50_crtc_show_cursor(xf86CrtcPtr crtc)
193{
194 //ScrnInfoPtr pScrn = crtc->scrn;
195 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
196 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_show_cursor is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
197
198 if (!nv_crtc->crtc->blanked)
199 nv_crtc->crtc->ShowCursor(nv_crtc->crtc, FALSE);
200}
201
202static void
203nv50_crtc_hide_cursor(xf86CrtcPtr crtc)
204{
205 //ScrnInfoPtr pScrn = crtc->scrn;
206 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
207 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_hide_cursor is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
208
209 nv_crtc->crtc->HideCursor(nv_crtc->crtc, FALSE);
210}
211
212static void
213nv50_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
214{
215 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
216
217 nv_crtc->crtc->SetCursorPosition(nv_crtc->crtc, x, y);
218}
219
220static void
221nv50_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *src)
222{
223 //ScrnInfoPtr pScrn = crtc->scrn;
224 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
225 //xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_crtc_load_cursor_argb is called for %s.\n", nv_crtc->crtc->index ? "CRTC1" : "CRTC0");
226
227 nv_crtc->crtc->LoadCursor(nv_crtc->crtc, TRUE, (uint32_t *) src);
228}
229
230static void *
231nv50_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
232{
233 ScrnInfoPtr pScrn = crtc->scrn;
234 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
235 NVPtr pNv = NVPTR(pScrn);
236 int size, pitch;
237
238 ErrorF("nv50_crtc_shadow_allocate\n");
239
240 pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8);
241 size = pitch * height;
242
243 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM |
244 NOUVEAU_BO_MAP, 64, size, &nv_crtc->shadow)) {
245 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
246 "Failed to allocate memory for shadow buffer!\n");
247 return NULL;
248 }
249
250 if (nv_crtc->shadow && nouveau_bo_map(nv_crtc->shadow, NOUVEAU_BO_RDWR)) {
251 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
252 "Failed to map shadow buffer.\n");
253 return NULL;
254 }
255
256 pNv->shadow[nv_crtc->crtc->index] = nv_crtc->shadow;
257
258 return nv_crtc->shadow->map;
259}
260
261static PixmapPtr
262nv50_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
263{
264 ScrnInfoPtr pScrn = crtc->scrn;
265 uint32_t pitch;
266 PixmapPtr rotate_pixmap;
267
268 ErrorF("nv50_crtc_shadow_create\n");
269
270 if (!data)
271 data = crtc->funcs->shadow_allocate (crtc, width, height);
272
273 pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8);
274
275 rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
276 width, height,
277 pScrn->depth,
278 pScrn->bitsPerPixel,
279 pitch,
280 data);
281
282 if (rotate_pixmap == NULL) {
283 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
284 "Couldn't allocate shadow pixmap for rotated CRTC\n");
285 }
286
287 return rotate_pixmap;
288}
289
290static void
291nv50_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
292{
293 ScrnInfoPtr pScrn = crtc->scrn;
294 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
295 NVPtr pNv = NVPTR(pScrn);
296 ScreenPtr pScreen = pScrn->pScreen;
297
298 ErrorF("nv50_crtc_shadow_destroy\n");
299
300 if (rotate_pixmap)
301 pScreen->DestroyPixmap(rotate_pixmap);
302
303 if (nv_crtc->shadow)
304 nouveau_bo_ref(NULL, &nv_crtc->shadow);
305
306 nv_crtc->shadow = NULL;
307 /* for easy acces by exa */
308 pNv->shadow[nv_crtc->crtc->index] = NULL;
309}
310
311#if XF86_CRTC_VERSION >= 2
312static void
313nv50_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
314{
315 ScrnInfoPtr pScrn = crtc->scrn;
316 NV50CrtcPrivatePtr nv_crtc = crtc->driver_private;
317 nouveauCrtcPtr nvcrtc = nv_crtc->crtc; /* sigh.. */
318 NVPtr pNv = NVPTR(pScrn);
319 uint32_t fb;
320
321 nvcrtc->SetFB(nvcrtc, pNv->scanout);
322 nvcrtc->SetFBOffset(nvcrtc, x, y);
323 nvcrtc->fb_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
324 fb = nvcrtc->front_buffer->offset - pNv->dev->vm_vram_base;
325
326 NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_OFFSET, fb >> 8);
327 NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_PITCH, nvcrtc->fb_pitch | (1<<20));
328 NV50CrtcCommand(nvcrtc, NV50_CRTC0_FB_SIZE, (pScrn->virtualY << 16) |
329 pScrn->virtualX);
330
331 NV50DisplayCommand(pScrn, NV50_UPDATE_DISPLAY, 0);
332}
333#endif
334
335static void
336nv50_crtc_destroy(xf86CrtcPtr crtc)
337{
338 xfree(crtc->driver_private);
339}
340
341static const xf86CrtcFuncsRec nv50_crtc_funcs = {
342 .dpms = nv50_crtc_dpms,
343 .save = NULL,
344 .restore = NULL,
345 .lock = nv50_crtc_lock,
346 .unlock = NULL,
347 .mode_fixup = nv50_crtc_mode_fixup,
348 .prepare = nv50_crtc_prepare,
349 .mode_set = nv50_crtc_mode_set,
350 .gamma_set = nv50_crtc_gamma_set,
351 .commit = nv50_crtc_commit,
352 .shadow_create = nv50_crtc_shadow_create,
353 .shadow_allocate = nv50_crtc_shadow_allocate,
354 .shadow_destroy = nv50_crtc_shadow_destroy,
355 .set_cursor_position = nv50_crtc_set_cursor_position,
356 .show_cursor = nv50_crtc_show_cursor,
357 .hide_cursor = nv50_crtc_hide_cursor,
358 .load_cursor_argb = nv50_crtc_load_cursor_argb,
359 .destroy = nv50_crtc_destroy,
360#if XF86_CRTC_VERSION >= 2
361 .set_origin = nv50_crtc_set_origin,
362#endif
363};
364
365void
366nv50_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
367{
368 NVPtr pNv = NVPTR(pScrn);
369 xf86CrtcPtr crtc;
370 NV50CrtcPrivatePtr nv_crtc;
371
372 crtc = xf86CrtcCreate(pScrn, &nv50_crtc_funcs);
373 if (crtc == NULL)
374 return;
375
376 nv_crtc = xnfcalloc (sizeof (NV50CrtcPrivateRec), 1);
377 nv_crtc->crtc = pNv->crtc[crtc_num];
378
379 crtc->driver_private = nv_crtc;
380}
381
382
383/*
384 * "Output" stuff.
385 */
386
387static void
388nv50_output_dpms(xf86OutputPtr output, int mode)
389{
390 ScrnInfoPtr pScrn = output->scrn;
391 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_dpms is called with mode %d.\n", mode);
392
393 NVPtr pNv = NVPTR(pScrn);
394 NV50OutputPrivatePtr nv_output = output->driver_private;
395
396 /* Keep the crtc wiring consistent with randr-1.2 */
397 if (output->crtc) {
398 NV50CrtcPrivatePtr nv_crtc = output->crtc->driver_private;
399 nv_output->output->crtc = nv_crtc->crtc;
400 } else {
401 nv_output->output->crtc = NULL;
402 }
403
404 /* Our crtc's map 1:1 onto randr-1.2 crtc's. */
405 switch (mode) {
406 case DPMSModeOn:
407 nv_output->output->active = TRUE;
408 break;
409 case DPMSModeSuspend:
410 case DPMSModeStandby:
411 case DPMSModeOff:
412 default:
413 nv_output->output->active = FALSE;
414 break;
415 }
416
417 /* Set dpms on all outputs for ths connector, just to be safe. */
418 nouveauConnectorPtr connector =
419 pNv->connector[nv_output->output->dcb->i2c_index];
420 int i;
421 for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) {
422 if (connector->outputs[i])
423 connector->outputs[i]->SetPowerMode(connector->outputs[i], mode);
424 }
425}
426
427static int
428nv50_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
429{
430 ScrnInfoPtr pScrn = output->scrn;
431 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_mode_valid is called.\n");
432
433 NV50OutputPrivatePtr nv_output = output->driver_private;
434
435 return nv_output->output->ModeValid(nv_output->output, mode);
436}
437
438static Bool
439nv50_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
440{
441 return TRUE;
442}
443
444static void
445nv50_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
446{
447 ScrnInfoPtr pScrn = output->scrn;
448 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_mode_set is called.\n");
449
450 NV50OutputPrivatePtr nv_output = output->driver_private;
451
452 nv_output->output->ModeSet(nv_output->output, mode);
453}
454
455static xf86OutputStatus
456nv50_output_detect(xf86OutputPtr output)
457{
458 ScrnInfoPtr pScrn = output->scrn;
459 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_detect is called.\n");
460
461 NVPtr pNv = NVPTR(pScrn);
462 NV50OutputPrivatePtr nv_output = output->driver_private;
463 nouveauConnectorPtr connector =
464 pNv->connector[nv_output->output->dcb->i2c_index];
465
466 if (!connector)
467 return XF86OutputStatusDisconnected;
468
469 Bool detect_present = FALSE;
470 Bool detect_digital = FALSE;
471 xf86MonPtr ddc_mon = connector->DDCDetect(connector);
472 int i;
473
474 if (!ddc_mon) {
475 for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) {
476 if (connector->outputs[i] && connector->outputs[i]->Detect) {
477 detect_present = connector->outputs[i]->Detect(connector->outputs[i]);
478 if (detect_present) {
479 if (connector->outputs[i]->type == OUTPUT_TMDS || connector->outputs[i]->type == OUTPUT_LVDS)
480 detect_digital = TRUE;
481 break;
482 }
483 }
484 }
485 }
486
487 /* HACK: assume that a connector only holds output in the case of a tv-out */
488 if (nv_output->output->type == OUTPUT_TV)
489 return XF86OutputStatusUnknown;
490
491 /*
492 * We abuse randr-1.2 outputs as connector, so here we have to determine what actual output is connected to the connector.
493 */
494 if (ddc_mon || detect_present) {
495 Bool is_digital = FALSE;
496 Bool found = FALSE;
497 nouveauCrtcPtr crtc_backup = nv_output->output->crtc;
498 nv_output->output->crtc = NULL;
499 nv_output->output->connector = NULL;
500
501 if (ddc_mon)
502 is_digital = ddc_mon->features.input_type;
503 else
504 is_digital = detect_digital;
505
506 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected a %s output on %s\n", is_digital ? "Digital" : "Analog", connector->name);
507
508 for (i = 0; i < MAX_OUTPUTS_PER_CONNECTOR; i++) {
509 if (!is_digital && (connector->outputs[i]->type == OUTPUT_ANALOG || connector->outputs[i]->type == OUTPUT_TV)) {
510 found = TRUE;
511 } else if (is_digital && (connector->outputs[i]->type == OUTPUT_TMDS || connector->outputs[i]->type == OUTPUT_LVDS)) {
512 found = TRUE;
513 }
514 if (found) {
515 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found a suitable output, index %d\n", i);
516 connector->connected_output = i;
517 connector->outputs[i]->connector = connector;
518 connector->outputs[i]->crtc = crtc_backup;
519 nv_output->output = connector->outputs[i];
520 break;
521 }
522 }
523 }
524
525 if (ddc_mon || detect_present) {
526 free(ddc_mon);
527 return XF86OutputStatusConnected;
528 } else {
529 return XF86OutputStatusDisconnected;
530 }
531}
532
533static DisplayModePtr
534nv50_output_get_modes(xf86OutputPtr output)
535{
536 ScrnInfoPtr pScrn = output->scrn;
537 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_detect is called.\n");
538
539 NVPtr pNv = NVPTR(pScrn);
540 NV50OutputPrivatePtr nv_output = output->driver_private;
541 nouveauConnectorPtr connector =
542 pNv->connector[nv_output->output->dcb->i2c_index];
543
544 xf86MonPtr ddc_mon = connector->DDCDetect(connector);
545
546 xf86OutputSetEDID(output, ddc_mon);
547
548 DisplayModePtr ddc_modes = connector->GetDDCModes(connector);
549 DisplayModePtr default_modes = NULL;
550
551 xf86DeleteMode(&nv_output->output->native_mode, nv_output->output->native_mode);
552 nv_output->output->native_mode = NULL;
553 if (nv_output->output->crtc)
554 nv_output->output->crtc->native_mode = NULL;
555
556 /* typically only LVDS will hit this code path. */
557 if (!ddc_modes) {
558 DisplayModeRec mode = {};
559
560 if (nv_output->output->type == OUTPUT_LVDS &&
561 nouveau_bios_fp_mode(pScrn, &mode)) {
562 mode.status = MODE_OK;
563 mode.type = M_T_DRIVER | M_T_PREFERRED;
564 xf86SetModeDefaultName(&mode);
565
566 ddc_modes = xf86DuplicateMode(&mode);
567 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
568 "LVDS: Using a bios mode, which should work, if it doesn't please report.\n");
569 }
570 }
571
572 if (!ddc_modes && nv_output->output->type == OUTPUT_LVDS) {
573 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "LVDS and no modes found, bailing out.\n");
574 return NULL;
575 }
576
577 /* NV5x hardware can also do scaling on analog connections. */
578 if (ddc_modes) {
579 /* Use the first preferred mode as native mode. */
580 DisplayModePtr mode;
581
582 /* Find the preferred mode. */
583 for (mode = ddc_modes; mode != NULL; mode = mode->next) {
584 if (mode->type & M_T_PREFERRED) {
585 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
586 "%s: preferred mode is %s\n",
587 output->name, mode->name);
588 break;
589 }
590 }
591
592 /* TODO: Scaling needs a native mode, maybe fail in a better way. */
593 if (!mode) {
594 mode = ddc_modes;
595 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
596 "%s: no preferred mode found, using %s\n",
597 output->name, mode->name);
598 }
599
600 nv_output->output->native_mode = xf86DuplicateMode(mode);
601 }
602
603 /* No ddc means no native mode, so make one up to avoid crashes. */
604 if (!nv_output->output->native_mode)
605 nv_output->output->native_mode = xf86CVTMode(1024, 768, 60.0, FALSE, FALSE);
606
607 xf86SetModeCrtc(nv_output->output->native_mode, 0);
608
609 if (nv_output->output->crtc)
610 nv_output->output->crtc->native_mode = nv_output->output->native_mode;
611
612 if (nv_output->output->type == OUTPUT_LVDS &&
613 (!ddc_mon ||!GTF_SUPPORTED(ddc_mon->features.msc))) {
614#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,6,99,1,0)
615 default_modes = xf86GetDefaultModes(output->interlaceAllowed,
616 output->doubleScanAllowed);
617#else
618 default_modes = xf86GetDefaultModes();
619#endif
620 }
621
622 xf86ModesAdd(ddc_modes, default_modes);
623 return ddc_modes;
624}
625
626static void
627nv50_output_destroy(xf86OutputPtr output)
628{
629 NV50OutputPrivatePtr nv_output = output->driver_private;
630
631 xf86DeleteMode(&nv_output->output->native_mode, nv_output->output->native_mode);
632
633 xfree(output->driver_private);
634 output->driver_private = NULL;
635}
636
637void
638nv50_output_prepare(xf86OutputPtr output)
639{
640 ScrnInfoPtr pScrn = output->scrn;
641 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_prepare is called.\n");
642
643 NV50OutputPrivatePtr nv_output = output->driver_private;
644 NV50CrtcPrivatePtr nv_crtc = output->crtc->driver_private;
645
646 /* Set the real crtc now. */
647 nv_output->output->crtc = nv_crtc->crtc;
648
649 /* Transfer some output properties to the crtc for easy access. */
650 nv_output->output->crtc->scale_mode = nv_output->output->scale_mode;
651 nv_output->output->crtc->dithering = nv_output->output->dithering;
652 nv_output->output->crtc->native_mode = nv_output->output->native_mode;
653
654 if (nv_output->output->scale_mode != SCALE_PANEL)
655 nv_output->output->crtc->use_native_mode = TRUE;
656 else
657 nv_output->output->crtc->use_native_mode = FALSE;
658}
659
660static void
661nv50_output_commit(xf86OutputPtr output)
662{
663 ScrnInfoPtr pScrn = output->scrn;
664 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_commit is called.\n");
665}
666
667#ifdef RANDR_GET_CRTC_INTERFACE
668static xf86CrtcPtr
669nv50_output_get_crtc(xf86OutputPtr output)
670{
671 ScrnInfoPtr pScrn = output->scrn;
672 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "nv50_output_get_crtc is called.\n");
673
674 NV50OutputPrivatePtr nv_output = output->driver_private;
675 nouveauCrtcPtr crtc = nv_output->output->GetCurrentCrtc(nv_output->output);
676
677 /*
678 * Match the internal crtc to the public crtc.
679 * Note that GetCurrentCrtc() retrieves hardware state.
680 * Otherwise we could have just used output->crtc.
681 */
682 if (crtc) {
683 int i;
684 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
685 for (i = 0; i < xf86_config->num_crtc; i++) {
686 NV50CrtcPrivatePtr nv_crtc = xf86_config->crtc[i]->driver_private;
687 if (nv_crtc->crtc == crtc)
688 return xf86_config->crtc[i];
689 }
690 }
691
692 return NULL;
693}
694#endif /* RANDR_GET_CRTC_INTERFACE */
695
696/*
697 * Output properties.
698 */
699
700/*
701 * Several scaling modes exist, let the user choose.
702 */
703#define SCALING_MODE_NAME "SCALING_MODE"
704static const struct {
705 char *name;
706 enum scaling_modes mode;
707} scaling_mode[] = {
708 { "panel", SCALE_PANEL },
709 { "fullscreen", SCALE_FULLSCREEN },
710 { "aspect", SCALE_ASPECT },
711 { "noscale", SCALE_NOSCALE },
712 { NULL, SCALE_INVALID}
713};
714static Atom scaling_mode_atom;
715
716#define DITHERING_MODE_NAME "DITHERING"
717static Atom dithering_atom;
718
719int
720nv_scaling_mode_lookup(char *name, int size)
721{
722 int i;
723
724 /* for when name is zero terminated */
725 if (size < 0)
726 size = strlen(name);
727
728 for (i = 0; scaling_mode[i].name; i++)
729 /* We're getting non-terminated strings */
730 if (strlen(scaling_mode[i].name) >= size &&
731 !strncasecmp(name, scaling_mode[i].name, size))
732 break;
733
734 return scaling_mode[i].mode;
735}
736
737void
738nv50_output_create_resources(xf86OutputPtr output)
739{
740 NV50OutputPrivatePtr nv_output = output->driver_private;
741 ScrnInfoPtr pScrn = output->scrn;
742 INT32 dithering_range[2] = { 0, 1 };
743 int error, i;
744
745 /*
746 * Setup scaling mode property.
747 */
748 scaling_mode_atom = MakeAtom(SCALING_MODE_NAME, sizeof(SCALING_MODE_NAME) - 1, TRUE);
749
750 error = RRConfigureOutputProperty(output->randr_output,
751 scaling_mode_atom, TRUE, FALSE, FALSE,
752 0, NULL);
753
754 if (error != 0) {
755 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
756 "RRConfigureOutputProperty error, %d\n", error);
757 }
758
759 char *existing_scale_name = NULL;
760 for (i = 0; scaling_mode[i].name; i++)
761 if (scaling_mode[i].mode == nv_output->output->scale_mode)
762 existing_scale_name = scaling_mode[i].name;
763
764 error = RRChangeOutputProperty(output->randr_output, scaling_mode_atom,
765 XA_STRING, 8, PropModeReplace,
766 strlen(existing_scale_name),
767 existing_scale_name, FALSE, TRUE);
768
769 if (error != 0) {
770 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
771 "Failed to set scaling mode, %d\n", error);
772 }
773
774 if (nv_output->output->type == OUTPUT_TMDS || nv_output->output->type == OUTPUT_LVDS) {
775 /*
776 * Setup dithering property.
777 */
778 dithering_atom = MakeAtom(DITHERING_MODE_NAME, sizeof(DITHERING_MODE_NAME) - 1, TRUE);
779
780 error = RRConfigureOutputProperty(output->randr_output,
781 dithering_atom, TRUE, TRUE, FALSE,
782 2, dithering_range);
783
784 if (error != 0) {
785 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
786 "RRConfigureOutputProperty error, %d\n", error);
787 }
788
789 error = RRChangeOutputProperty(output->randr_output, dithering_atom,
790 XA_INTEGER, 32, PropModeReplace, 1, &nv_output->output->dithering,
791 FALSE, TRUE);
792
793 if (error != 0) {
794 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
795 "Failed to set dithering mode, %d\n", error);
796 }
797 }
798}
799
800Bool
801nv50_output_set_property(xf86OutputPtr output, Atom property,
802 RRPropertyValuePtr value)
803{
804 NV50OutputPrivatePtr nv_output = output->driver_private;
805
806 if (property == scaling_mode_atom) {
807 int32_t ret;
808 char *name = NULL;
809
810 if (value->type != XA_STRING || value->format != 8)
811 return FALSE;
812
813 name = (char *) value->data;
814
815 /* Match a string to a scaling mode */
816 ret = nv_scaling_mode_lookup(name, value->size);
817 if (ret == SCALE_INVALID)
818 return FALSE;
819
820 /* LVDS must always use gpu scaling. */
821 if (ret == SCALE_PANEL && nv_output->output->type == OUTPUT_LVDS)
822 return FALSE;
823
824 nv_output->output->scale_mode = ret;
825 if (nv_output->output->crtc) /* normally prepare sets all these things for the crtc. */
826 nv_output->output->crtc->scale_mode = ret;
827 return TRUE;
828 } else if (property == dithering_atom) {
829 if (value->type != XA_INTEGER || value->format != 32)
830 return FALSE;
831
832 int32_t val = *(int32_t *) value->data;
833
834 if (val < 0 || val > 1)
835 return FALSE;
836
837 nv_output->output->dithering = val;
838 if (nv_output->output->crtc) /* normally prepare sets all these things for the crtc. */
839 nv_output->output->crtc->dithering = val;
840 return TRUE;
841 }
842
843 return TRUE;
844}
845
846static const xf86OutputFuncsRec nv50_output_funcs = {
847 .dpms = nv50_output_dpms,
848 .save = NULL,
849 .restore = NULL,
850 .mode_valid = nv50_output_mode_valid,
851 .mode_fixup = nv50_output_mode_fixup,
852 .mode_set = nv50_output_mode_set,
853 .detect = nv50_output_detect,
854 .get_modes = nv50_output_get_modes,
855 .destroy = nv50_output_destroy,
856 .prepare = nv50_output_prepare,
857 .commit = nv50_output_commit,
858#ifdef RANDR_GET_CRTC_INTERFACE
859 .get_crtc = nv50_output_get_crtc,
860#endif /*RANDR_GET_CRTC_INTERFACE */
861 .create_resources = nv50_output_create_resources,
862 .set_property = nv50_output_set_property,
863};
864
865void
866nv50_output_create(ScrnInfoPtr pScrn)
867{
868 NVPtr pNv = NVPTR(pScrn);
869 xf86OutputPtr output;
870 NV50OutputPrivatePtr nv_output;
871 int i;
872
873 /* this is a 1:1 hookup of the connectors. */
874 for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++) {
875 if (!(pNv->connector[i]->outputs[0]))
876 continue; /* An empty connector is not useful. */
877
878 if (!(output = xf86OutputCreate(pScrn, &nv50_output_funcs, pNv->connector[i]->name)))
879 return;
880
881 if (!(nv_output = xnfcalloc(sizeof(NV50OutputPrivateRec), 1)))
882 return;
883
884 output->driver_private = nv_output;
885
886 nv_output->output = pNv->connector[i]->outputs[0]; /* initially just wire up the first output available. */
887
888 output->possible_crtcs = nv_output->output->allowed_crtc;
889 output->possible_clones = 0;
890
891 if (nv_output->output->type == OUTPUT_TMDS || nv_output->output->type == OUTPUT_LVDS) {
892 output->doubleScanAllowed = false;
893 output->interlaceAllowed = false;
894 } else {
895 output->doubleScanAllowed = true;
896 output->interlaceAllowed = true;
897 }
898 }
899}
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 @@
1/*
2 * Copyright 2008 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#ifndef __NV50_RANDR_H_
24#define __NV50_RANDR_H_
25
26#include "nouveau_modeset.h"
27#include "nouveau_crtc.h"
28#include "nouveau_output.h"
29#include "nouveau_connector.h"
30
31typedef struct NV50CrtcPrivate {
32 int head;
33 nouveauCrtcPtr crtc;
34 struct nouveau_bo *shadow;
35} NV50CrtcPrivateRec, *NV50CrtcPrivatePtr;
36
37typedef struct NV50OutputPrivate {
38 nouveauOutputPtr output;
39} NV50OutputPrivateRec, *NV50OutputPrivatePtr;
40
41#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 @@
1/*
2 * Copyright 2007 NVIDIA, Corporation
3 * Copyright 2008 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "nouveau_modeset.h"
25#include "nouveau_crtc.h"
26#include "nouveau_output.h"
27#include "nouveau_connector.h"
28
29static int
30NV50SorModeValid(nouveauOutputPtr output, DisplayModePtr mode)
31{
32 int high_limit;
33
34 if (output->type == OUTPUT_LVDS)
35 high_limit = 400000;
36 else
37 high_limit = 165000; /* no dual link dvi until we figure it out completely */
38
39 if (mode->Clock > high_limit)
40 return MODE_CLOCK_HIGH;
41
42 if (mode->Clock < 25000)
43 return MODE_CLOCK_LOW;
44
45 if (mode->Flags & V_DBLSCAN)
46 return MODE_NO_DBLESCAN;
47
48 if (mode->HDisplay > output->native_mode->HDisplay || mode->VDisplay > output->native_mode->VDisplay)
49 return MODE_PANEL;
50
51 return MODE_OK;
52}
53
54static void
55NV50SorModeSet(nouveauOutputPtr output, DisplayModePtr mode)
56{
57 ScrnInfoPtr pScrn = output->scrn;
58 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorModeSet is called.\n");
59
60 const int sorOff = 0x40 * NV50OrOffset(output);
61 uint32_t mode_ctl = NV50_SOR_MODE_CTRL_OFF;
62
63 if (!mode) {
64 /* Disconnect the SOR */
65 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disconnecting SOR.\n");
66 NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl);
67 return;
68 }
69
70 /* Anyone know a more appropriate name? */
71 DisplayModePtr desired_mode = output->crtc->use_native_mode ? output->crtc->native_mode : mode;
72
73 if (output->type == OUTPUT_LVDS) {
74 mode_ctl |= NV50_SOR_MODE_CTRL_LVDS;
75 } else {
76 mode_ctl |= NV50_SOR_MODE_CTRL_TMDS;
77 if (desired_mode->Clock > 165000)
78 mode_ctl |= NV50_SOR_MODE_CTRL_TMDS_DUAL_LINK;
79 }
80
81 if (output->crtc) {
82 if (output->crtc->index == 1)
83 mode_ctl |= NV50_SOR_MODE_CTRL_CRTC1;
84 else
85 mode_ctl |= NV50_SOR_MODE_CTRL_CRTC0;
86 } else {
87 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Warning, output has no crtc.\n");
88 return;
89 }
90
91 if (desired_mode->Flags & V_NHSYNC)
92 mode_ctl |= NV50_SOR_MODE_CTRL_NHSYNC;
93
94 if (desired_mode->Flags & V_NVSYNC)
95 mode_ctl |= NV50_SOR_MODE_CTRL_NVSYNC;
96
97 // This wouldn't be necessary, but the server is stupid and calls
98 // nv50_sor_dpms after the output is disconnected, even though the hardware
99 // turns it off automatically.
100 output->SetPowerMode(output, DPMSModeOn);
101
102 NV50DisplayCommand(pScrn, NV50_SOR0_MODE_CTRL + sorOff, mode_ctl);
103
104 output->crtc->SetScaleMode(output->crtc, output->scale_mode);
105}
106
107static void
108NV50SorSetClockMode(nouveauOutputPtr output, int clock)
109{
110 ScrnInfoPtr pScrn = output->scrn;
111 NVPtr pNv = NVPTR(pScrn);
112 const int limit = output->dcb->type == OUTPUT_LVDS ? 112000 : 165000;
113
114 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
115 "NV50SorSetClockMode is called.\n");
116
117#if 0
118 ret = nouveau_bios_run_display_table(pScrn, output->dcb, clock);
119 if (ret)
120 NV_WARN(pScrn, "failed to run output script, may hang!\n");
121#else
122 /* just to keep the original behaviour until we can reliably run
123 * the output scripts...
124 */
125 if (output->dcb->type == OUTPUT_LVDS)
126 return;
127#endif
128
129 /* 0x70000 was a late addition to nv, mentioned as fixing tmds
130 * initialisation on certain gpu's. */
131 /* I presume it's some kind of clock setting, but what precisely i
132 * do not know.
133 */
134 NVWrite(pNv, NV50_SOR0_CLK_CTRL2 + NV50OrOffset(output) * 0x800,
135 0x70000 | ((clock > limit) ? 0x101 : 0));
136}
137
138static int
139NV50SorSense(nouveauOutputPtr output)
140{
141 switch (output->type) {
142 case OUTPUT_TMDS:
143 case OUTPUT_LVDS:
144 return output->type;
145 default:
146 return OUTPUT_NONE;
147 }
148}
149
150static void
151NV50SorSetPowerMode(nouveauOutputPtr output, int mode)
152{
153 ScrnInfoPtr pScrn = output->scrn;
154 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorSetPowerMode is called with mode %d.\n", mode);
155
156 NVPtr pNv = NVPTR(pScrn);
157 uint32_t tmp;
158
159 while ((NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_CTRL_PENDING));
160
161 tmp = NVRead(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800);
162 tmp |= NV50_SOR_DPMS_CTRL_PENDING;
163
164 if (mode == DPMSModeOn)
165 tmp |= NV50_SOR_DPMS_CTRL_MODE_ON;
166 else
167 tmp &= ~NV50_SOR_DPMS_CTRL_MODE_ON;
168
169 NVWrite(pNv, NV50_SOR0_DPMS_CTRL + NV50OrOffset(output) * 0x800, tmp);
170 while ((NVRead(pNv, NV50_SOR0_DPMS_STATE + NV50OrOffset(output) * 0x800) & NV50_SOR_DPMS_STATE_WAIT));
171}
172
173static Bool
174NV50SorDetect(nouveauOutputPtr output)
175{
176 if (output->type == OUTPUT_LVDS) /* assume connected */
177 return TRUE;
178
179 return FALSE;
180}
181
182static nouveauCrtcPtr
183NV50SorGetCurrentCrtc(nouveauOutputPtr output)
184{
185 ScrnInfoPtr pScrn = output->scrn;
186 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "NV50SorGetCurrentCrtc is called.\n");
187
188 NVPtr pNv = NVPTR(pScrn);
189 uint32_t mode_ctrl = NVRead(pNv, NV50_SOR0_MODE_CTRL_VAL + NV50OrOffset(output) * 0x8);
190
191 /*
192 * MODE_CTRL values only contain one instance of crtc0 and of crtc1.
193 * This is because we disconnect outputs upon modeset.
194 * Crtc might be off even if we get a positive return.
195 * But we are still associated with that crtc.
196 */
197 if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC0)
198 return pNv->crtc[0];
199 else if (mode_ctrl & NV50_SOR_MODE_CTRL_CRTC1)
200 return pNv->crtc[1];
201
202 return NULL;
203}
204
205void
206NV50SorSetFunctionPointers(nouveauOutputPtr output)
207{
208 output->ModeValid = NV50SorModeValid;
209 output->ModeSet = NV50SorModeSet;
210 output->SetClockMode = NV50SorSetClockMode;
211 output->Sense = NV50SorSense;
212 output->Detect = NV50SorDetect;
213 output->SetPowerMode = NV50SorSetPowerMode;
214 output->GetCurrentCrtc = NV50SorGetCurrentCrtc;
215}
216
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 @@
1/*
2 * Copyright 2007 Maarten Maathuis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#ifndef __NV50REG_H_
25#define __NV50REG_H_
26
27/* Bit 28 also does something, although i don't know what. */
28#define NV50_CONNECTOR_HOTPLUG_INTR 0x0000E050
29 #define NV50_CONNECTOR_HOTPLUG_INTR_PLUG_I2C0 (1 << 0)
30 #define NV50_CONNECTOR_HOTPLUG_INTR_PLUG_I2C1 (2 << 0)
31 #define NV50_CONNECTOR_HOTPLUG_INTR_UNPLUG_I2C0 (1 << 16)
32 #define NV50_CONNECTOR_HOTPLUG_INTR_UNPLUG_I2C1 (2 << 16)
33
34/* Writing 0x7FFF7FFF seems to be the way to acknowledge an interrupt. */
35/* There is also bit 7 and bit 23, but i also don't know what they do. */
36#define NV50_CONNECTOR_HOTPLUG_CTRL 0x0000E054
37 #define NV50_CONNECTOR_HOTPLUG_CTRL_PLUG_I2C0 (1 << 0)
38 #define NV50_CONNECTOR_HOTPLUG_CTRL_PLUG_I2C1 (2 << 0)
39 #define NV50_CONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C0 (1 << 16)
40 #define NV50_CONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C1 (2 << 16)
41
42/* This works for DVI->VGA adapters as well, providing the adapter supports it. */
43/* It's unknown if bits exist for i2c port > 1. */
44/* Renamed to avoid confusion with other instances of CONNECTED. */
45#define NV50_CONNECTOR_HOTPLUG_STATE 0x0000E104
46 #define NV50_CONNECTOR_HOTPLUG_STATE_I2C0_DETECT_PIN (1 << 2)
47 #define NV50_CONNECTOR_HOTPLUG_STATE_I2C1_DETECT_PIN (1 << 6)
48
49#define NV50_PCONNECTOR_I2C_PORT_0 0x0000e138
50#define NV50_PCONNECTOR_I2C_PORT_1 0x0000e150
51#define NV50_PCONNECTOR_I2C_PORT_2 0x0000e168
52#define NV50_PCONNECTOR_I2C_PORT_3 0x0000e180
53#define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240
54#define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258
55
56/* 0x00610024 is the state register to read, all it's bits also exist in 0x0061002C in the form of interrupt switches. */
57#define NV50_DISPLAY_SUPERVISOR 0x00610024
58 #define NV50_DISPLAY_SUPERVISOR_CRTC0 (1 << 2)
59 #define NV50_DISPLAY_SUPERVISOR_CRTC1 (2 << 2)
60 #define NV50_DISPLAY_SUPERVISOR_CRTCn (3 << 2)
61 #define NV50_DISPLAY_SUPERVISOR_CLK_MASK (7 << 4)
62 #define NV50_DISPLAY_SUPERVISOR_CLK_UPDATE (2 << 4)
63
64/* Two vblank interrupts arrive per blanking period, it could be rise and fall, i do not know. */
65/* If a vblank interrupt arrives, check NV50_DISPLAY_SUPERVISOR, it will show for which crtc (or both) it is. */
66/* Note that one crtc bit will always show, maybe it's updated when a vblank occurs? */
67/* Once modesetting goes into the kernel, we can ditch NV50CheckWriteVClk() and do it with interrupts. */
68/* Up until then, realise that most interrupts are not handled properly yet (and will stall your machine). */
69/* Bit 8 and 9 also exist for sure, but their purpose is unknown. */
70#define NV50_DISPLAY_SUPERVISOR_INTR 0x0061002C
71 #define NV50_DISPLAY_INTR_VBLANK_CRTC0 (1 << 2)
72 #define NV50_DISPLAY_INTR_VBLANK_CRTC1 (1 << 3)
73 #define NV50_DISPLAY_INTR_UNK1 (1 << 4)
74 #define NV50_DISPLAY_INTR_CLK_UPDATE (2 << 4)
75 #define NV50_DISPLAY_INTR_UNK4 (4 << 4)
76
77#define NV50_DISPLAY_UNK30_CTRL 0x00610030
78 #define NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK0 (1 << 9)
79 #define NV50_DISPLAY_UNK30_CTRL_UPDATE_VCLK1 (1 << 10)
80 #define NV50_DISPLAY_UNK30_CTRL_PENDING (1 << 31)
81
82#define NV50_DISPLAY_UNK50_CTRL 0x00610050
83 #define NV50_DISPLAY_UNK50_CTRL_CRTC0_ACTIVE (2 << 0)
84 #define NV50_DISPLAY_UNK50_CTRL_CRTC0_MASK (3 << 0)
85 #define NV50_DISPLAY_UNK50_CTRL_CRTC1_ACTIVE (2 << 8)
86 #define NV50_DISPLAY_UNK50_CTRL_CRTC1_MASK (3 << 8)
87
88/* I really don't know what this does, except that it's only revelant at start. */
89#define NV50_DISPLAY_UNK200_CTRL 0x00610200
90
91/* bit3 always activates itself, and bit 4 is some kind of switch. */
92#define NV50_CRTC0_CURSOR_CTRL2 0x00610270
93 #define NV50_CRTC_CURSOR_CTRL2_ON (1 << 0)
94 #define NV50_CRTC_CURSOR_CTRL2_OFF (0 << 0)
95 #define NV50_CRTC_CURSOR_CTRL2_STATUS_MASK (3 << 16)
96 #define NV50_CRTC_CURSOR_CTRL2_STATUS_ACTIVE (1 << 16)
97#define NV50_CRTC1_CURSOR_CTRL2 0x00610280
98
99#define NV50_DISPLAY_CTRL_STATE 0x00610300
100 #define NV50_DISPLAY_CTRL_STATE_DISABLE (0 << 0)
101 #define NV50_DISPLAY_CTRL_STATE_ENABLE (1 << 0)
102 #define NV50_DISPLAY_CTRL_STATE_PENDING (1 << 31)
103#define NV50_DISPLAY_CTRL_VAL 0x00610304
104
105#define NV50_DISPLAY_UNK_380 0x00610380
106/* Clamped to 256 MiB */
107#define NV50_DISPLAY_RAM_AMOUNT 0x00610384
108#define NV50_DISPLAY_UNK_388 0x00610388
109#define NV50_DISPLAY_UNK_38C 0x0061038C
110
111/* The registers in this range are normally accessed through display commands, with an offset of 0x540 for crtc1. */
112/* They also seem duplicated into the next register as well. */
113#define NV50_CRTC0_CLUT_MODE_VAL 0x00610A24
114#define NV50_CRTC0_SCALE_CTRL_VAL 0x00610A50
115#define NV50_CRTC0_CURSOR_CTRL_VAL 0x00610A58
116#define NV50_CRTC0_DEPTH_VAL 0x00610AC8
117#define NV50_CRTC0_CLOCK_VAL 0x00610AD0
118#define NV50_CRTC0_COLOR_CTRL_VAL 0x00610AE0
119#define NV50_CRTC0_SYNC_START_TO_BLANK_END_VAL 0x00610AE8
120#define NV50_CRTC0_MODE_UNK1_VAL 0x00610AF0
121#define NV50_CRTC0_DISPLAY_TOTAL_VAL 0x00610AF8
122#define NV50_CRTC0_SYNC_DURATION_VAL 0x00610B00
123/* For some reason this displayed the maximum framebuffer size for crtc0/dfp. */
124/* It was correct for crtc1/afp. */
125#define NV50_CRTC0_FB_SIZE_VAL 0x00610B18
126#define NV50_CRTC0_FB_PITCH_VAL 0x00610B20
127#define NV50_CRTC0_FB_POS_VAL 0x00610B28
128#define NV50_CRTC0_SCALE_CENTER_OFFSET_VAL 0x00610B38
129#define NV50_CRTC0_REAL_RES_VAL 0x00610B40
130/* I can't be 100% about the order of these two, as setting them differently locks up the card. */
131#define NV50_CRTC0_SCALE_RES1_VAL 0x00610B48
132#define NV50_CRTC0_SCALE_RES2_VAL 0x00610B50
133
134/* Some registers are based on extrapolation. */
135#define NV50_DAC0_MODE_CTRL_VAL 0x00610B58
136#define NV50_DAC1_MODE_CTRL_VAL 0x00610B60
137#define NV50_DAC2_MODE_CTRL_VAL 0x00610B68
138#define NV50_SOR0_MODE_CTRL_VAL 0x00610B70
139#define NV50_SOR1_MODE_CTRL_VAL 0x00610B78
140#define NV50_SOR2_MODE_CTRL_VAL 0x00610B80
141
142#define NV50_DAC0_MODE_CTRL2_VAL 0x00610BDC
143#define NV50_DAC1_MODE_CTRL2_VAL 0x00610BE4
144#define NV50_DAC2_MODE_CTRL2_VAL 0x00610BEC
145
146#define NV50_CRTC1_CLUT_MODE_VAL 0x00610F64
147#define NV50_CRTC1_SCALE_CTRL_VAL 0x00610F90
148#define NV50_CRTC1_CURSOR_CTRL_VAL 0x00610F98
149#define NV50_CRTC1_DEPTH_VAL 0x00611008
150#define NV50_CRTC1_CLOCK_VAL 0x00611010
151#define NV50_CRTC1_COLOR_CTRL_VAL 0x00611020
152#define NV50_CRTC1_SYNC_START_TO_BLANK_END_VAL 0x00611028
153#define NV50_CRTC1_MODE_UNK1_VAL 0x00611030
154#define NV50_CRTC1_DISPLAY_TOTAL_VAL 0x00611038
155#define NV50_CRTC1_SYNC_DURATION_VAL 0x00611040
156#define NV50_CRTC1_FB_SIZE_VAL 0x00611058
157#define NV50_CRTC1_FB_PITCH_VAL 0x00611060
158#define NV50_CRTC1_FB_POS_VAL 0x00611068
159#define NV50_CRTC1_SCALE_CENTER_OFFSET_VAL 0x00611078
160#define NV50_CRTC1_REAL_RES_VAL 0x00611080
161/* I can't be 100% about the order of these two, as setting them differently locks up the card. */
162#define NV50_CRTC1_SCALE_RES1_VAL 0x00611088
163#define NV50_CRTC1_SCALE_RES2_VAL 0x00611090
164
165/* These CLK_CTRL names are a bit of a guess, i do have my reasons though. */
166/* These connected indicators exist for crtc, dac and sor. */
167#define NV50_CRTC0_CLK_CTRL1 0x00614100
168 #define NV50_CRTC_CLK_CTRL1_CONNECTED (3 << 9)
169/* These are probably redrirected from 0x4000 range (very similar regs to nv40, maybe different order) */
170#define NV50_CRTC0_VPLL_A 0x00614104
171#define NV50_CRTC0_VPLL_B 0x00614108
172#define NV50_CRTC0_CLK_CTRL2 0x00614200
173
174/* These control some special modes, like dual link dvi, maybe they need another name? */
175#define NV50_DAC0_CLK_CTRL2 0x00614280
176#define NV50_SOR0_CLK_CTRL2 0x00614300
177
178#define NV50_CRTC1_CLK_CTRL1 0x00614900
179#define NV50_CRTC1_VPLL_A 0x00614904
180#define NV50_CRTC1_VPLL_B 0x00614908
181#define NV50_CRTC1_CLK_CTRL2 0x00614A00
182
183#define NV50_DAC1_CLK_CTRL2 0x00614A80
184#define NV50_SOR1_CLK_CTRL2 0x00614B00
185
186#define NV50_DAC2_CLK_CTRL2 0x00615280
187#define NV50_SOR2_CLK_CTRL2 0x00615300
188
189#define NV50_DAC0_DPMS_CTRL 0x0061A004
190 #define NV50_DAC_DPMS_CTRL_HSYNC_OFF (1 << 0)
191 #define NV50_DAC_DPMS_CTRL_VSYNC_OFF (1 << 2)
192 #define NV50_DAC_DPMS_CTRL_BLANKED (1 << 4)
193 #define NV50_DAC_DPMS_CTRL_OFF (1 << 6)
194 /* Some cards also use bit 22, why exactly is unknown. */
195 /* It seems that 1, 4 and 5 are present at bit0. bit4. bit16, bit20. */
196 /* No idea what the symmetry means precisely. */
197 #define NV50_DAC_DPMS_CTRL_DEFAULT_STATE (21 << 16)
198 #define NV50_DAC_DPMS_CTRL_PENDING (1 << 31)
199#define NV50_DAC0_LOAD_CTRL 0x0061A00C
200 #define NV50_DAC_LOAD_CTRL_ACTIVE (1 << 20)
201 #define NV50_DAC_LOAD_CTRL_PRESENT (7 << 27)
202 /* this a bit of a guess, as load detect is very fast */
203 #define NV50_DAC_LOAD_CTRL_DONE (1 << 31)
204/* These connected indicators exist for crtc, dac and sor. */
205/* The upper 4 bits seem to be some kind indicator. */
206/* The purpose of bit 1 is unknown, maybe some kind of reset? */
207#define NV50_DAC0_CLK_CTRL1 0x0061A010
208 #define NV50_DAC_CLK_CTRL1_CONNECTED (3 << 9)
209#define NV50_DAC1_DPMS_CTRL 0x0061A804
210#define NV50_DAC1_LOAD_CTRL 0x0061A80C
211#define NV50_DAC1_CLK_CTRL1 0x0061A810
212#define NV50_DAC2_DPMS_CTRL 0x0061B004
213#define NV50_DAC2_LOAD_CTRL 0x0061B00C
214#define NV50_DAC2_CLK_CTRL1 0x0061B010
215
216/* both SOR_DPMS and DAC_DPMS have a bit28, whose purpose is unknown atm. */
217#define NV50_SOR0_DPMS_CTRL 0x0061C004
218 #define NV50_SOR_DPMS_CTRL_MODE_ON (1 << 0)
219 #define NV50_SOR_DPMS_CTRL_PENDING (1 << 31)
220/* These connected indicators exist for crtc, dac and sor. */
221/* I don't know what bit27 does, it doesn't seem extremely important. */
222#define NV50_SOR0_CLK_CTRL1 0x0061C008
223 #define NV50_SOR_CLK_CTRL1_CONNECTED (3 << 9)
224/* Seems to be a default state, nothing that can RE'd in great detail. */
225#define NV50_SOR0_UNK00C 0x0061C00C
226#define NV50_SOR0_UNK010 0x0061C010
227#define NV50_SOR0_UNK014 0x0061C014
228#define NV50_SOR0_UNK018 0x0061C018
229
230#define NV50_SOR0_DPMS_STATE 0x0061C030
231 #define NV50_SOR_DPMS_STATE_ACTIVE (3 << 16) /* this does not show if DAC is active */
232 #define NV50_SOR_DPMS_STATE_BLANKED (8 << 16)
233 #define NV50_SOR_DPMS_STATE_WAIT (1 << 28)
234
235#define NV50_SOR1_DPMS_CTRL 0x0061C804
236#define NV50_SOR1_CLK_CTRL1 0x0061C808
237/* Seems to be a default state, nothing that can RE'd in any great detail. */
238#define NV50_SOR1_UNK00C 0x0061C80C
239#define NV50_SOR1_UNK010 0x0061C810
240#define NV50_SOR1_UNK014 0x0061C814
241#define NV50_SOR1_UNK018 0x0061C818
242
243#define NV50_SOR1_DPMS_STATE 0x0061C830
244
245#define NV50_SOR2_DPMS_CTRL 0x0061D004
246#define NV50_SOR2_CLK_CTRL1 0x0061D008
247/* Seems to be a default state, nothing that can RE'd in any great detail. */
248#define NV50_SOR2_UNK00C 0x0061D00C
249#define NV50_SOR2_UNK010 0x0061D010
250#define NV50_SOR2_UNK014 0x0061D014
251#define NV50_SOR2_UNK018 0x0061D018
252
253#define NV50_SOR2_DPMS_STATE 0x0061D030
254
255/* A few things seem to exist in the 0x0064XXXX range, but not much. */
256/* Each of these corresponds to a range in 0x006102XX. */
257/* The blob writes zero to these regs. */
258/* 0x00610200-0x0061020C, 0x00610200 seems special from all the rest. */
259#define NV50_UNK_640000 0x00640000
260/* 0x00610210-0x0061021C */
261#define NV50_UNK_641000 0x00641000
262/* 0x00610220-0x0061022C */
263/* Seems tv-out related somehow, the other two show up always. */
264#define NV50_UNK_642000 0x00642000
265/* 0x00610230-0x0061023C and 0x00610240-0x0061024C seem to be similar. */
266/* I think the correlation goes for all 0x0064X000, up to and including 6. */
267
268/* Write 0 to process the new position, seem to be write only registers. */
269#define NV50_CRTC0_CURSOR_POS_CTRL 0x00647080
270#define NV50_CRTC0_CURSOR_POS 0x00647084
271#define NV50_CRTC1_CURSOR_POS_CTRL 0x00648080
272#define NV50_CRTC1_CURSOR_POS 0x00648084
273
274/* These things below are so called "commands" */
275#define NV50_UPDATE_DISPLAY 0x80
276#define NV50_UNK84 0x84
277#define NV50_UNK88 0x88
278
279#define NV50_DAC0_MODE_CTRL 0x400
280 #define NV50_DAC_MODE_CTRL_OFF (0 << 0)
281 #define NV50_DAC_MODE_CTRL_CRTC0 (1 << 0)
282 #define NV50_DAC_MODE_CTRL_CRTC1 (1 << 1)
283#define NV50_DAC1_MODE_CTRL 0x480
284#define NV50_DAC2_MODE_CTRL 0x500
285
286#define NV50_DAC0_MODE_CTRL2 0x404
287 #define NV50_DAC_MODE_CTRL2_NHSYNC (1 << 0)
288 #define NV50_DAC_MODE_CTRL2_NVSYNC (2 << 0)
289#define NV50_DAC1_MODE_CTRL2 0x484
290#define NV50_DAC2_MODE_CTRL2 0x504
291
292#define NV50_SOR0_MODE_CTRL 0x600
293 #define NV50_SOR_MODE_CTRL_OFF (0 << 0)
294 #define NV50_SOR_MODE_CTRL_CRTC0 (1 << 0)
295 #define NV50_SOR_MODE_CTRL_CRTC1 (1 << 1)
296 #define NV50_SOR_MODE_CTRL_LVDS (0 << 8)
297 #define NV50_SOR_MODE_CTRL_TMDS (1 << 8)
298 #define NV50_SOR_MODE_CTRL_TMDS_DUAL_LINK (4 << 8)
299 #define NV50_SOR_MODE_CTRL_NHSYNC (1 << 12)
300 #define NV50_SOR_MODE_CTRL_NVSYNC (2 << 12)
301#define NV50_SOR1_MODE_CTRL 0x640
302#define NV50_SOR2_MODE_CTRL 0x680
303
304#define NV50_CRTC0_UNK800 0x800
305#define NV50_CRTC0_CLOCK 0x804
306#define NV50_CRTC0_INTERLACE 0x808
307
308/* 0x810 is a reasonable guess, nothing more. */
309#define NV50_CRTC0_DISPLAY_START 0x810
310#define NV50_CRTC0_DISPLAY_TOTAL 0x814
311#define NV50_CRTC0_SYNC_DURATION 0x818
312#define NV50_CRTC0_SYNC_START_TO_BLANK_END 0x81C
313#define NV50_CRTC0_MODE_UNK1 0x820
314#define NV50_CRTC0_MODE_UNK2 0x824
315
316#define NV50_CRTC0_UNK82C 0x82C
317
318/* You can't have a palette in 8 bit mode (=OFF) */
319#define NV50_CRTC0_CLUT_MODE 0x840
320 #define NV50_CRTC0_CLUT_MODE_BLANK 0x00000000
321 #define NV50_CRTC0_CLUT_MODE_OFF 0x80000000
322 #define NV50_CRTC0_CLUT_MODE_ON 0xC0000000
323#define NV50_CRTC0_CLUT_OFFSET 0x844
324
325/* Anyone know what part of the chip is triggered here precisely? */
326#define NV84_CRTC0_BLANK_UNK1 0x85C
327 #define NV84_CRTC0_BLANK_UNK1_BLANK 0x0
328 #define NV84_CRTC0_BLANK_UNK1_UNBLANK 0x1
329
330#define NV50_CRTC0_FB_OFFSET 0x860
331
332#define NV50_CRTC0_FB_SIZE 0x868
333#define NV50_CRTC0_FB_PITCH 0x86C
334
335#define NV50_CRTC0_DEPTH 0x870
336 #define NV50_CRTC0_DEPTH_8BPP 0x1E00
337 #define NV50_CRTC0_DEPTH_15BPP 0xE900
338 #define NV50_CRTC0_DEPTH_16BPP 0xE800
339 #define NV50_CRTC0_DEPTH_24BPP 0xCF00
340
341/* I'm openminded to better interpretations. */
342/* This is an educated guess. */
343/* NV50 has RAMDAC and TMDS offchip, so it's unlikely to be that. */
344#define NV50_CRTC0_BLANK_CTRL 0x874
345 #define NV50_CRTC0_BLANK_CTRL_BLANK 0x0
346 #define NV50_CRTC0_BLANK_CTRL_UNBLANK 0x1
347
348#define NV50_CRTC0_CURSOR_CTRL 0x880
349 #define NV50_CRTC0_CURSOR_CTRL_SHOW 0x85000000
350 #define NV50_CRTC0_CURSOR_CTRL_HIDE 0x05000000
351
352#define NV50_CRTC0_CURSOR_OFFSET 0x884
353
354/* Anyone know what part of the chip is triggered here precisely? */
355#define NV84_CRTC0_BLANK_UNK2 0x89C
356 #define NV84_CRTC0_BLANK_UNK2_BLANK 0x0
357 #define NV84_CRTC0_BLANK_UNK2_UNBLANK 0x1
358
359#define NV50_CRTC0_DITHERING_CTRL 0x8A0
360 #define NV50_CRTC0_DITHERING_CTRL_ON 0x11
361 #define NV50_CRTC0_DITHERING_CTRL_OFF 0x0
362
363#define NV50_CRTC0_SCALE_CTRL 0x8A4
364 #define NV50_CRTC0_SCALE_CTRL_SCALER_INACTIVE (0 << 0)
365 /* It doesn't seem to be needed, hence i wonder what it does precisely. */
366 #define NV50_CRTC0_SCALE_CTRL_SCALER_ACTIVE (9 << 0)
367#define NV50_CRTC0_COLOR_CTRL 0x8A8
368 #define NV50_CRTC_COLOR_CTRL_MODE_COLOR (4 << 16)
369
370#define NV50_CRTC0_FB_POS 0x8C0
371#define NV50_CRTC0_REAL_RES 0x8C8
372
373/* Added a macro, because the signed stuff can cause you problems very quickly. */
374#define NV50_CRTC0_SCALE_CENTER_OFFSET 0x8D4
375 #define NV50_CRTC_SCALE_CENTER_OFFSET_VAL(x, y) ((((unsigned)y << 16) & 0xFFFF0000) | (((unsigned)x) & 0x0000FFFF))
376/* Both of these are needed, otherwise nothing happens. */
377#define NV50_CRTC0_SCALE_RES1 0x8D8
378#define NV50_CRTC0_SCALE_RES2 0x8DC
379
380#define NV50_CRTC1_UNK800 0xC00
381#define NV50_CRTC1_CLOCK 0xC04
382#define NV50_CRTC1_INTERLACE 0xC08
383
384/* 0xC10 is a reasonable guess, nothing more. */
385#define NV50_CRTC1_DISPLAY_START 0xC10
386#define NV50_CRTC1_DISPLAY_TOTAL 0xC14
387#define NV50_CRTC1_SYNC_DURATION 0xC18
388#define NV50_CRTC1_SYNC_START_TO_BLANK_END 0xC1C
389#define NV50_CRTC1_MODE_UNK1 0xC20
390#define NV50_CRTC1_MODE_UNK2 0xC24
391
392#define NV50_CRTC1_CLUT_MODE 0xC40
393 #define NV50_CRTC1_CLUT_MODE_BLANK 0x00000000
394 #define NV50_CRTC1_CLUT_MODE_OFF 0x80000000
395 #define NV50_CRTC1_CLUT_MODE_ON 0xC0000000
396#define NV50_CRTC1_CLUT_OFFSET 0xC44
397
398/* Anyone know what part of the chip is triggered here precisely? */
399#define NV84_CRTC1_BLANK_UNK1 0xC5C
400 #define NV84_CRTC1_BLANK_UNK1_BLANK 0x0
401 #define NV84_CRTC1_BLANK_UNK1_UNBLANK 0x1
402
403#define NV50_CRTC1_FB_OFFSET 0xC60
404
405#define NV50_CRTC1_FB_SIZE 0xC68
406#define NV50_CRTC1_FB_PITCH 0xC6C
407
408#define NV50_CRTC1_DEPTH 0xC70
409 #define NV50_CRTC1_DEPTH_8BPP 0x1E00
410 #define NV50_CRTC1_DEPTH_15BPP 0xE900
411 #define NV50_CRTC1_DEPTH_16BPP 0xE800
412 #define NV50_CRTC1_DEPTH_24BPP 0xCF00
413
414/* I'm openminded to better interpretations. */
415#define NV50_CRTC1_BLANK_CTRL 0xC74
416 #define NV50_CRTC1_BLANK_CTRL_BLANK 0x0
417 #define NV50_CRTC1_BLANK_CTRL_UNBLANK 0x1
418
419#define NV50_CRTC1_CURSOR_CTRL 0xC80
420 #define NV50_CRTC1_CURSOR_CTRL_SHOW 0x85000000
421 #define NV50_CRTC1_CURSOR_CTRL_HIDE 0x05000000
422
423#define NV50_CRTC1_CURSOR_OFFSET 0xC84
424
425/* Anyone know what part of the chip is triggered here precisely? */
426#define NV84_CRTC1_BLANK_UNK2 0xC9C
427 #define NV84_CRTC1_BLANK_UNK2_BLANK 0x0
428 #define NV84_CRTC1_BLANK_UNK2_UNBLANK 0x1
429
430#define NV50_CRTC1_DITHERING_CTRL 0xCA0
431 #define NV50_CRTC1_DITHERING_CTRL_ON 0x11
432 #define NV50_CRTC1_DITHERING_CTRL_OFF 0x0
433
434#define NV50_CRTC1_SCALE_CTRL 0xCA4
435#define NV50_CRTC1_COLOR_CTRL 0xCA8
436
437#define NV50_CRTC1_FB_POS 0xCC0
438#define NV50_CRTC1_REAL_RES 0xCC8
439
440#define NV50_CRTC1_SCALE_CENTER_OFFSET 0xCD4
441/* Both of these are needed, otherwise nothing happens. */
442#define NV50_CRTC1_SCALE_RES1 0xCD8
443#define NV50_CRTC1_SCALE_RES2 0xCDC
444
445/* misc stuff */
446#define NV50_I2C_START 0x7
447#define NV50_I2C_STOP 0x3
448
449#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)
261 struct nouveau_grobj *blit; 261 struct nouveau_grobj *blit;
262 uint32_t class; 262 uint32_t class;
263 263
264 class = (pNv->WaitVSyncPossible) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT; 264 class = (pNv->NVArch > 0x11) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT;
265 265
266 if (!pNv->NvImageBlit) { 266 if (!pNv->NvImageBlit) {
267 if (nouveau_grobj_alloc(chan, NvImageBlit, class, 267 if (nouveau_grobj_alloc(chan, NvImageBlit, class,
@@ -283,7 +283,7 @@ NVAccelInitImageBlit(ScrnInfoPtr pScrn)
283 BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_OPERATION, 1); 283 BEGIN_RING(chan, blit, NV04_IMAGE_BLIT_OPERATION, 1);
284 OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_ROP_AND); 284 OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_ROP_AND);
285 285
286 if (pNv->WaitVSyncPossible) { 286 if (blit->grclass == NV12_IMAGE_BLIT) {
287 BEGIN_RING(chan, blit, 0x0120, 3); 287 BEGIN_RING(chan, blit, 0x0120, 3);
288 OUT_RING (chan, 0); 288 OUT_RING (chan, 0);
289 OUT_RING (chan, 1); 289 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 @@
1/*
2 * Copyright 2005-2006 Erik Waling
3 * Copyright 2006 Stephane Marchesin
4 * Copyright 2007-2009 Stuart Bennett
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "nv_include.h"
26
27#if defined(__FreeBSD__) || defined(__NetBSD__)
28#define bswap_16 bswap16
29#define bswap_32 bswap32
30#else
31#include <byteswap.h>
32#endif
33
34/* these defines are made up */
35#define NV_CIO_CRE_44_HEADA 0x0
36#define NV_CIO_CRE_44_HEADB 0x3
37#define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */
38#define LEGACY_I2C_CRT 0x80
39#define LEGACY_I2C_PANEL 0x81
40
41#define BIOSLOG(sip, fmt, arg...) NV_DEBUG(sip, fmt, ##arg)
42#define LOG_OLD_VALUE(x) //x
43
44#define BIOS_USLEEP(n) usleep(n)
45
46#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x))
47#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x))
48
49static int crtchead = 0;
50
51/* this will need remembering across a suspend */
52static uint32_t saved_nv_pfb_cfg0;
53
54typedef struct {
55 bool execute;
56 bool repeat;
57} init_exec_t;
58
59static inline uint16_t le16_to_cpu(const uint16_t x)
60{
61#if X_BYTE_ORDER == X_BIG_ENDIAN
62 return bswap_16(x);
63#else
64 return x;
65#endif
66}
67
68static inline uint32_t le32_to_cpu(const uint32_t x)
69{
70#if X_BYTE_ORDER == X_BIG_ENDIAN
71 return bswap_32(x);
72#else
73 return x;
74#endif
75}
76
77static bool nv_cksum(const uint8_t *data, unsigned int length)
78{
79 /* there's a few checksums in the BIOS, so here's a generic checking function */
80 int i;
81 uint8_t sum = 0;
82
83 for (i = 0; i < length; i++)
84 sum += data[i];
85
86 if (sum)
87 return true;
88
89 return false;
90}
91
92static int
93score_vbios(ScrnInfoPtr pScrn, const uint8_t *data, const bool writeable)
94{
95 if (!(data[0] == 0x55 && data[1] == 0xAA)) {
96 NV_TRACEWARN(pScrn, "... BIOS signature not found\n");
97 return 0;
98 }
99
100 if (nv_cksum(data, data[2] * 512)) {
101 NV_TRACEWARN(pScrn, "... BIOS checksum invalid\n");
102 /* if a ro image is somewhat bad, it's probably all rubbish */
103 return writeable ? 2 : 1;
104 } else
105 NV_TRACE(pScrn, "... appears to be valid\n");
106
107 return 3;
108}
109
110static void load_vbios_prom(NVPtr pNv, uint8_t *data)
111{
112 uint32_t pci_nv_20, save_pci_nv_20;
113 int pcir_ptr;
114 int i;
115
116 if (pNv->Architecture >= NV_ARCH_50)
117 pci_nv_20 = 0x88050;
118 else
119 pci_nv_20 = NV_PBUS_PCI_NV_20;
120
121 /* enable ROM access */
122 save_pci_nv_20 = nvReadMC(pNv, pci_nv_20);
123 nvWriteMC(pNv, pci_nv_20,
124 save_pci_nv_20 & ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
125
126 /* bail if no rom signature */
127 if (NV_RD08(pNv->REGS, NV_PROM_OFFSET) != 0x55 ||
128 NV_RD08(pNv->REGS, NV_PROM_OFFSET + 1) != 0xaa)
129 goto out;
130
131 /* additional check (see note below) - read PCI record header */
132 pcir_ptr = NV_RD08(pNv->REGS, NV_PROM_OFFSET + 0x18) |
133 NV_RD08(pNv->REGS, NV_PROM_OFFSET + 0x19) << 8;
134 if (NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr) != 'P' ||
135 NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 1) != 'C' ||
136 NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 2) != 'I' ||
137 NV_RD08(pNv->REGS, NV_PROM_OFFSET + pcir_ptr + 3) != 'R')
138 goto out;
139
140 /* on some 6600GT/6800LE prom reads are messed up. nvclock alleges a
141 * a good read may be obtained by waiting or re-reading (cargocult: 5x)
142 * each byte. we'll hope pramin has something usable instead
143 */
144 for (i = 0; i < NV_PROM_SIZE; i++)
145 data[i] = NV_RD08(pNv->REGS, NV_PROM_OFFSET + i);
146
147out:
148 /* disable ROM access */
149 nvWriteMC(pNv, pci_nv_20,
150 save_pci_nv_20 | NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
151}
152
153static void load_vbios_pramin(NVPtr pNv, uint8_t *data)
154{
155 uint32_t old_bar0_pramin = 0;
156 int i;
157
158 if (pNv->Architecture >= NV_ARCH_50) {
159 uint32_t vbios_vram = (NV_RD32(pNv->REGS, 0x619f04) & ~0xff) << 8;
160
161 if (!vbios_vram)
162 vbios_vram = (NV_RD32(pNv->REGS, 0x1700) << 16) + 0xf0000;
163
164 old_bar0_pramin = NV_RD32(pNv->REGS, 0x1700);
165 NV_WR32(pNv->REGS, 0x1700, vbios_vram >> 16);
166 }
167
168 /* bail if no rom signature */
169 if (NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET) != 0x55 ||
170 NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET + 1) != 0xaa)
171 goto out;
172
173 for (i = 0; i < NV_PROM_SIZE; i++)
174 data[i] = NV_RD08(pNv->REGS, NV_PRAMIN_OFFSET + i);
175
176out:
177 if (pNv->Architecture >= NV_ARCH_50)
178 NV_WR32(pNv->REGS, 0x1700, old_bar0_pramin);
179}
180
181static void load_vbios_pci(NVPtr pNv, uint8_t *data)
182{
183 pci_device_read_rom(pNv->PciInfo, data);
184}
185
186struct methods {
187 const char desc[8];
188 void (*loadbios)(NVPtr, uint8_t *);
189 const bool rw;
190 int score;
191};
192
193static struct methods nv04_methods[] = {
194 { "PROM", load_vbios_prom, false },
195 { "PRAMIN", load_vbios_pramin, true },
196 { "PCI ROM", load_vbios_pci, true },
197 { }
198};
199
200static struct methods nv50_methods[] = {
201 { "PRAMIN", load_vbios_pramin, true },
202 { "PROM", load_vbios_prom, false },
203 { "PCI ROM", load_vbios_pci, true },
204 { }
205};
206
207static bool NVShadowVBIOS(ScrnInfoPtr pScrn, uint8_t *data)
208{
209 NVPtr pNv = NVPTR(pScrn);
210 struct methods *methods, *method;
211 int testscore = 3;
212
213 if (pNv->Architecture < NV_ARCH_50)
214 methods = nv04_methods;
215 else
216 methods = nv50_methods;
217
218 method = methods;
219 while (method->loadbios) {
220 NV_TRACE(pScrn, "Attempting to load BIOS image from %s\n",
221 method->desc);
222 data[0] = data[1] = 0; /* avoid reuse of previous image */
223 method->loadbios(pNv, data);
224 method->score = score_vbios(pScrn, data, method->rw);
225 if (method->score == testscore)
226 return true;
227 method++;
228 }
229
230 while (--testscore > 0) {
231 method = methods;
232 while (method->loadbios) {
233 if (method->score == testscore) {
234 NV_TRACE(pScrn, "Using BIOS image from %s\n",
235 method->desc);
236 method->loadbios(pNv, data);
237 return true;
238 }
239 method++;
240 }
241 }
242
243 NV_ERROR(pScrn, "No valid BIOS image found\n");
244 return false;
245}
246
247typedef struct {
248 char* name;
249 uint8_t id;
250 int length;
251 int length_offset;
252 int length_multiplier;
253 bool (*handler)(ScrnInfoPtr pScrn, struct nvbios *, uint16_t, init_exec_t *);
254} init_tbl_entry_t;
255
256typedef struct {
257 uint8_t id[2];
258 uint16_t length;
259 uint16_t offset;
260} bit_entry_t;
261
262static int parse_init_table(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset, init_exec_t *iexec);
263
264#define MACRO_INDEX_SIZE 2
265#define MACRO_SIZE 8
266#define CONDITION_SIZE 12
267#define IO_FLAG_CONDITION_SIZE 9
268#define IO_CONDITION_SIZE 5
269#define MEM_INIT_SIZE 66
270
271static void still_alive(void)
272{
273// sync();
274// BIOS_USLEEP(2000);
275}
276
277static uint32_t
278munge_reg(ScrnInfoPtr pScrn, uint32_t reg)
279{
280 NVPtr pNv = NVPTR(pScrn);
281
282 if (pNv->Architecture < NV_ARCH_50)
283 return reg;
284
285 if (reg & 0x40000000)
286 reg += pNv->VBIOS.display.head * 0x800;
287
288 reg &= ~(0x40000000);
289 return reg;
290}
291
292static int valid_reg(ScrnInfoPtr pScrn, uint32_t reg)
293{
294 NVPtr pNv = NVPTR(pScrn);
295
296 /* C51 has misaligned regs on purpose. Marvellous */
297 if (reg & 0x2 || (reg & 0x1 && pNv->VBIOS.pub.chip_version != 0x51)) {
298 NV_ERROR(pScrn, "========== misaligned reg 0x%08X ==========\n",
299 reg);
300 return 0;
301 }
302 /* warn on C51 regs that haven't been verified accessible in mmiotracing */
303 if (reg & 0x1 && pNv->VBIOS.pub.chip_version == 0x51 &&
304 reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
305 NV_WARN(pScrn, "=== C51 misaligned reg 0x%08X not verified ===\n",
306 reg);
307
308 #define WITHIN(x,y,z) ((x>=y)&&(x<=y+z))
309 if (WITHIN(reg,NV_PMC_OFFSET,NV_PMC_SIZE))
310 return 1;
311 if (WITHIN(reg,NV_PBUS_OFFSET,NV_PBUS_SIZE))
312 return 1;
313 if (WITHIN(reg,NV_PFIFO_OFFSET,NV_PFIFO_SIZE))
314 return 1;
315 /* maybe a little large, but it will do for the moment. */
316 if (pNv->Architecture == NV_ARCH_50 && WITHIN(reg, 0x1000, 0xEFFF))
317 return 1;
318 if (pNv->VBIOS.pub.chip_version >= 0x30 && WITHIN(reg,0x4000,0x600))
319 return 1;
320 if (pNv->VBIOS.pub.chip_version >= 0x40 && WITHIN(reg,0xc000,0x48))
321 return 1;
322 if (pNv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
323 return 1;
324 if (pNv->VBIOS.pub.chip_version >= 0x40) {
325 if (reg == 0x00011014 || reg == 0x00020328)
326 return 1;
327 if (WITHIN(reg,0x88000,NV_PBUS_SIZE)) /* new PBUS */
328 return 1;
329 }
330 if (pNv->Architecture == NV_ARCH_50) {
331 /* No clue what they do, but because they are outside normal
332 * ranges we' better list them seperately. */
333 if (reg == 0x00020018 || reg == 0x0002004C ||
334 reg == 0x00020060 || reg == 0x00021218 ||
335 reg == 0x0002130C || reg == 0x00089008 ||
336 reg == 0x00089028)
337 return 1;
338 }
339 if (WITHIN(reg,NV_PFB_OFFSET,NV_PFB_SIZE))
340 return 1;
341 if (WITHIN(reg,NV_PEXTDEV_OFFSET,NV_PEXTDEV_SIZE))
342 return 1;
343 if (WITHIN(reg,NV_PCRTC0_OFFSET,NV_PCRTC0_SIZE * 2))
344 return 1;
345 if (pNv->Architecture == NV_ARCH_50 &&
346 WITHIN(reg, NV50_DISPLAY_OFFSET, NV50_DISPLAY_SIZE))
347 return 1;
348 if (WITHIN(reg,NV_PRAMDAC0_OFFSET,NV_PRAMDAC0_SIZE * 2))
349 return 1;
350 if (pNv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
351 return 1;
352 if (pNv->VBIOS.pub.chip_version == 0x51 && WITHIN(reg,NV_PRAMIN_OFFSET,NV_PRAMIN_SIZE))
353 return 1;
354 #undef WITHIN
355
356 NV_ERROR(pScrn, "========== unknown reg 0x%08X ==========\n", reg);
357
358 return 0;
359}
360
361static bool valid_idx_port(ScrnInfoPtr pScrn, uint16_t port)
362{
363 /* if adding more ports here, the read/write functions below will need
364 * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is
365 * used for the port in question
366 */
367 if (port == NV_CIO_CRX__COLOR)
368 return true;
369 if (port == NV_VIO_SRX)
370 return true;
371
372 NV_ERROR(pScrn, "========== unknown indexed io port 0x%04X ==========\n",
373 port);
374
375 return false;
376}
377
378static bool valid_port(ScrnInfoPtr pScrn, uint16_t port)
379{
380 /* if adding more ports here, the read/write functions below will need
381 * updating so that the correct mmio range (PRMCIO, PRMDIO, PRMVIO) is
382 * used for the port in question
383 */
384 if (port == NV_VIO_VSE2)
385 return true;
386
387 NV_ERROR(pScrn, "========== unknown io port 0x%04X ==========\n", port);
388
389 return false;
390}
391
392static uint32_t bios_rd32(ScrnInfoPtr pScrn, uint32_t reg)
393{
394 NVPtr pNv = NVPTR(pScrn);
395 uint32_t data;
396
397 reg = munge_reg(pScrn, reg);
398 if (!valid_reg(pScrn, reg))
399 return 0;
400
401 /* C51 sometimes uses regs with bit0 set in the address. For these
402 * cases there should exist a translation in a BIOS table to an IO
403 * port address which the BIOS uses for accessing the reg
404 *
405 * These only seem to appear for the power control regs to a flat panel,
406 * and the GPIO regs at 0x60081*. In C51 mmio traces the normal regs
407 * for 0x1308 and 0x1310 are used - hence the mask below. An S3
408 * suspend-resume mmio trace from a C51 will be required to see if this
409 * is true for the power microcode in 0x14.., or whether the direct IO
410 * port access method is needed
411 */
412 if (reg & 0x1)
413 reg &= ~0x1;
414
415 data = NV_RD32(pNv->REGS, reg);
416
417 BIOSLOG(pScrn, " Read: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
418
419 return data;
420}
421
422static void bios_wr32(ScrnInfoPtr pScrn, uint32_t reg, uint32_t data)
423{
424 NVPtr pNv = NVPTR(pScrn);
425
426 reg = munge_reg(pScrn, reg);
427 if (!valid_reg(pScrn, reg))
428 return;
429
430 /* see note in bios_rd32 */
431 if (reg & 0x1)
432 reg &= 0xfffffffe;
433
434 LOG_OLD_VALUE(bios_rd32(pScrn, reg));
435 BIOSLOG(pScrn, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
436
437 if (pNv->VBIOS.execute) {
438 still_alive();
439 NV_WR32(pNv->REGS, reg, data);
440 }
441}
442
443static uint8_t bios_idxprt_rd(ScrnInfoPtr pScrn, uint16_t port, uint8_t index)
444{
445 NVPtr pNv = NVPTR(pScrn);
446 uint8_t data;
447
448 if (!valid_idx_port(pScrn, port))
449 return 0;
450
451 if (port == NV_VIO_SRX)
452 data = NVReadVgaSeq(pNv, crtchead, index);
453 else /* assume NV_CIO_CRX__COLOR */
454 data = NVReadVgaCrtc(pNv, crtchead, index);
455
456 BIOSLOG(pScrn, " Indexed IO read: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
457 port, index, crtchead, data);
458
459 return data;
460}
461
462static void bios_idxprt_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t index, uint8_t data)
463{
464 NVPtr pNv = NVPTR(pScrn);
465
466 if (!valid_idx_port(pScrn, port))
467 return;
468
469 /* The current head is maintained in a file scope variable crtchead.
470 * We trap changes to CR44 and update the head variable and hence the
471 * register set written.
472 * As CR44 only exists on CRTC0, we update crtchead to head0 in advance
473 * of the write, and to head1 after the write
474 */
475 if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && data != NV_CIO_CRE_44_HEADB)
476 crtchead = 0;
477
478 LOG_OLD_VALUE(bios_idxprt_rd(pScrn, port, index));
479 BIOSLOG(pScrn, " Indexed IO write: Port: 0x%04X, Index: 0x%02X, Head: 0x%02X, Data: 0x%02X\n",
480 port, index, crtchead, data);
481
482 if (pNv->VBIOS.execute) {
483 still_alive();
484 if (port == NV_VIO_SRX)
485 NVWriteVgaSeq(pNv, crtchead, index, data);
486 else /* assume NV_CIO_CRX__COLOR */
487 NVWriteVgaCrtc(pNv, crtchead, index, data);
488 }
489
490 if (port == NV_CIO_CRX__COLOR && index == NV_CIO_CRE_44 && data == NV_CIO_CRE_44_HEADB)
491 crtchead = 1;
492}
493
494static uint8_t bios_port_rd(ScrnInfoPtr pScrn, uint16_t port)
495{
496 NVPtr pNv = NVPTR(pScrn);
497 uint8_t data;
498
499 if (!valid_port(pScrn, port))
500 return 0;
501
502 data = NVReadPRMVIO(pNv, crtchead, NV_PRMVIO0_OFFSET + port);
503
504 BIOSLOG(pScrn, " IO read: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n",
505 port, crtchead, data);
506
507 return data;
508}
509
510static void bios_port_wr(ScrnInfoPtr pScrn, uint16_t port, uint8_t data)
511{
512 NVPtr pNv = NVPTR(pScrn);
513
514 if (!valid_port(pScrn, port))
515 return;
516
517 LOG_OLD_VALUE(bios_port_rd(pScrn, port));
518 BIOSLOG(pScrn, " IO write: Port: 0x%04X, Head: 0x%02X, Data: 0x%02X\n",
519 port, crtchead, data);
520
521 if (pNv->VBIOS.execute) {
522 still_alive();
523 NVWritePRMVIO(pNv, crtchead, NV_PRMVIO0_OFFSET + port, data);
524 }
525}
526
527static bool io_flag_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond)
528{
529 /* The IO flag condition entry has 2 bytes for the CRTC port; 1 byte
530 * for the CRTC index; 1 byte for the mask to apply to the value
531 * retrieved from the CRTC; 1 byte for the shift right to apply to the
532 * masked CRTC value; 2 bytes for the offset to the flag array, to
533 * which the shifted value is added; 1 byte for the mask applied to the
534 * value read from the flag array; and 1 byte for the value to compare
535 * against the masked byte from the flag table.
536 */
537
538 uint16_t condptr = bios->io_flag_condition_tbl_ptr + cond * IO_FLAG_CONDITION_SIZE;
539 uint16_t crtcport = ROM16(bios->data[condptr]);
540 uint8_t crtcindex = bios->data[condptr + 2];
541 uint8_t mask = bios->data[condptr + 3];
542 uint8_t shift = bios->data[condptr + 4];
543 uint16_t flagarray = ROM16(bios->data[condptr + 5]);
544 uint8_t flagarraymask = bios->data[condptr + 7];
545 uint8_t cmpval = bios->data[condptr + 8];
546 uint8_t data;
547
548 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",
549 offset, crtcport, crtcindex, mask, shift, flagarray, flagarraymask, cmpval);
550
551 data = bios_idxprt_rd(pScrn, crtcport, crtcindex);
552
553 data = bios->data[flagarray + ((data & mask) >> shift)];
554 data &= flagarraymask;
555
556 BIOSLOG(pScrn, "0x%04X: Checking if 0x%02X equals 0x%02X\n", offset, data, cmpval);
557
558 return (data == cmpval);
559}
560
561static bool bios_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond)
562{
563 /* The condition table entry has 4 bytes for the address of the
564 * register to check, 4 bytes for a mask to apply to the register and
565 * 4 for a test comparison value
566 */
567
568 uint16_t condptr = bios->condition_tbl_ptr + cond * CONDITION_SIZE;
569 uint32_t reg = ROM32(bios->data[condptr]);
570 uint32_t mask = ROM32(bios->data[condptr + 4]);
571 uint32_t cmpval = ROM32(bios->data[condptr + 8]);
572 uint32_t data;
573
574 BIOSLOG(pScrn, "0x%04X: Cond: 0x%02X, Reg: 0x%08X, Mask: 0x%08X\n",
575 offset, cond, reg, mask);
576
577 data = bios_rd32(pScrn, reg) & mask;
578
579 BIOSLOG(pScrn, "0x%04X: Checking if 0x%08X equals 0x%08X\n",
580 offset, data, cmpval);
581
582 return (data == cmpval);
583}
584
585static bool io_condition_met(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, uint8_t cond)
586{
587 /* The IO condition entry has 2 bytes for the IO port address; 1 byte
588 * for the index to write to io_port; 1 byte for the mask to apply to
589 * the byte read from io_port+1; and 1 byte for the value to compare
590 * against the masked byte.
591 */
592
593 uint16_t condptr = bios->io_condition_tbl_ptr + cond * IO_CONDITION_SIZE;
594 uint16_t io_port = ROM16(bios->data[condptr]);
595 uint8_t port_index = bios->data[condptr + 2];
596 uint8_t mask = bios->data[condptr + 3];
597 uint8_t cmpval = bios->data[condptr + 4];
598
599 uint8_t data = bios_idxprt_rd(pScrn, io_port, port_index) & mask;
600
601 BIOSLOG(pScrn, "0x%04X: Checking if 0x%02X equals 0x%02X\n",
602 offset, data, cmpval);
603
604 return (data == cmpval);
605}
606
607static int setPLL(ScrnInfoPtr pScrn, struct nvbios *bios, uint32_t reg, uint32_t clk)
608{
609 /* clk in kHz */
610 struct pll_lims pll_lim;
611 int ret;
612 struct nouveau_pll_vals pllvals;
613
614 /* high regs (such as in the mac g5 table) are not -= 4 */
615 if ((ret = get_pll_limits(pScrn, reg > 0x405c ? reg : reg - 4, &pll_lim)))
616 return ret;
617
618 if (!(clk = nouveau_calc_pll_mnp(pScrn, &pll_lim, clk, &pllvals)))
619 return -ERANGE;
620
621 if (bios->execute) {
622 still_alive();
623 nouveau_hw_setpll(pScrn, reg, &pllvals);
624 }
625
626 return 0;
627}
628
629static int dcb_entry_idx_from_crtchead(ScrnInfoPtr pScrn)
630{
631 /* for the results of this function to be correct, CR44 must have been
632 * set (using bios_idxprt_wr to set crtchead), CR58 set for CR57 = 0,
633 * and the DCB table parsed, before the script calling the function is
634 * run. run_digital_op_script is example of how to do such setup
635 */
636
637 uint8_t dcb_entry = NVReadVgaCrtc5758(NVPTR(pScrn), crtchead, 0);
638
639 if (dcb_entry > NVPTR(pScrn)->VBIOS.bdcb.dcb.entries) {
640 NV_ERROR(pScrn, "CR58 doesn't have a valid DCB entry currently "
641 "(%02X)\n", dcb_entry);
642 dcb_entry = 0x7f; /* unused / invalid marker */
643 }
644
645 return dcb_entry;
646}
647
648static int init_dcb_i2c_entry(ScrnInfoPtr pScrn, struct nvbios *bios, int index);
649
650static int
651create_i2c_device(ScrnInfoPtr pScrn, struct nvbios *bios, int i2c_index, int address, I2CDevRec *i2cdev)
652{
653 struct bios_parsed_dcb *bdcb = &bios->bdcb;
654 int ret;
655
656 if (i2c_index == 0xff) {
657 /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
658 int idx = dcb_entry_idx_from_crtchead(pScrn), shift = 0;
659 int default_indices = bdcb->i2c_default_indices;
660
661 if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default)
662 shift = 4;
663
664 i2c_index = (default_indices >> shift) & 0xf;
665 }
666 if (i2c_index == 0x80) /* g80+ */
667 i2c_index = bdcb->i2c_default_indices & 0xf;
668
669 if ((ret = init_dcb_i2c_entry(pScrn, bios, i2c_index)))
670 return ret;
671
672 memset(i2cdev, 0, sizeof(I2CDevRec));
673 i2cdev->DevName = "init script device";
674 i2cdev->pI2CBus = bdcb->dcb.i2c[i2c_index].chan;
675 i2cdev->SlaveAddr = address;
676 if (!xf86I2CDevInit(i2cdev)) {
677 NV_ERROR(pScrn, "Couldn't add I2C device\n");
678 return -EINVAL;
679 }
680
681 return 0;
682}
683
684static uint32_t get_tmds_index_reg(ScrnInfoPtr pScrn, uint8_t mlv)
685{
686 /* For mlv < 0x80, it is an index into a table of TMDS base addresses
687 * For mlv == 0x80 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
688 * to index a table of offsets to the basic 0x6808b0 address
689 * For mlv == 0x81 use the "or" value of the dcb_entry indexed by CR58 for CR57 = 0
690 * to index a table of offsets to the basic 0x6808b0 address, and then flip the offset by 8
691 */
692
693 NVPtr pNv = NVPTR(pScrn);
694 const int pramdac_offset[13] = {0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000};
695 const uint32_t pramdac_table[4] = {0x6808b0, 0x6808b8, 0x6828b0, 0x6828b8};
696
697 if (mlv >= 0x80) {
698 int dcb_entry, dacoffset;
699
700 /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
701 if ((dcb_entry = dcb_entry_idx_from_crtchead(pScrn)) == 0x7f)
702 return 0;
703 dacoffset = pramdac_offset[pNv->VBIOS.bdcb.dcb.entry[dcb_entry].or];
704 if (mlv == 0x81)
705 dacoffset ^= 8;
706 return (0x6808b0 + dacoffset);
707 } else {
708 if (mlv > (sizeof(pramdac_table) / sizeof(uint32_t))) {
709 NV_ERROR(pScrn, "Magic Lookup Value too big (%02X)\n", mlv);
710 return 0;
711 }
712 return pramdac_table[mlv];
713 }
714}
715
716static bool init_io_restrict_prog(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
717{
718 /* INIT_IO_RESTRICT_PROG opcode: 0x32 ('2')
719 *
720 * offset (8 bit): opcode
721 * offset + 1 (16 bit): CRTC port
722 * offset + 3 (8 bit): CRTC index
723 * offset + 4 (8 bit): mask
724 * offset + 5 (8 bit): shift
725 * offset + 6 (8 bit): count
726 * offset + 7 (32 bit): register
727 * offset + 11 (32 bit): configuration 1
728 * ...
729 *
730 * Starting at offset + 11 there are "count" 32 bit values.
731 * To find out which value to use read index "CRTC index" on "CRTC port",
732 * AND this value with "mask" and then bit shift right "shift" bits.
733 * Read the appropriate value using this index and write to "register"
734 */
735
736 uint16_t crtcport = ROM16(bios->data[offset + 1]);
737 uint8_t crtcindex = bios->data[offset + 3];
738 uint8_t mask = bios->data[offset + 4];
739 uint8_t shift = bios->data[offset + 5];
740 uint8_t count = bios->data[offset + 6];
741 uint32_t reg = ROM32(bios->data[offset + 7]);
742 uint8_t config;
743 uint32_t configval;
744
745 if (!iexec->execute)
746 return true;
747
748 BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
749 offset, crtcport, crtcindex, mask, shift, count, reg);
750
751 config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
752 if (config > count) {
753 NV_ERROR(pScrn,
754 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
755 offset, config, count);
756 return false;
757 }
758
759 configval = ROM32(bios->data[offset + 11 + config * 4]);
760
761 BIOSLOG(pScrn, "0x%04X: Writing config %02X\n", offset, config);
762
763 bios_wr32(pScrn, reg, configval);
764
765 return true;
766}
767
768static bool init_repeat(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
769{
770 /* INIT_REPEAT opcode: 0x33 ('3')
771 *
772 * offset (8 bit): opcode
773 * offset + 1 (8 bit): count
774 *
775 * Execute script following this opcode up to INIT_REPEAT_END
776 * "count" times
777 */
778
779 uint8_t count = bios->data[offset + 1];
780 uint8_t i;
781
782 /* no iexec->execute check by design */
783
784 BIOSLOG(pScrn, "0x%04X: Repeating following segment %d times\n", offset, count);
785
786 iexec->repeat = true;
787
788 /* count - 1, as the script block will execute once when we leave this
789 * opcode -- this is compatible with bios behaviour as:
790 * a) the block is always executed at least once, even if count == 0
791 * b) the bios interpreter skips to the op following INIT_END_REPEAT,
792 * while we don't
793 */
794 for (i = 0; i < count - 1; i++)
795 parse_init_table(pScrn, bios, offset + 2, iexec);
796
797 iexec->repeat = false;
798
799 return true;
800}
801
802static bool init_io_restrict_pll(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
803{
804 /* INIT_IO_RESTRICT_PLL opcode: 0x34 ('4')
805 *
806 * offset (8 bit): opcode
807 * offset + 1 (16 bit): CRTC port
808 * offset + 3 (8 bit): CRTC index
809 * offset + 4 (8 bit): mask
810 * offset + 5 (8 bit): shift
811 * offset + 6 (8 bit): IO flag condition index
812 * offset + 7 (8 bit): count
813 * offset + 8 (32 bit): register
814 * offset + 12 (16 bit): frequency 1
815 * ...
816 *
817 * Starting at offset + 12 there are "count" 16 bit frequencies (10kHz).
818 * Set PLL register "register" to coefficients for frequency n,
819 * selected by reading index "CRTC index" of "CRTC port" ANDed with
820 * "mask" and shifted right by "shift". If "IO flag condition index" > 0,
821 * and condition met, double frequency before setting it.
822 */
823
824 uint16_t crtcport = ROM16(bios->data[offset + 1]);
825 uint8_t crtcindex = bios->data[offset + 3];
826 uint8_t mask = bios->data[offset + 4];
827 uint8_t shift = bios->data[offset + 5];
828 int8_t io_flag_condition_idx = bios->data[offset + 6];
829 uint8_t count = bios->data[offset + 7];
830 uint32_t reg = ROM32(bios->data[offset + 8]);
831 uint8_t config;
832 uint16_t freq;
833
834 if (!iexec->execute)
835 return true;
836
837 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",
838 offset, crtcport, crtcindex, mask, shift, io_flag_condition_idx, count, reg);
839
840 config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
841 if (config > count) {
842 NV_ERROR(pScrn,
843 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
844 offset, config, count);
845 return false;
846 }
847
848 freq = ROM16(bios->data[offset + 12 + config * 2]);
849
850 if (io_flag_condition_idx > 0) {
851 if (io_flag_condition_met(pScrn, bios, offset, io_flag_condition_idx)) {
852 BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- frequency doubled\n", offset);
853 freq *= 2;
854 } else
855 BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- frequency unchanged\n", offset);
856 }
857
858 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %d0kHz\n",
859 offset, reg, config, freq);
860
861 setPLL(pScrn, bios, reg, freq * 10);
862
863 return true;
864}
865
866static bool init_end_repeat(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
867{
868 /* INIT_END_REPEAT opcode: 0x36 ('6')
869 *
870 * offset (8 bit): opcode
871 *
872 * Marks the end of the block for INIT_REPEAT to repeat
873 */
874
875 /* no iexec->execute check by design */
876
877 /* iexec->repeat flag necessary to go past INIT_END_REPEAT opcode when
878 * we're not in repeat mode
879 */
880 if (iexec->repeat)
881 return false;
882
883 return true;
884}
885
886static bool init_copy(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
887{
888 /* INIT_COPY opcode: 0x37 ('7')
889 *
890 * offset (8 bit): opcode
891 * offset + 1 (32 bit): register
892 * offset + 5 (8 bit): shift
893 * offset + 6 (8 bit): srcmask
894 * offset + 7 (16 bit): CRTC port
895 * offset + 9 (8 bit): CRTC index
896 * offset + 10 (8 bit): mask
897 *
898 * Read index "CRTC index" on "CRTC port", AND with "mask", OR with
899 * (REGVAL("register") >> "shift" & "srcmask") and write-back to CRTC port
900 */
901
902 uint32_t reg = ROM32(bios->data[offset + 1]);
903 uint8_t shift = bios->data[offset + 5];
904 uint8_t srcmask = bios->data[offset + 6];
905 uint16_t crtcport = ROM16(bios->data[offset + 7]);
906 uint8_t crtcindex = bios->data[offset + 9];
907 uint8_t mask = bios->data[offset + 10];
908 uint32_t data;
909 uint8_t crtcdata;
910
911 if (!iexec->execute)
912 return true;
913
914 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n",
915 offset, reg, shift, srcmask, crtcport, crtcindex, mask);
916
917 data = bios_rd32(pScrn, reg);
918
919 if (shift < 0x80)
920 data >>= shift;
921 else
922 data <<= (0x100 - shift);
923
924 data &= srcmask;
925
926 crtcdata = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) | (uint8_t)data;
927 bios_idxprt_wr(pScrn, crtcport, crtcindex, crtcdata);
928
929 return true;
930}
931
932static bool init_not(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
933{
934 /* INIT_NOT opcode: 0x38 ('8')
935 *
936 * offset (8 bit): opcode
937 *
938 * Invert the current execute / no-execute condition (i.e. "else")
939 */
940 if (iexec->execute)
941 BIOSLOG(pScrn, "0x%04X: ------ Skipping following commands ------\n", offset);
942 else
943 BIOSLOG(pScrn, "0x%04X: ------ Executing following commands ------\n", offset);
944
945 iexec->execute = !iexec->execute;
946 return true;
947}
948
949static bool init_io_flag_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
950{
951 /* INIT_IO_FLAG_CONDITION opcode: 0x39 ('9')
952 *
953 * offset (8 bit): opcode
954 * offset + 1 (8 bit): condition number
955 *
956 * Check condition "condition number" in the IO flag condition table.
957 * If condition not met skip subsequent opcodes until condition is
958 * inverted (INIT_NOT), or we hit INIT_RESUME
959 */
960
961 uint8_t cond = bios->data[offset + 1];
962
963 if (!iexec->execute)
964 return true;
965
966 if (io_flag_condition_met(pScrn, bios, offset, cond))
967 BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
968 else {
969 BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
970 iexec->execute = false;
971 }
972
973 return true;
974}
975
976static bool init_idx_addr_latched(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
977{
978 /* INIT_INDEX_ADDRESS_LATCHED opcode: 0x49 ('I')
979 *
980 * offset (8 bit): opcode
981 * offset + 1 (32 bit): control register
982 * offset + 5 (32 bit): data register
983 * offset + 9 (32 bit): mask
984 * offset + 13 (32 bit): data
985 * offset + 17 (8 bit): count
986 * offset + 18 (8 bit): address 1
987 * offset + 19 (8 bit): data 1
988 * ...
989 *
990 * For each of "count" address and data pairs, write "data n" to "data register",
991 * read the current value of "control register", and write it back once ANDed
992 * with "mask", ORed with "data", and ORed with "address n"
993 */
994
995 uint32_t controlreg = ROM32(bios->data[offset + 1]);
996 uint32_t datareg = ROM32(bios->data[offset + 5]);
997 uint32_t mask = ROM32(bios->data[offset + 9]);
998 uint32_t data = ROM32(bios->data[offset + 13]);
999 uint8_t count = bios->data[offset + 17];
1000 uint32_t value;
1001 int i;
1002
1003 if (!iexec->execute)
1004 return true;
1005
1006 BIOSLOG(pScrn, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n",
1007 offset, controlreg, datareg, mask, data, count);
1008
1009 for (i = 0; i < count; i++) {
1010 uint8_t instaddress = bios->data[offset + 18 + i * 2];
1011 uint8_t instdata = bios->data[offset + 19 + i * 2];
1012
1013 BIOSLOG(pScrn, "0x%04X: Address: 0x%02X, Data: 0x%02X\n", offset, instaddress, instdata);
1014
1015 bios_wr32(pScrn, datareg, instdata);
1016 value = (bios_rd32(pScrn, controlreg) & mask) | data | instaddress;
1017 bios_wr32(pScrn, controlreg, value);
1018 }
1019
1020 return true;
1021}
1022
1023static bool init_io_restrict_pll2(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1024{
1025 /* INIT_IO_RESTRICT_PLL2 opcode: 0x4A ('J')
1026 *
1027 * offset (8 bit): opcode
1028 * offset + 1 (16 bit): CRTC port
1029 * offset + 3 (8 bit): CRTC index
1030 * offset + 4 (8 bit): mask
1031 * offset + 5 (8 bit): shift
1032 * offset + 6 (8 bit): count
1033 * offset + 7 (32 bit): register
1034 * offset + 11 (32 bit): frequency 1
1035 * ...
1036 *
1037 * Starting at offset + 11 there are "count" 32 bit frequencies (kHz).
1038 * Set PLL register "register" to coefficients for frequency n,
1039 * selected by reading index "CRTC index" of "CRTC port" ANDed with
1040 * "mask" and shifted right by "shift".
1041 */
1042
1043 uint16_t crtcport = ROM16(bios->data[offset + 1]);
1044 uint8_t crtcindex = bios->data[offset + 3];
1045 uint8_t mask = bios->data[offset + 4];
1046 uint8_t shift = bios->data[offset + 5];
1047 uint8_t count = bios->data[offset + 6];
1048 uint32_t reg = ROM32(bios->data[offset + 7]);
1049 uint8_t config;
1050 uint32_t freq;
1051
1052 if (!iexec->execute)
1053 return true;
1054
1055 BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n",
1056 offset, crtcport, crtcindex, mask, shift, count, reg);
1057
1058 if (!reg)
1059 return true;
1060
1061 config = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) >> shift;
1062 if (config > count) {
1063 NV_ERROR(pScrn,
1064 "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n",
1065 offset, config, count);
1066 return false;
1067 }
1068
1069 freq = ROM32(bios->data[offset + 11 + config * 4]);
1070
1071 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Config: 0x%02X, Freq: %dkHz\n",
1072 offset, reg, config, freq);
1073
1074 setPLL(pScrn, bios, reg, freq);
1075
1076 return true;
1077}
1078
1079static bool init_pll2(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1080{
1081 /* INIT_PLL2 opcode: 0x4B ('K')
1082 *
1083 * offset (8 bit): opcode
1084 * offset + 1 (32 bit): register
1085 * offset + 5 (32 bit): freq
1086 *
1087 * Set PLL register "register" to coefficients for frequency "freq"
1088 */
1089
1090 uint32_t reg = ROM32(bios->data[offset + 1]);
1091 uint32_t freq = ROM32(bios->data[offset + 5]);
1092
1093 if (!iexec->execute)
1094 return true;
1095
1096 BIOSLOG(pScrn, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n",
1097 offset, reg, freq);
1098
1099 setPLL(pScrn, bios, reg, freq);
1100
1101 return true;
1102}
1103
1104static bool init_i2c_byte(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1105{
1106 /* INIT_I2C_BYTE opcode: 0x4C ('L')
1107 *
1108 * offset (8 bit): opcode
1109 * offset + 1 (8 bit): DCB I2C table entry index
1110 * offset + 2 (8 bit): I2C slave address
1111 * offset + 3 (8 bit): count
1112 * offset + 4 (8 bit): I2C register 1
1113 * offset + 5 (8 bit): mask 1
1114 * offset + 6 (8 bit): data 1
1115 * ...
1116 *
1117 * For each of "count" registers given by "I2C register n" on the device
1118 * addressed by "I2C slave address" on the I2C bus given by
1119 * "DCB I2C table entry index", read the register, AND the result with
1120 * "mask n" and OR it with "data n" before writing it back to the device
1121 */
1122
1123 uint8_t i2c_index = bios->data[offset + 1];
1124 uint8_t i2c_address = bios->data[offset + 2];
1125 uint8_t count = bios->data[offset + 3];
1126 I2CDevRec i2cdev;
1127 int i;
1128
1129 if (!iexec->execute)
1130 return true;
1131
1132 BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n",
1133 offset, i2c_index, i2c_address, count);
1134
1135 if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev))
1136 return false;
1137
1138 for (i = 0; i < count; i++) {
1139 uint8_t i2c_reg = bios->data[offset + 4 + i * 3];
1140 uint8_t mask = bios->data[offset + 5 + i * 3];
1141 uint8_t data = bios->data[offset + 6 + i * 3];
1142 uint8_t value;
1143
1144 xf86I2CReadByte(&i2cdev, i2c_reg, &value);
1145
1146 BIOSLOG(pScrn, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1147 offset, i2c_reg, value, mask, data);
1148
1149 value = (value & mask) | data;
1150
1151 if (bios->execute)
1152 xf86I2CWriteByte(&i2cdev, i2c_reg, value);
1153 }
1154
1155 xf86DestroyI2CDevRec(&i2cdev, FALSE);
1156
1157 return true;
1158}
1159
1160static bool init_zm_i2c_byte(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1161{
1162 /* INIT_ZM_I2C_BYTE opcode: 0x4D ('M')
1163 *
1164 * offset (8 bit): opcode
1165 * offset + 1 (8 bit): DCB I2C table entry index
1166 * offset + 2 (8 bit): I2C slave address
1167 * offset + 3 (8 bit): count
1168 * offset + 4 (8 bit): I2C register 1
1169 * offset + 5 (8 bit): data 1
1170 * ...
1171 *
1172 * For each of "count" registers given by "I2C register n" on the device
1173 * addressed by "I2C slave address" on the I2C bus given by
1174 * "DCB I2C table entry index", set the register to "data n"
1175 */
1176
1177 uint8_t i2c_index = bios->data[offset + 1];
1178 uint8_t i2c_address = bios->data[offset + 2];
1179 uint8_t count = bios->data[offset + 3];
1180 I2CDevRec i2cdev;
1181 int i;
1182
1183 if (!iexec->execute)
1184 return true;
1185
1186 BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n",
1187 offset, i2c_index, i2c_address, count);
1188
1189 if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev))
1190 return false;
1191
1192 for (i = 0; i < count; i++) {
1193 uint8_t i2c_reg = bios->data[offset + 4 + i * 2];
1194 uint8_t data = bios->data[offset + 5 + i * 2];
1195
1196 BIOSLOG(pScrn, "0x%04X: I2CReg: 0x%02X, Data: 0x%02X\n",
1197 offset, i2c_reg, data);
1198
1199 if (bios->execute)
1200 if (!xf86I2CWriteByte(&i2cdev, i2c_reg, data))
1201 break;
1202 }
1203
1204 xf86DestroyI2CDevRec(&i2cdev, FALSE);
1205
1206 return true;
1207}
1208
1209static bool init_zm_i2c(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1210{
1211 /* INIT_ZM_I2C opcode: 0x4E ('N')
1212 *
1213 * offset (8 bit): opcode
1214 * offset + 1 (8 bit): DCB I2C table entry index
1215 * offset + 2 (8 bit): I2C slave address
1216 * offset + 3 (8 bit): count
1217 * offset + 4 (8 bit): data 1
1218 * ...
1219 *
1220 * Send "count" bytes ("data n") to the device addressed by "I2C slave
1221 * address" on the I2C bus given by "DCB I2C table entry index"
1222 */
1223
1224 uint8_t i2c_index = bios->data[offset + 1];
1225 uint8_t i2c_address = bios->data[offset + 2];
1226 uint8_t count = bios->data[offset + 3];
1227 I2CDevRec i2cdev;
1228 uint8_t data[256]; /* 256 is max "count" could specify */
1229 int i;
1230
1231 if (!iexec->execute)
1232 return true;
1233
1234 BIOSLOG(pScrn, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, Count: 0x%02X\n",
1235 offset, i2c_index, i2c_address, count);
1236
1237 if (create_i2c_device(pScrn, bios, i2c_index, i2c_address, &i2cdev))
1238 return false;
1239
1240 for (i = 0; i < count; i++) {
1241 data[i] = bios->data[offset + 4 + i];
1242
1243 BIOSLOG(pScrn, "0x%04X: Data: 0x%02X\n", offset, data[i]);
1244 }
1245
1246 if (bios->execute)
1247 xf86I2CWrite(&i2cdev, data, count);
1248
1249 xf86DestroyI2CDevRec(&i2cdev, FALSE);
1250
1251 return true;
1252}
1253
1254static bool init_tmds(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1255{
1256 /* INIT_TMDS opcode: 0x4F ('O') (non-canon name)
1257 *
1258 * offset (8 bit): opcode
1259 * offset + 1 (8 bit): magic lookup value
1260 * offset + 2 (8 bit): TMDS address
1261 * offset + 3 (8 bit): mask
1262 * offset + 4 (8 bit): data
1263 *
1264 * Read the data reg for TMDS address "TMDS address", AND it with mask
1265 * and OR it with data, then write it back
1266 * "magic lookup value" determines which TMDS base address register is used --
1267 * see get_tmds_index_reg()
1268 */
1269
1270 uint8_t mlv = bios->data[offset + 1];
1271 uint32_t tmdsaddr = bios->data[offset + 2];
1272 uint8_t mask = bios->data[offset + 3];
1273 uint8_t data = bios->data[offset + 4];
1274 uint32_t reg, value;
1275
1276 if (!iexec->execute)
1277 return true;
1278
1279 BIOSLOG(pScrn, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1280 offset, mlv, tmdsaddr, mask, data);
1281
1282 if (!(reg = get_tmds_index_reg(pScrn, mlv)))
1283 return false;
1284
1285 bios_wr32(pScrn, reg, tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE);
1286 value = (bios_rd32(pScrn, reg + 4) & mask) | data;
1287 bios_wr32(pScrn, reg + 4, value);
1288 bios_wr32(pScrn, reg, tmdsaddr);
1289
1290 return true;
1291}
1292
1293static bool init_zm_tmds_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1294{
1295 /* INIT_ZM_TMDS_GROUP opcode: 0x50 ('P') (non-canon name)
1296 *
1297 * offset (8 bit): opcode
1298 * offset + 1 (8 bit): magic lookup value
1299 * offset + 2 (8 bit): count
1300 * offset + 3 (8 bit): addr 1
1301 * offset + 4 (8 bit): data 1
1302 * ...
1303 *
1304 * For each of "count" TMDS address and data pairs write "data n" to "addr n"
1305 * "magic lookup value" determines which TMDS base address register is used --
1306 * see get_tmds_index_reg()
1307 */
1308
1309 uint8_t mlv = bios->data[offset + 1];
1310 uint8_t count = bios->data[offset + 2];
1311 uint32_t reg;
1312 int i;
1313
1314 if (!iexec->execute)
1315 return true;
1316
1317 BIOSLOG(pScrn, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n",
1318 offset, mlv, count);
1319
1320 if (!(reg = get_tmds_index_reg(pScrn, mlv)))
1321 return false;
1322
1323 for (i = 0; i < count; i++) {
1324 uint8_t tmdsaddr = bios->data[offset + 3 + i * 2];
1325 uint8_t tmdsdata = bios->data[offset + 4 + i * 2];
1326
1327 bios_wr32(pScrn, reg + 4, tmdsdata);
1328 bios_wr32(pScrn, reg, tmdsaddr);
1329 }
1330
1331 return true;
1332}
1333
1334static bool init_cr_idx_adr_latch(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1335{
1336 /* INIT_CR_INDEX_ADDRESS_LATCHED opcode: 0x51 ('Q')
1337 *
1338 * offset (8 bit): opcode
1339 * offset + 1 (8 bit): CRTC index1
1340 * offset + 2 (8 bit): CRTC index2
1341 * offset + 3 (8 bit): baseaddr
1342 * offset + 4 (8 bit): count
1343 * offset + 5 (8 bit): data 1
1344 * ...
1345 *
1346 * For each of "count" address and data pairs, write "baseaddr + n" to
1347 * "CRTC index1" and "data n" to "CRTC index2"
1348 * Once complete, restore initial value read from "CRTC index1"
1349 */
1350 uint8_t crtcindex1 = bios->data[offset + 1];
1351 uint8_t crtcindex2 = bios->data[offset + 2];
1352 uint8_t baseaddr = bios->data[offset + 3];
1353 uint8_t count = bios->data[offset + 4];
1354 uint8_t oldaddr, data;
1355 int i;
1356
1357 if (!iexec->execute)
1358 return true;
1359
1360 BIOSLOG(pScrn, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, BaseAddr: 0x%02X, Count: 0x%02X\n",
1361 offset, crtcindex1, crtcindex2, baseaddr, count);
1362
1363 oldaddr = bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, crtcindex1);
1364
1365 for (i = 0; i < count; i++) {
1366 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex1, baseaddr + i);
1367
1368 data = bios->data[offset + 5 + i];
1369 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex2, data);
1370 }
1371
1372 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex1, oldaddr);
1373
1374 return true;
1375}
1376
1377static bool init_cr(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1378{
1379 /* INIT_CR opcode: 0x52 ('R')
1380 *
1381 * offset (8 bit): opcode
1382 * offset + 1 (8 bit): CRTC index
1383 * offset + 2 (8 bit): mask
1384 * offset + 3 (8 bit): data
1385 *
1386 * Assign the value of at "CRTC index" ANDed with mask and ORed with data
1387 * back to "CRTC index"
1388 */
1389
1390 uint8_t crtcindex = bios->data[offset + 1];
1391 uint8_t mask = bios->data[offset + 2];
1392 uint8_t data = bios->data[offset + 3];
1393 uint8_t value;
1394
1395 if (!iexec->execute)
1396 return true;
1397
1398 BIOSLOG(pScrn, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
1399 offset, crtcindex, mask, data);
1400
1401 value = (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, crtcindex) & mask) | data;
1402 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex, value);
1403
1404 return true;
1405}
1406
1407static bool init_zm_cr(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1408{
1409 /* INIT_ZM_CR opcode: 0x53 ('S')
1410 *
1411 * offset (8 bit): opcode
1412 * offset + 1 (8 bit): CRTC index
1413 * offset + 2 (8 bit): value
1414 *
1415 * Assign "value" to CRTC register with index "CRTC index".
1416 */
1417
1418 uint8_t crtcindex = ROM32(bios->data[offset + 1]);
1419 uint8_t data = bios->data[offset + 2];
1420
1421 if (!iexec->execute)
1422 return true;
1423
1424 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, crtcindex, data);
1425
1426 return true;
1427}
1428
1429static bool init_zm_cr_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1430{
1431 /* INIT_ZM_CR_GROUP opcode: 0x54 ('T')
1432 *
1433 * offset (8 bit): opcode
1434 * offset + 1 (8 bit): count
1435 * offset + 2 (8 bit): CRTC index 1
1436 * offset + 3 (8 bit): value 1
1437 * ...
1438 *
1439 * For "count", assign "value n" to CRTC register with index "CRTC index n".
1440 */
1441
1442 uint8_t count = bios->data[offset + 1];
1443 int i;
1444
1445 if (!iexec->execute)
1446 return true;
1447
1448 for (i = 0; i < count; i++)
1449 init_zm_cr(pScrn, bios, offset + 2 + 2 * i - 1, iexec);
1450
1451 return true;
1452}
1453
1454static bool init_condition_time(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1455{
1456 /* INIT_CONDITION_TIME opcode: 0x56 ('V')
1457 *
1458 * offset (8 bit): opcode
1459 * offset + 1 (8 bit): condition number
1460 * offset + 2 (8 bit): retries / 50
1461 *
1462 * Check condition "condition number" in the condition table.
1463 * Bios code then sleeps for 2ms if the condition is not met, and
1464 * repeats up to "retries" times, but on one C51 this has proved
1465 * insufficient. In mmiotraces the driver sleeps for 20ms, so we do
1466 * this, and bail after "retries" times, or 2s, whichever is less.
1467 * If still not met after retries, clear execution flag for this table.
1468 */
1469
1470 uint8_t cond = bios->data[offset + 1];
1471 uint16_t retries = bios->data[offset + 2] * 50;
1472
1473 if (!iexec->execute)
1474 return true;
1475
1476 if (retries > 100)
1477 retries = 100;
1478
1479 BIOSLOG(pScrn, "0x%04X: Condition: 0x%02X, Retries: 0x%02X\n", offset, cond, retries);
1480
1481 for (; retries > 0; retries--)
1482 if (bios_condition_met(pScrn, bios, offset, cond)) {
1483 BIOSLOG(pScrn, "0x%04X: Condition met, continuing\n", offset);
1484 break;
1485 } else {
1486 BIOSLOG(pScrn, "0x%04X: Condition not met, sleeping for 20ms\n", offset);
1487 BIOS_USLEEP(20000);
1488 }
1489
1490 if (!bios_condition_met(pScrn, bios, offset, cond)) {
1491 NV_WARN(pScrn, "0x%04X: Condition still not met after %dms, "
1492 "skiping following opcodes\n", offset, 20 * retries);
1493 iexec->execute = false;
1494 }
1495
1496 return true;
1497}
1498
1499static bool init_zm_reg_sequence(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1500{
1501 /* INIT_ZM_REG_SEQUENCE opcode: 0x58 ('X')
1502 *
1503 * offset (8 bit): opcode
1504 * offset + 1 (32 bit): base register
1505 * offset + 5 (8 bit): count
1506 * offset + 6 (32 bit): value 1
1507 * ...
1508 *
1509 * Starting at offset + 6 there are "count" 32 bit values.
1510 * For "count" iterations set "base register" + 4 * current_iteration
1511 * to "value current_iteration"
1512 */
1513
1514 uint32_t basereg = ROM32(bios->data[offset + 1]);
1515 uint32_t count = bios->data[offset + 5];
1516 int i;
1517
1518 if (!iexec->execute)
1519 return true;
1520
1521 BIOSLOG(pScrn, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n", offset, basereg, count);
1522
1523 for (i = 0; i < count; i++) {
1524 uint32_t reg = basereg + i * 4;
1525 uint32_t data = ROM32(bios->data[offset + 6 + i * 4]);
1526
1527 bios_wr32(pScrn, reg, data);
1528 }
1529
1530 return true;
1531}
1532
1533static bool init_sub_direct(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1534{
1535 /* INIT_SUB_DIRECT opcode: 0x5B ('[')
1536 *
1537 * offset (8 bit): opcode
1538 * offset + 1 (16 bit): subroutine offset (in bios)
1539 *
1540 * Calls a subroutine that will execute commands until INIT_DONE
1541 * is found.
1542 */
1543
1544 uint16_t sub_offset = ROM16(bios->data[offset + 1]);
1545
1546 if (!iexec->execute)
1547 return true;
1548
1549 BIOSLOG(pScrn, "0x%04X: Executing subroutine at 0x%04X\n", offset, sub_offset);
1550
1551 parse_init_table(pScrn, bios, sub_offset, iexec);
1552
1553 BIOSLOG(pScrn, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset);
1554
1555 return true;
1556}
1557
1558static bool init_copy_nv_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1559{
1560 /* INIT_COPY_NV_REG opcode: 0x5F ('_')
1561 *
1562 * offset (8 bit): opcode
1563 * offset + 1 (32 bit): src reg
1564 * offset + 5 (8 bit): shift
1565 * offset + 6 (32 bit): src mask
1566 * offset + 10 (32 bit): xor
1567 * offset + 14 (32 bit): dst reg
1568 * offset + 18 (32 bit): dst mask
1569 *
1570 * Shift REGVAL("src reg") right by (signed) "shift", AND result with
1571 * "src mask", then XOR with "xor". Write this OR'd with
1572 * (REGVAL("dst reg") AND'd with "dst mask") to "dst reg"
1573 */
1574
1575 uint32_t srcreg = *((uint32_t *)(&bios->data[offset + 1]));
1576 uint8_t shift = bios->data[offset + 5];
1577 uint32_t srcmask = *((uint32_t *)(&bios->data[offset + 6]));
1578 uint32_t xor = *((uint32_t *)(&bios->data[offset + 10]));
1579 uint32_t dstreg = *((uint32_t *)(&bios->data[offset + 14]));
1580 uint32_t dstmask = *((uint32_t *)(&bios->data[offset + 18]));
1581 uint32_t srcvalue, dstvalue;
1582
1583 if (!iexec->execute)
1584 return true;
1585
1586 BIOSLOG(pScrn, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n",
1587 offset, srcreg, shift, srcmask, xor, dstreg, dstmask);
1588
1589 srcvalue = bios_rd32(pScrn, srcreg);
1590
1591 if (shift < 0x80)
1592 srcvalue >>= shift;
1593 else
1594 srcvalue <<= (0x100 - shift);
1595
1596 srcvalue = (srcvalue & srcmask) ^ xor;
1597
1598 dstvalue = bios_rd32(pScrn, dstreg) & dstmask;
1599
1600 bios_wr32(pScrn, dstreg, dstvalue | srcvalue);
1601
1602 return true;
1603}
1604
1605static bool init_zm_index_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1606{
1607 /* INIT_ZM_INDEX_IO opcode: 0x62 ('b')
1608 *
1609 * offset (8 bit): opcode
1610 * offset + 1 (16 bit): CRTC port
1611 * offset + 3 (8 bit): CRTC index
1612 * offset + 4 (8 bit): data
1613 *
1614 * Write "data" to index "CRTC index" of "CRTC port"
1615 */
1616 uint16_t crtcport = ROM16(bios->data[offset + 1]);
1617 uint8_t crtcindex = bios->data[offset + 3];
1618 uint8_t data = bios->data[offset + 4];
1619
1620 if (!iexec->execute)
1621 return true;
1622
1623 bios_idxprt_wr(pScrn, crtcport, crtcindex, data);
1624
1625 return true;
1626}
1627
1628static bool init_compute_mem(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1629{
1630 /* INIT_COMPUTE_MEM opcode: 0x63 ('c')
1631 *
1632 * offset (8 bit): opcode
1633 *
1634 * This opcode is meant to set NV_PFB_CFG0 (0x100200) appropriately so
1635 * that the hardware can correctly calculate how much VRAM it has
1636 * (and subsequently report that value in NV_PFB_CSTATUS (0x10020C))
1637 *
1638 * The implementation of this opcode in general consists of two parts:
1639 * 1) determination of the memory bus width
1640 * 2) determination of how many of the card's RAM pads have ICs attached
1641 *
1642 * 1) is done by a cunning combination of writes to offsets 0x1c and
1643 * 0x3c in the framebuffer, and seeing whether the written values are
1644 * read back correctly. This then affects bits 4-7 of NV_PFB_CFG0
1645 *
1646 * 2) is done by a cunning combination of writes to an offset slightly
1647 * less than the maximum memory reported by NV_PFB_CSTATUS, then seeing
1648 * if the test pattern can be read back. This then affects bits 12-15 of
1649 * NV_PFB_CFG0
1650 *
1651 * In this context a "cunning combination" may include multiple reads
1652 * and writes to varying locations, often alternating the test pattern
1653 * and 0, doubtless to make sure buffers are filled, residual charges
1654 * on tracks are removed etc.
1655 *
1656 * Unfortunately, the "cunning combination"s mentioned above, and the
1657 * changes to the bits in NV_PFB_CFG0 differ with nearly every bios
1658 * trace I have.
1659 *
1660 * Therefore, we cheat and assume the value of NV_PFB_CFG0 with which
1661 * we started was correct, and use that instead
1662 */
1663
1664 /* no iexec->execute check by design */
1665
1666 /* on every card I've seen, this step gets done for us earlier in the init scripts
1667 uint8_t crdata = bios_idxprt_rd(pScrn, NV_VIO_SRX, 0x01);
1668 bios_idxprt_wr(pScrn, NV_VIO_SRX, 0x01, crdata | 0x20);
1669 */
1670
1671 /* this also has probably been done in the scripts, but an mmio trace of
1672 * s3 resume shows nvidia doing it anyway (unlike the NV_VIO_SRX write)
1673 */
1674 bios_wr32(pScrn, NV_PFB_REFCTRL, NV_PFB_REFCTRL_VALID_1);
1675
1676 /* write back the saved configuration value */
1677 bios_wr32(pScrn, NV_PFB_CFG0, saved_nv_pfb_cfg0);
1678
1679 return true;
1680}
1681
1682static bool init_reset(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1683{
1684 /* INIT_RESET opcode: 0x65 ('e')
1685 *
1686 * offset (8 bit): opcode
1687 * offset + 1 (32 bit): register
1688 * offset + 5 (32 bit): value1
1689 * offset + 9 (32 bit): value2
1690 *
1691 * Assign "value1" to "register", then assign "value2" to "register"
1692 */
1693
1694 uint32_t reg = ROM32(bios->data[offset + 1]);
1695 uint32_t value1 = ROM32(bios->data[offset + 5]);
1696 uint32_t value2 = ROM32(bios->data[offset + 9]);
1697 uint32_t pci_nv_19, pci_nv_20;
1698
1699 /* no iexec->execute check by design */
1700
1701 pci_nv_19 = bios_rd32(pScrn, NV_PBUS_PCI_NV_19);
1702 bios_wr32(pScrn, NV_PBUS_PCI_NV_19, 0);
1703 bios_wr32(pScrn, reg, value1);
1704
1705 BIOS_USLEEP(10);
1706
1707 bios_wr32(pScrn, reg, value2);
1708 bios_wr32(pScrn, NV_PBUS_PCI_NV_19, pci_nv_19);
1709
1710 pci_nv_20 = bios_rd32(pScrn, NV_PBUS_PCI_NV_20);
1711 pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; /* 0xfffffffe */
1712 bios_wr32(pScrn, NV_PBUS_PCI_NV_20, pci_nv_20);
1713
1714 return true;
1715}
1716
1717static bool init_configure_mem(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1718{
1719 /* INIT_CONFIGURE_MEM opcode: 0x66 ('f')
1720 *
1721 * offset (8 bit): opcode
1722 *
1723 * Equivalent to INIT_DONE on bios version 3 or greater.
1724 * For early bios versions, sets up the memory registers, using values
1725 * taken from the memory init table
1726 */
1727
1728 /* no iexec->execute check by design */
1729
1730 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);
1731 uint16_t seqtbloffs = bios->legacy.sdr_seq_tbl_ptr, meminitdata = meminitoffs + 6;
1732 uint32_t reg, data;
1733
1734 if (bios->major_version > 2)
1735 return false;
1736
1737 bios_idxprt_wr(pScrn, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX,
1738 bios_idxprt_rd(pScrn, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20);
1739
1740 if (bios->data[meminitoffs] & 1)
1741 seqtbloffs = bios->legacy.ddr_seq_tbl_ptr;
1742
1743 for (reg = ROM32(bios->data[seqtbloffs]);
1744 reg != 0xffffffff;
1745 reg = ROM32(bios->data[seqtbloffs += 4])) {
1746
1747 switch (reg) {
1748 case NV_PFB_PRE:
1749 data = NV_PFB_PRE_CMD_PRECHARGE;
1750 break;
1751 case NV_PFB_PAD:
1752 data = NV_PFB_PAD_CKE_NORMAL;
1753 break;
1754 case NV_PFB_REF:
1755 data = NV_PFB_REF_CMD_REFRESH;
1756 break;
1757 default:
1758 data = ROM32(bios->data[meminitdata]);
1759 meminitdata += 4;
1760 if (data == 0xffffffff)
1761 continue;
1762 }
1763
1764 bios_wr32(pScrn, reg, data);
1765 }
1766
1767 return true;
1768}
1769
1770static bool init_configure_clk(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1771{
1772 /* INIT_CONFIGURE_CLK opcode: 0x67 ('g')
1773 *
1774 * offset (8 bit): opcode
1775 *
1776 * Equivalent to INIT_DONE on bios version 3 or greater.
1777 * For early bios versions, sets up the NVClk and MClk PLLs, using
1778 * values taken from the memory init table
1779 */
1780
1781 /* no iexec->execute check by design */
1782
1783 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);
1784 int clock;
1785
1786 if (bios->major_version > 2)
1787 return false;
1788
1789 clock = ROM16(bios->data[meminitoffs + 4]) * 10;
1790 setPLL(pScrn, bios, NV_PRAMDAC_NVPLL_COEFF, clock);
1791
1792 clock = ROM16(bios->data[meminitoffs + 2]) * 10;
1793 if (bios->data[meminitoffs] & 1) /* DDR */
1794 clock *= 2;
1795 setPLL(pScrn, bios, NV_PRAMDAC_MPLL_COEFF, clock);
1796
1797 return true;
1798}
1799
1800static bool init_configure_preinit(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1801{
1802 /* INIT_CONFIGURE_PREINIT opcode: 0x68 ('h')
1803 *
1804 * offset (8 bit): opcode
1805 *
1806 * Equivalent to INIT_DONE on bios version 3 or greater.
1807 * For early bios versions, does early init, loading ram and crystal
1808 * configuration from straps into CR3C
1809 */
1810
1811 /* no iexec->execute check by design */
1812
1813 uint32_t straps = bios_rd32(pScrn, NV_PEXTDEV_BOOT_0);
1814 uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6));
1815
1816 if (bios->major_version > 2)
1817 return false;
1818
1819 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX, cr3c);
1820
1821 return true;
1822}
1823
1824static bool init_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1825{
1826 /* INIT_IO opcode: 0x69 ('i')
1827 *
1828 * offset (8 bit): opcode
1829 * offset + 1 (16 bit): CRTC port
1830 * offset + 3 (8 bit): mask
1831 * offset + 4 (8 bit): data
1832 *
1833 * Assign ((IOVAL("crtc port") & "mask") | "data") to "crtc port"
1834 */
1835
1836 uint16_t crtcport = ROM16(bios->data[offset + 1]);
1837 uint8_t mask = bios->data[offset + 3];
1838 uint8_t data = bios->data[offset + 4];
1839
1840 if (!iexec->execute)
1841 return true;
1842
1843 BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n",
1844 offset, crtcport, mask, data);
1845
1846 bios_port_wr(pScrn, crtcport, (bios_port_rd(pScrn, crtcport) & mask) | data);
1847
1848 return true;
1849}
1850
1851static bool init_sub(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1852{
1853 /* INIT_SUB opcode: 0x6B ('k')
1854 *
1855 * offset (8 bit): opcode
1856 * offset + 1 (8 bit): script number
1857 *
1858 * Execute script number "script number", as a subroutine
1859 */
1860
1861 uint8_t sub = bios->data[offset + 1];
1862
1863 if (!iexec->execute)
1864 return true;
1865
1866 BIOSLOG(pScrn, "0x%04X: Calling script %d\n", offset, sub);
1867
1868 parse_init_table(pScrn, bios,
1869 ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]),
1870 iexec);
1871
1872 BIOSLOG(pScrn, "0x%04X: End of script %d\n", offset, sub);
1873
1874 return true;
1875}
1876
1877static bool init_ram_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1878{
1879 /* INIT_RAM_CONDITION opcode: 0x6D ('m')
1880 *
1881 * offset (8 bit): opcode
1882 * offset + 1 (8 bit): mask
1883 * offset + 2 (8 bit): cmpval
1884 *
1885 * Test if (NV_PFB_BOOT_0 & "mask") equals "cmpval".
1886 * If condition not met skip subsequent opcodes until condition is
1887 * inverted (INIT_NOT), or we hit INIT_RESUME
1888 */
1889
1890 uint8_t mask = bios->data[offset + 1];
1891 uint8_t cmpval = bios->data[offset + 2];
1892 uint8_t data;
1893
1894 if (!iexec->execute)
1895 return true;
1896
1897 data = bios_rd32(pScrn, NV_PFB_BOOT_0) & mask;
1898
1899 BIOSLOG(pScrn, "0x%04X: Checking if 0x%08X equals 0x%08X\n", offset, data, cmpval);
1900
1901 if (data == cmpval)
1902 BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
1903 else {
1904 BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
1905 iexec->execute = false;
1906 }
1907
1908 return true;
1909}
1910
1911static bool init_nv_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1912{
1913 /* INIT_NV_REG opcode: 0x6E ('n')
1914 *
1915 * offset (8 bit): opcode
1916 * offset + 1 (32 bit): register
1917 * offset + 5 (32 bit): mask
1918 * offset + 9 (32 bit): data
1919 *
1920 * Assign ((REGVAL("register") & "mask") | "data") to "register"
1921 */
1922
1923 uint32_t reg = ROM32(bios->data[offset + 1]);
1924 uint32_t mask = ROM32(bios->data[offset + 5]);
1925 uint32_t data = ROM32(bios->data[offset + 9]);
1926
1927 if (!iexec->execute)
1928 return true;
1929
1930 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n", offset, reg, mask, data);
1931
1932 bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data);
1933
1934 return true;
1935}
1936
1937static bool init_macro(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1938{
1939 /* INIT_MACRO opcode: 0x6F ('o')
1940 *
1941 * offset (8 bit): opcode
1942 * offset + 1 (8 bit): macro number
1943 *
1944 * Look up macro index "macro number" in the macro index table.
1945 * The macro index table entry has 1 byte for the index in the macro table,
1946 * and 1 byte for the number of times to repeat the macro.
1947 * The macro table entry has 4 bytes for the register address and
1948 * 4 bytes for the value to write to that register
1949 */
1950
1951 uint8_t macro_index_tbl_idx = bios->data[offset + 1];
1952 uint16_t tmp = bios->macro_index_tbl_ptr + (macro_index_tbl_idx * MACRO_INDEX_SIZE);
1953 uint8_t macro_tbl_idx = bios->data[tmp];
1954 uint8_t count = bios->data[tmp + 1];
1955 uint32_t reg, data;
1956 int i;
1957
1958 if (!iexec->execute)
1959 return true;
1960
1961 BIOSLOG(pScrn, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, Count: 0x%02X\n",
1962 offset, macro_index_tbl_idx, macro_tbl_idx, count);
1963
1964 for (i = 0; i < count; i++) {
1965 uint16_t macroentryptr = bios->macro_tbl_ptr + (macro_tbl_idx + i) * MACRO_SIZE;
1966
1967 reg = ROM32(bios->data[macroentryptr]);
1968 data = ROM32(bios->data[macroentryptr + 4]);
1969
1970 bios_wr32(pScrn, reg, data);
1971 }
1972
1973 return true;
1974}
1975
1976static bool init_done(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1977{
1978 /* INIT_DONE opcode: 0x71 ('q')
1979 *
1980 * offset (8 bit): opcode
1981 *
1982 * End the current script
1983 */
1984
1985 /* mild retval abuse to stop parsing this table */
1986 return false;
1987}
1988
1989static bool init_resume(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
1990{
1991 /* INIT_RESUME opcode: 0x72 ('r')
1992 *
1993 * offset (8 bit): opcode
1994 *
1995 * End the current execute / no-execute condition
1996 */
1997
1998 if (iexec->execute)
1999 return true;
2000
2001 iexec->execute = true;
2002 BIOSLOG(pScrn, "0x%04X: ---- Executing following commands ----\n", offset);
2003
2004 return true;
2005}
2006
2007static bool init_time(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2008{
2009 /* INIT_TIME opcode: 0x74 ('t')
2010 *
2011 * offset (8 bit): opcode
2012 * offset + 1 (16 bit): time
2013 *
2014 * Sleep for "time" microseconds.
2015 */
2016
2017 uint16_t time = ROM16(bios->data[offset + 1]);
2018
2019 if (!iexec->execute)
2020 return true;
2021
2022 BIOSLOG(pScrn, "0x%04X: Sleeping for 0x%04X microseconds\n", offset, time);
2023
2024 BIOS_USLEEP(time);
2025
2026 return true;
2027}
2028
2029static bool init_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2030{
2031 /* INIT_CONDITION opcode: 0x75 ('u')
2032 *
2033 * offset (8 bit): opcode
2034 * offset + 1 (8 bit): condition number
2035 *
2036 * Check condition "condition number" in the condition table.
2037 * If condition not met skip subsequent opcodes until condition is
2038 * inverted (INIT_NOT), or we hit INIT_RESUME
2039 */
2040
2041 uint8_t cond = bios->data[offset + 1];
2042
2043 if (!iexec->execute)
2044 return true;
2045
2046 BIOSLOG(pScrn, "0x%04X: Condition: 0x%02X\n", offset, cond);
2047
2048 if (bios_condition_met(pScrn, bios, offset, cond))
2049 BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
2050 else {
2051 BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
2052 iexec->execute = false;
2053 }
2054
2055 return true;
2056}
2057
2058static bool init_io_condition(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2059{
2060 /* INIT_IO_CONDITION opcode: 0x76
2061 *
2062 * offset (8 bit): opcode
2063 * offset + 1 (8 bit): condition number
2064 *
2065 * Check condition "condition number" in the io condition table.
2066 * If condition not met skip subsequent opcodes until condition is
2067 * inverted (INIT_NOT), or we hit INIT_RESUME
2068 */
2069
2070 uint8_t cond = bios->data[offset + 1];
2071
2072 if (!iexec->execute)
2073 return true;
2074
2075 BIOSLOG(pScrn, "0x%04X: IO condition: 0x%02X\n", offset, cond);
2076
2077 if (io_condition_met(pScrn, bios, offset, cond))
2078 BIOSLOG(pScrn, "0x%04X: Condition fulfilled -- continuing to execute\n", offset);
2079 else {
2080 BIOSLOG(pScrn, "0x%04X: Condition not fulfilled -- skipping following commands\n", offset);
2081 iexec->execute = false;
2082 }
2083
2084 return true;
2085}
2086
2087static bool init_index_io(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2088{
2089 /* INIT_INDEX_IO opcode: 0x78 ('x')
2090 *
2091 * offset (8 bit): opcode
2092 * offset + 1 (16 bit): CRTC port
2093 * offset + 3 (8 bit): CRTC index
2094 * offset + 4 (8 bit): mask
2095 * offset + 5 (8 bit): data
2096 *
2097 * Read value at index "CRTC index" on "CRTC port", AND with "mask", OR with "data", write-back
2098 */
2099
2100 uint16_t crtcport = ROM16(bios->data[offset + 1]);
2101 uint8_t crtcindex = bios->data[offset + 3];
2102 uint8_t mask = bios->data[offset + 4];
2103 uint8_t data = bios->data[offset + 5];
2104 uint8_t value;
2105
2106 if (!iexec->execute)
2107 return true;
2108
2109 BIOSLOG(pScrn, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n",
2110 offset, crtcport, crtcindex, mask, data);
2111
2112 value = (bios_idxprt_rd(pScrn, crtcport, crtcindex) & mask) | data;
2113 bios_idxprt_wr(pScrn, crtcport, crtcindex, value);
2114
2115 return true;
2116}
2117
2118static bool init_pll(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2119{
2120 /* INIT_PLL opcode: 0x79 ('y')
2121 *
2122 * offset (8 bit): opcode
2123 * offset + 1 (32 bit): register
2124 * offset + 5 (16 bit): freq
2125 *
2126 * Set PLL register "register" to coefficients for frequency (10kHz) "freq"
2127 */
2128
2129 uint32_t reg = ROM32(bios->data[offset + 1]);
2130 uint16_t freq = ROM16(bios->data[offset + 5]);
2131
2132 if (!iexec->execute)
2133 return true;
2134
2135 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq);
2136
2137 setPLL(pScrn, bios, reg, freq * 10);
2138
2139 return true;
2140}
2141
2142static bool init_zm_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2143{
2144 /* INIT_ZM_REG opcode: 0x7A ('z')
2145 *
2146 * offset (8 bit): opcode
2147 * offset + 1 (32 bit): register
2148 * offset + 5 (32 bit): value
2149 *
2150 * Assign "value" to "register"
2151 */
2152
2153 uint32_t reg = ROM32(bios->data[offset + 1]);
2154 uint32_t value = ROM32(bios->data[offset + 5]);
2155
2156 if (!iexec->execute)
2157 return true;
2158
2159 bios_wr32(pScrn, reg, value);
2160
2161 return true;
2162}
2163
2164static bool init_8e(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2165{
2166 /* INIT_8E opcode: 0x8E ('')
2167 *
2168 * offset (8 bit): opcode
2169 *
2170 * The purpose of this opcode is unclear (being for nv50 cards), and
2171 * the literal functionality can be seen in the code below.
2172 *
2173 * A brief synopsis is that for each entry in a table pointed to by the
2174 * DCB table header, depending on the settings of various bits, various
2175 * other bits in registers 0xe100, 0xe104, and 0xe108, are set or
2176 * cleared.
2177 */
2178
2179 uint8_t headerlen = bios->data[bios->bdcb.init8e_table_ptr + 1];
2180 uint8_t entries = bios->data[bios->bdcb.init8e_table_ptr + 2];
2181 uint8_t recordlen = bios->data[bios->bdcb.init8e_table_ptr + 3];
2182 int i;
2183
2184 if (bios->bdcb.version != 0x40) {
2185 NV_ERROR(pScrn, "DCB table not version 4.0\n");
2186 return false;
2187 }
2188 if (!bios->bdcb.init8e_table_ptr) {
2189 NV_WARN(pScrn, "Invalid pointer to INIT_8E table\n");
2190 return false;
2191 }
2192
2193 for (i = 0; i < entries; i++) {
2194 uint32_t entry = ROM32(bios->data[bios->bdcb.init8e_table_ptr + headerlen + recordlen * i]);
2195 int shift = (entry & 0x1f) * 4;
2196 uint32_t mask;
2197 uint32_t reg = 0xe104;
2198 uint32_t data;
2199
2200 if ((entry & 0xff00) == 0xff00)
2201 continue;
2202
2203 if (shift >= 32) {
2204 reg += 4;
2205 shift -= 32;
2206 }
2207 shift %= 32;
2208
2209 mask = ~(3 << shift);
2210 if (entry & (1 << 24))
2211 data = (entry >> 21);
2212 else
2213 data = (entry >> 19);
2214 data = ((data & 3) ^ 2) << shift;
2215
2216 BIOSLOG(pScrn, "0x%04X: Entry: 0x%08X, Reg: 0x%08X, Shift: 0x%02X, Mask: 0x%08X, Data: 0x%08X\n",
2217 offset, entry, reg, shift, mask, data);
2218
2219 bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data);
2220
2221 reg = 0xe100;
2222 shift = entry & 0x1f;
2223
2224 mask = ~(1 << 16 | 1);
2225 mask = mask << shift | mask >> (32 - shift);
2226 data = 0;
2227 if ((entry & (3 << 25)) == (1 << 25))
2228 data |= 1;
2229 if ((entry & (3 << 25)) == (2 << 25))
2230 data |= 0x10000;
2231 data <<= shift;
2232
2233 BIOSLOG(pScrn, "0x%04X: Entry: 0x%08X, Reg: 0x%08X, Shift: 0x%02X, Mask: 0x%08X, Data: 0x%08X\n",
2234 offset, entry, reg, shift, mask, data);
2235
2236 bios_wr32(pScrn, reg, (bios_rd32(pScrn, reg) & mask) | data);
2237 }
2238
2239 return true;
2240}
2241
2242/* hack to avoid moving the itbl_entry array before this function */
2243int init_ram_restrict_zm_reg_group_blocklen = 0;
2244
2245static bool init_ram_restrict_zm_reg_group(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2246{
2247 /* INIT_RAM_RESTRICT_ZM_REG_GROUP opcode: 0x8F ('')
2248 *
2249 * offset (8 bit): opcode
2250 * offset + 1 (32 bit): reg
2251 * offset + 5 (8 bit): regincrement
2252 * offset + 6 (8 bit): count
2253 * offset + 7 (32 bit): value 1,1
2254 * ...
2255 *
2256 * Use the RAMCFG strap of PEXTDEV_BOOT as an index into the table at
2257 * ram_restrict_table_ptr. The value read from here is 'n', and
2258 * "value 1,n" gets written to "reg". This repeats "count" times and on
2259 * each iteration 'm', "reg" increases by "regincrement" and
2260 * "value m,n" is used. The extent of n is limited by a number read
2261 * from the 'M' BIT table, herein called "blocklen"
2262 */
2263
2264 uint32_t reg = ROM32(bios->data[offset + 1]);
2265 uint8_t regincrement = bios->data[offset + 5];
2266 uint8_t count = bios->data[offset + 6];
2267 uint32_t strap_ramcfg, data;
2268 uint16_t blocklen;
2269 uint8_t index;
2270 int i;
2271
2272 /* previously set by 'M' BIT table */
2273 blocklen = init_ram_restrict_zm_reg_group_blocklen;
2274
2275 if (!iexec->execute)
2276 return true;
2277
2278 if (!blocklen) {
2279 NV_ERROR(pScrn, "0x%04X: Zero block length - has the M table "
2280 "been parsed?\n", offset);
2281 return false;
2282 }
2283
2284 strap_ramcfg = (bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 2) & 0xf;
2285 index = bios->data[bios->ram_restrict_tbl_ptr + strap_ramcfg];
2286
2287 BIOSLOG(pScrn, "0x%04X: Reg: 0x%08X, RegIncrement: 0x%02X, Count: 0x%02X, StrapRamCfg: 0x%02X, Index: 0x%02X\n",
2288 offset, reg, regincrement, count, strap_ramcfg, index);
2289
2290 for (i = 0; i < count; i++) {
2291 data = ROM32(bios->data[offset + 7 + index * 4 + blocklen * i]);
2292
2293 bios_wr32(pScrn, reg, data);
2294
2295 reg += regincrement;
2296 }
2297
2298 return true;
2299}
2300
2301static bool init_copy_zm_reg(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2302{
2303 /* INIT_COPY_ZM_REG opcode: 0x90 ('')
2304 *
2305 * offset (8 bit): opcode
2306 * offset + 1 (32 bit): src reg
2307 * offset + 5 (32 bit): dst reg
2308 *
2309 * Put contents of "src reg" into "dst reg"
2310 */
2311
2312 uint32_t srcreg = ROM32(bios->data[offset + 1]);
2313 uint32_t dstreg = ROM32(bios->data[offset + 5]);
2314
2315 if (!iexec->execute)
2316 return true;
2317
2318 bios_wr32(pScrn, dstreg, bios_rd32(pScrn, srcreg));
2319
2320 return true;
2321}
2322
2323static bool init_zm_reg_group_addr_latched(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2324{
2325 /* INIT_ZM_REG_GROUP_ADDRESS_LATCHED opcode: 0x91 ('')
2326 *
2327 * offset (8 bit): opcode
2328 * offset + 1 (32 bit): dst reg
2329 * offset + 5 (8 bit): count
2330 * offset + 6 (32 bit): data 1
2331 * ...
2332 *
2333 * For each of "count" values write "data n" to "dst reg"
2334 */
2335
2336 uint32_t reg = ROM32(bios->data[offset + 1]);
2337 uint8_t count = bios->data[offset + 5];
2338 int i;
2339
2340 if (!iexec->execute)
2341 return true;
2342
2343 for (i = 0; i < count; i++) {
2344 uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]);
2345 bios_wr32(pScrn, reg, data);
2346 }
2347
2348 return true;
2349}
2350
2351static bool init_reserved(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset, init_exec_t *iexec)
2352{
2353 /* INIT_RESERVED opcode: 0x92 ('')
2354 *
2355 * offset (8 bit): opcode
2356 *
2357 * Seemingly does nothing
2358 */
2359
2360 return true;
2361}
2362
2363static init_tbl_entry_t itbl_entry[] = {
2364 /* command name , id , length , offset , mult , command handler */
2365 /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
2366 { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog },
2367 { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat },
2368 { "INIT_IO_RESTRICT_PLL" , 0x34, 12 , 7 , 2 , init_io_restrict_pll },
2369 { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat },
2370 { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy },
2371 { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not },
2372 { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition },
2373 { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, 18 , 17 , 2 , init_idx_addr_latched },
2374 { "INIT_IO_RESTRICT_PLL2" , 0x4A, 11 , 6 , 4 , init_io_restrict_pll2 },
2375 { "INIT_PLL2" , 0x4B, 9 , 0 , 0 , init_pll2 },
2376 { "INIT_I2C_BYTE" , 0x4C, 4 , 3 , 3 , init_i2c_byte },
2377 { "INIT_ZM_I2C_BYTE" , 0x4D, 4 , 3 , 2 , init_zm_i2c_byte },
2378 { "INIT_ZM_I2C" , 0x4E, 4 , 3 , 1 , init_zm_i2c },
2379 { "INIT_TMDS" , 0x4F, 5 , 0 , 0 , init_tmds },
2380 { "INIT_ZM_TMDS_GROUP" , 0x50, 3 , 2 , 2 , init_zm_tmds_group },
2381 { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch },
2382 { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr },
2383 { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr },
2384 { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group },
2385 { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time },
2386 { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence },
2387 /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
2388 { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct },
2389 { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg },
2390 { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io },
2391 { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem },
2392 { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset },
2393 { "INIT_CONFIGURE_MEM" , 0x66, 1 , 0 , 0 , init_configure_mem },
2394 { "INIT_CONFIGURE_CLK" , 0x67, 1 , 0 , 0 , init_configure_clk },
2395 { "INIT_CONFIGURE_PREINIT" , 0x68, 1 , 0 , 0 , init_configure_preinit },
2396 { "INIT_IO" , 0x69, 5 , 0 , 0 , init_io },
2397 { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub },
2398 { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition },
2399 { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg },
2400 { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro },
2401 { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done },
2402 { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume },
2403 /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */
2404 { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time },
2405 { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition },
2406 { "INIT_IO_CONDITION" , 0x76, 2 , 0 , 0 , init_io_condition },
2407 { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io },
2408 { "INIT_PLL" , 0x79, 7 , 0 , 0 , init_pll },
2409 { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg },
2410 { "INIT_8E" , 0x8E, 1 , 0 , 0 , init_8e },
2411 /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */
2412 { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, 7 , 6 , 0 , init_ram_restrict_zm_reg_group },
2413 { "INIT_COPY_ZM_REG" , 0x90, 9 , 0 , 0 , init_copy_zm_reg },
2414 { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6 , 5 , 4 , init_zm_reg_group_addr_latched },
2415 { "INIT_RESERVED" , 0x92, 1 , 0 , 0 , init_reserved },
2416 { 0 , 0 , 0 , 0 , 0 , 0 }
2417};
2418
2419static unsigned int get_init_table_entry_length(struct nvbios *bios, unsigned int offset, int i)
2420{
2421 /* Calculates the length of a given init table entry. */
2422 return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier;
2423}
2424
2425#define MAX_TABLE_OPS 1000
2426
2427static int parse_init_table(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset, init_exec_t *iexec)
2428{
2429 /* Parses all commands in an init table.
2430 *
2431 * We start out executing all commands found in the init table. Some
2432 * opcodes may change the status of iexec->execute to SKIP, which will
2433 * cause the following opcodes to perform no operation until the value
2434 * is changed back to EXECUTE.
2435 */
2436
2437 int count = 0, i;
2438 uint8_t id;
2439
2440 /* Loop until INIT_DONE causes us to break out of the loop
2441 * (or until offset > bios length just in case... )
2442 * (and no more than MAX_TABLE_OPS iterations, just in case... ) */
2443 while ((offset < bios->length) && (count++ < MAX_TABLE_OPS)) {
2444 id = bios->data[offset];
2445
2446 /* Find matching id in itbl_entry */
2447 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != id); i++)
2448 ;
2449
2450 if (itbl_entry[i].name) {
2451 BIOSLOG(pScrn, "0x%04X: [ (0x%02X) - %s ]\n",
2452 offset, itbl_entry[i].id, itbl_entry[i].name);
2453
2454 /* execute eventual command handler */
2455 if (itbl_entry[i].handler)
2456 if (!(*itbl_entry[i].handler)(pScrn, bios, offset, iexec))
2457 break;
2458 } else {
2459 NV_ERROR(pScrn, "0x%04X: Init table command not found: "
2460 "0x%02X\n", offset, id);
2461 return -ENOENT;
2462 }
2463
2464 /* Add the offset of the current command including all data
2465 * of that command. The offset will then be pointing on the
2466 * next op code.
2467 */
2468 offset += get_init_table_entry_length(bios, offset, i);
2469 }
2470
2471 if (offset >= bios->length)
2472 NV_WARN(pScrn,
2473 "Offset 0x%04X greater than known bios image length. "
2474 "Corrupt image?\n", offset);
2475 if (count >= MAX_TABLE_OPS)
2476 NV_WARN(pScrn, "More than %d opcodes to a table is unlikely, "
2477 "is the bios image corrupt?\n", MAX_TABLE_OPS);
2478
2479 return 0;
2480}
2481
2482static void parse_init_tables(ScrnInfoPtr pScrn, struct nvbios *bios)
2483{
2484 /* Loops and calls parse_init_table() for each present table. */
2485
2486 int i = 0;
2487 uint16_t table;
2488 init_exec_t iexec = {true, false};
2489
2490 if (bios->old_style_init) {
2491 if (bios->init_script_tbls_ptr)
2492 parse_init_table(pScrn, bios, bios->init_script_tbls_ptr, &iexec);
2493 if (bios->extra_init_script_tbl_ptr)
2494 parse_init_table(pScrn, bios, bios->extra_init_script_tbl_ptr, &iexec);
2495
2496 return;
2497 }
2498
2499 while ((table = ROM16(bios->data[bios->init_script_tbls_ptr + i]))) {
2500 NV_INFO(pScrn, "Parsing VBIOS init table %d at offset 0x%04X\n",
2501 i / 2, table);
2502 BIOSLOG(pScrn, "0x%04X: ------ Executing following commands ------\n", table);
2503
2504 parse_init_table(pScrn, bios, table, &iexec);
2505 i += 2;
2506 }
2507}
2508
2509static void link_head_and_output(NVPtr pNv, struct dcb_entry *dcbent, int head, bool dl)
2510{
2511 /* The BIOS scripts don't do this for us, sadly
2512 * Luckily we do know the values ;-)
2513 *
2514 * head < 0 indicates we wish to force a setting with the overrideval
2515 * (for VT restore etc.)
2516 */
2517
2518 int ramdac = (dcbent->or & OUTPUT_C) >> 2;
2519 uint8_t tmds04 = 0x80;
2520
2521 if (head != ramdac)
2522 tmds04 = 0x88;
2523
2524 if (dcbent->type == OUTPUT_LVDS)
2525 tmds04 |= 0x01;
2526
2527 nv_write_tmds(pNv, dcbent->or, 0, 0x04, tmds04);
2528
2529 if (dl) /* dual link */
2530 nv_write_tmds(pNv, dcbent->or, 1, 0x04, tmds04 ^ 0x08);
2531}
2532
2533static uint16_t clkcmptable(struct nvbios *bios, uint16_t clktable, int pxclk)
2534{
2535 int compare_record_len, i = 0;
2536 uint16_t compareclk, scriptptr = 0;
2537
2538 if (bios->major_version < 5) /* pre BIT */
2539 compare_record_len = 3;
2540 else
2541 compare_record_len = 4;
2542
2543 do {
2544 compareclk = ROM16(bios->data[clktable + compare_record_len * i]);
2545 if (pxclk >= compareclk * 10) {
2546 if (bios->major_version < 5) {
2547 uint8_t tmdssub = bios->data[clktable + 2 + compare_record_len * i];
2548 scriptptr = ROM16(bios->data[bios->init_script_tbls_ptr + tmdssub * 2]);
2549 } else
2550 scriptptr = ROM16(bios->data[clktable + 2 + compare_record_len * i]);
2551 break;
2552 }
2553 i++;
2554 } while (compareclk);
2555
2556 return scriptptr;
2557}
2558
2559static void run_digital_op_script(ScrnInfoPtr pScrn, uint16_t scriptptr, struct dcb_entry *dcbent, int head, bool dl)
2560{
2561 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
2562 init_exec_t iexec = {true, false};
2563
2564 NV_TRACE(pScrn, "0x%04X: Parsing digital output script table\n",
2565 scriptptr);
2566 bios_idxprt_wr(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_44,
2567 head ? NV_CIO_CRE_44_HEADB : NV_CIO_CRE_44_HEADA);
2568 /* note: if dcb entries have been merged, index may be misleading */
2569 NVWriteVgaCrtc5758(NVPTR(pScrn), head, 0, dcbent->index);
2570 parse_init_table(pScrn, bios, scriptptr, &iexec);
2571
2572 link_head_and_output(NVPTR(pScrn), dcbent, head, dl);
2573}
2574
2575static int call_lvds_manufacturer_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script)
2576{
2577 NVPtr pNv = NVPTR(pScrn);
2578 struct nvbios *bios = &pNv->VBIOS;
2579 uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0);
2580 uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
2581
2582 if (!bios->fp.xlated_entry || !sub || !scriptofs)
2583 return -EINVAL;
2584
2585 run_digital_op_script(pScrn, scriptofs, dcbent, head, bios->fp.dual_link);
2586
2587 if (script == LVDS_PANEL_OFF)
2588 /* off-on delay in ms */
2589 BIOS_USLEEP(ROM16(bios->data[bios->fp.xlated_entry + 7]));
2590#ifdef __powerpc__
2591 /* Powerbook specific quirks */
2592 if (script == LVDS_RESET && ((pNv->Chipset & 0xffff) == 0x0179 || (pNv->Chipset & 0xffff) == 0x0329))
2593 nv_write_tmds(pNv, dcbent->or, 0, 0x02, 0x72);
2594 if ((pNv->Chipset & 0xffff) == 0x0179 || (pNv->Chipset & 0xffff) == 0x0189 || (pNv->Chipset & 0xffff) == 0x0329) {
2595 if (script == LVDS_PANEL_ON) {
2596 bios_wr32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
2597 bios_wr32(pScrn, NV_PCRTC_GPIO_EXT, bios_rd32(pScrn, NV_PCRTC_GPIO_EXT) | 1);
2598 }
2599 if (script == LVDS_PANEL_OFF) {
2600 bios_wr32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(pScrn, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
2601 bios_wr32(pScrn, NV_PCRTC_GPIO_EXT, bios_rd32(pScrn, NV_PCRTC_GPIO_EXT) & ~3);
2602 }
2603 }
2604#endif
2605
2606 return 0;
2607}
2608
2609static int run_lvds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk)
2610{
2611 /* The BIT LVDS table's header has the information to setup the
2612 * necessary registers. Following the standard 4 byte header are:
2613 * A bitmask byte and a dual-link transition pxclk value for use in
2614 * selecting the init script when not using straps; 4 script pointers
2615 * for panel power, selected by output and on/off; and 8 table pointers
2616 * for panel init, the needed one determined by output, and bits in the
2617 * conf byte. These tables are similar to the TMDS tables, consisting
2618 * of a list of pxclks and script pointers.
2619 */
2620
2621 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
2622 unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
2623 uint16_t scriptptr = 0, clktable;
2624 uint8_t clktableptr = 0;
2625
2626 /* for now we assume version 3.0 table - g80 support will need some changes */
2627
2628 switch (script) {
2629 case LVDS_INIT:
2630 return -ENOSYS;
2631 case LVDS_BACKLIGHT_ON:
2632 case LVDS_PANEL_ON:
2633 scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 7 + outputset * 2]);
2634 break;
2635 case LVDS_BACKLIGHT_OFF:
2636 case LVDS_PANEL_OFF:
2637 scriptptr = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 11 + outputset * 2]);
2638 break;
2639 case LVDS_RESET:
2640 if (dcbent->lvdsconf.use_straps_for_mode) {
2641 if (bios->fp.dual_link)
2642 clktableptr += 2;
2643 if (bios->fp.BITbit1)
2644 clktableptr++;
2645 } else {
2646 /* using EDID */
2647 uint8_t fallback = bios->data[bios->fp.lvdsmanufacturerpointer + 4];
2648 int fallbackcmpval = (dcbent->or == 4) ? 4 : 1;
2649
2650 if (bios->fp.dual_link) {
2651 clktableptr += 2;
2652 fallbackcmpval *= 2;
2653 }
2654 if (fallbackcmpval & fallback)
2655 clktableptr++;
2656 }
2657
2658 /* adding outputset * 8 may not be correct */
2659 clktable = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 15 + clktableptr * 2 + outputset * 8]);
2660 if (!clktable) {
2661 NV_ERROR(pScrn, "Pixel clock comparison table not found\n");
2662 return -ENOENT;
2663 }
2664 scriptptr = clkcmptable(bios, clktable, pxclk);
2665 }
2666
2667 if (!scriptptr) {
2668 NV_ERROR(pScrn, "LVDS output init script not found\n");
2669 return -ENOENT;
2670 }
2671 run_digital_op_script(pScrn, scriptptr, dcbent, head, bios->fp.dual_link);
2672
2673 return 0;
2674}
2675
2676int call_lvds_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk)
2677{
2678 /* LVDS operations are multiplexed in an effort to present a single API
2679 * which works with two vastly differing underlying structures.
2680 * This acts as the demux
2681 */
2682
2683 NVPtr pNv = NVPTR(pScrn);
2684 struct nvbios *bios = &pNv->VBIOS;
2685 uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2686 uint32_t sel_clk_binding, sel_clk;
2687 int ret;
2688
2689 if (bios->fp.last_script_invoc == (script << 1 | head) || !lvds_ver ||
2690 (lvds_ver >= 0x30 && script == LVDS_INIT))
2691 return 0;
2692
2693 if (!bios->fp.lvds_init_run) {
2694 bios->fp.lvds_init_run = true;
2695 call_lvds_script(pScrn, dcbent, head, LVDS_INIT, pxclk);
2696 }
2697
2698 if (script == LVDS_PANEL_ON && bios->fp.reset_after_pclk_change)
2699 call_lvds_script(pScrn, dcbent, head, LVDS_RESET, pxclk);
2700 if (script == LVDS_RESET && bios->fp.power_off_for_reset)
2701 call_lvds_script(pScrn, dcbent, head, LVDS_PANEL_OFF, pxclk);
2702
2703 NV_TRACE(pScrn, "Calling LVDS script %d:\n", script);
2704
2705 /* don't let script change pll->head binding */
2706 sel_clk_binding = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK) & 0x50000;
2707
2708 if (lvds_ver < 0x30)
2709 ret = call_lvds_manufacturer_script(pScrn, dcbent, head, script);
2710 else
2711 ret = run_lvds_table(pScrn, dcbent, head, script, pxclk);
2712
2713 bios->fp.last_script_invoc = (script << 1 | head);
2714
2715 sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
2716 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
2717 /* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */
2718 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, 0);
2719
2720 return ret;
2721}
2722
2723struct lvdstableheader {
2724 uint8_t lvds_ver, headerlen, recordlen;
2725};
2726
2727static int parse_lvds_manufacturer_table_header(ScrnInfoPtr pScrn, struct nvbios *bios, struct lvdstableheader *lth)
2728{
2729 /* BMP version (0xa) LVDS table has a simple header of version and
2730 * record length. The BIT LVDS table has the typical BIT table header:
2731 * version byte, header length byte, record length byte, and a byte for
2732 * the maximum number of records that can be held in the table */
2733
2734 uint8_t lvds_ver, headerlen, recordlen;
2735
2736 memset(lth, 0, sizeof(struct lvdstableheader));
2737
2738 if (bios->fp.lvdsmanufacturerpointer == 0x0) {
2739 NV_ERROR(pScrn, "Pointer to LVDS manufacturer table invalid\n");
2740 return -EINVAL;
2741 }
2742
2743 lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
2744
2745 switch (lvds_ver) {
2746 case 0x0a: /* pre NV40 */
2747 headerlen = 2;
2748 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2749 break;
2750 case 0x30: /* NV4x */
2751 headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2752 if (headerlen < 0x1f) {
2753 NV_ERROR(pScrn, "LVDS table header not understood\n");
2754 return -EINVAL;
2755 }
2756 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
2757 break;
2758 case 0x40: /* G80/G90 */
2759 headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1];
2760 if (headerlen < 0x7) {
2761 NV_ERROR(pScrn, "LVDS table header not understood\n");
2762 return -EINVAL;
2763 }
2764 recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2];
2765 break;
2766 default:
2767 NV_ERROR(pScrn,
2768 "LVDS table revision %d.%d not currently supported\n",
2769 lvds_ver >> 4, lvds_ver & 0xf);
2770 return -ENOSYS;
2771 }
2772
2773 lth->lvds_ver = lvds_ver;
2774 lth->headerlen = headerlen;
2775 lth->recordlen = recordlen;
2776
2777 return 0;
2778}
2779
2780static int get_fp_strap(ScrnInfoPtr pScrn, struct nvbios *bios)
2781{
2782 /* the fp strap is normally dictated by the "User Strap" in
2783 * PEXTDEV_BOOT_0[20:16], but on BMP cards when bit 2 of the
2784 * Internal_Flags struct at 0x48 is set, the user strap gets overriden
2785 * by the PCI subsystem ID during POST, but not before the previous user
2786 * strap has been committed to CR58 for CR57=0xf on head A, which may be
2787 * read and used instead
2788 */
2789 NVPtr pNv = NVPTR(pScrn);
2790
2791 if (bios->major_version < 5 && bios->data[0x48] & 0x4)
2792 return (NVReadVgaCrtc5758(NVPTR(pScrn), 0, 0xf) & 0xf);
2793
2794 if (pNv->Architecture >= NV_ARCH_50)
2795 return ((bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 24) & 0xf);
2796 else
2797 return ((bios_rd32(pScrn, NV_PEXTDEV_BOOT_0) >> 16) & 0xf);
2798}
2799
2800static int parse_fp_mode_table(ScrnInfoPtr pScrn, struct nvbios *bios)
2801{
2802 uint8_t *fptable;
2803 uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex;
2804 int ret, ofs, fpstrapping;
2805 struct lvdstableheader lth;
2806
2807 if (bios->fp.fptablepointer == 0x0) {
2808 /* Apple cards don't have the fp table; the laptops use DDC */
2809 /* The table is also missing on some x86 IGPs */
2810#ifndef __powerpc__
2811 NV_WARN(pScrn, "Pointer to flat panel table invalid\n");
2812#endif
2813 bios->pub.digital_min_front_porch = 0x4b;
2814 return 0;
2815 }
2816
2817 fptable = &bios->data[bios->fp.fptablepointer];
2818 fptable_ver = fptable[0];
2819
2820 switch (fptable_ver) {
2821 /* BMP version 0x5.0x11 BIOSen have version 1 like tables, but no version field,
2822 * and miss one of the spread spectrum/PWM bytes.
2823 * This could affect early GF2Go parts (not seen any appropriate ROMs though).
2824 * Here we assume that a version of 0x05 matches this case (combining with a
2825 * BMP version check would be better), as the common case for the panel type
2826 * field is 0x0005, and that is in fact what we are reading the first byte of. */
2827 case 0x05: /* some NV10, 11, 15, 16 */
2828 recordlen = 42;
2829 ofs = -1;
2830 break;
2831 case 0x10: /* some NV15/16, and NV11+ */
2832 recordlen = 44;
2833 ofs = 0;
2834 break;
2835 case 0x20: /* NV40+ */
2836 headerlen = fptable[1];
2837 recordlen = fptable[2];
2838 fpentries = fptable[3];
2839 /* fptable[4] is the minimum RAMDAC_FP_HCRTC->RAMDAC_FP_HSYNC_START gap */
2840 bios->pub.digital_min_front_porch = fptable[4];
2841 ofs = -7;
2842 break;
2843 default:
2844 NV_ERROR(pScrn,
2845 "FP table revision %d.%d not currently supported\n",
2846 fptable_ver >> 4, fptable_ver & 0xf);
2847 return -ENOSYS;
2848 }
2849
2850 if (!bios->is_mobile) /* !mobile only needs digital_min_front_porch */
2851 return 0;
2852
2853 if ((ret = parse_lvds_manufacturer_table_header(pScrn, bios, &lth)))
2854 return ret;
2855
2856 if (lth.lvds_ver == 0x30 || lth.lvds_ver == 0x40) {
2857 bios->fp.fpxlatetableptr = bios->fp.lvdsmanufacturerpointer + lth.headerlen + 1;
2858 bios->fp.xlatwidth = lth.recordlen;
2859 }
2860 if (bios->fp.fpxlatetableptr == 0x0) {
2861 NV_ERROR(pScrn, "Pointer to flat panel xlat table invalid\n");
2862 return -EINVAL;
2863 }
2864
2865 fpstrapping = get_fp_strap(pScrn, bios);
2866
2867 fpindex = bios->data[bios->fp.fpxlatetableptr + fpstrapping * bios->fp.xlatwidth];
2868
2869 if (fpindex > fpentries) {
2870 NV_ERROR(pScrn, "Bad flat panel table index\n");
2871 return -ENOENT;
2872 }
2873
2874 /* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
2875 if (lth.lvds_ver > 0x10)
2876 bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
2877
2878 /* if either the strap or xlated fpindex value are 0xf there is no
2879 * panel using a strap-derived bios mode present. this condition
2880 * includes, but is different from, the DDC panel indicator above
2881 */
2882 if (fpstrapping == 0xf || fpindex == 0xf)
2883 return 0;
2884
2885 bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen +
2886 recordlen * fpindex + ofs;
2887
2888 NV_TRACE(pScrn, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n",
2889 ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1,
2890 ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1,
2891 ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10);
2892
2893 return 0;
2894}
2895
2896bool nouveau_bios_fp_mode(ScrnInfoPtr pScrn, DisplayModeRec *mode)
2897{
2898 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
2899 uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
2900
2901 if (!mode) /* just checking whether we can produce a mode */
2902 return bios->fp.mode_ptr;
2903
2904 memset(mode, 0, sizeof(DisplayModeRec));
2905 /* for version 1.0 (version in byte 0):
2906 * bytes 1-2 are "panel type", including bits on whether Colour/mono,
2907 * single/dual link, and type (TFT etc.)
2908 * bytes 3-6 are bits per colour in RGBX */
2909 mode->Clock = ROM16(mode_entry[7]) * 10;
2910 /* bytes 9-10 is HActive */
2911 mode->HDisplay = ROM16(mode_entry[11]) + 1;
2912 /* bytes 13-14 is HValid Start
2913 * bytes 15-16 is HValid End */
2914 mode->HSyncStart = ROM16(mode_entry[17]) + 1;
2915 mode->HSyncEnd = ROM16(mode_entry[19]) + 1;
2916 mode->HTotal = ROM16(mode_entry[21]) + 1;
2917 /* bytes 23-24, 27-30 similarly, but vertical */
2918 mode->VDisplay = ROM16(mode_entry[25]) + 1;
2919 mode->VSyncStart = ROM16(mode_entry[31]) + 1;
2920 mode->VSyncEnd = ROM16(mode_entry[33]) + 1;
2921 mode->VTotal = ROM16(mode_entry[35]) + 1;
2922 mode->Flags |= (mode_entry[37] & 0x10) ? V_PHSYNC : V_NHSYNC;
2923 mode->Flags |= (mode_entry[37] & 0x1) ? V_PVSYNC : V_NVSYNC;
2924 /* bytes 38-39 relate to spread spectrum settings
2925 * bytes 40-43 are something to do with PWM */
2926
2927 return bios->fp.mode_ptr;
2928}
2929
2930int nouveau_bios_parse_lvds_table(ScrnInfoPtr pScrn, int pxclk, bool *dl, bool *if_is_24bit)
2931{
2932 /* The LVDS table header is (mostly) described in
2933 * parse_lvds_manufacturer_table_header(): the BIT header additionally
2934 * contains the dual-link transition pxclk (in 10s kHz), at byte 5 - if
2935 * straps are not being used for the panel, this specifies the frequency
2936 * at which modes should be set up in the dual link style.
2937 *
2938 * Following the header, the BMP (ver 0xa) table has several records,
2939 * indexed by a seperate xlat table, indexed in turn by the fp strap in
2940 * EXTDEV_BOOT. Each record had a config byte, followed by 6 script
2941 * numbers for use by INIT_SUB which controlled panel init and power,
2942 * and finally a dword of ms to sleep between power off and on
2943 * operations.
2944 *
2945 * In the BIT versions, the table following the header serves as an
2946 * integrated config and xlat table: the records in the table are
2947 * indexed by the FP strap nibble in EXTDEV_BOOT, and each record has
2948 * two bytes - the first as a config byte, the second for indexing the
2949 * fp mode table pointed to by the BIT 'D' table
2950 *
2951 * DDC is not used until after card init, so selecting the correct table
2952 * entry and setting the dual link flag for EDID equipped panels,
2953 * requiring tests against the native-mode pixel clock, cannot be done
2954 * until later, when this function should be called with non-zero pxclk
2955 */
2956
2957 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
2958 int fpstrapping = get_fp_strap(pScrn, bios), lvdsmanufacturerindex = 0;
2959 struct lvdstableheader lth;
2960 uint16_t lvdsofs;
2961 int ret, chip_version = bios->pub.chip_version;
2962
2963 if ((ret = parse_lvds_manufacturer_table_header(pScrn, bios, &lth)))
2964 return ret;
2965
2966 switch (lth.lvds_ver) {
2967 case 0x0a: /* pre NV40 */
2968 lvdsmanufacturerindex = bios->data[bios->fp.fpxlatemanufacturertableptr + fpstrapping];
2969
2970 /* we're done if this isn't the EDID panel case */
2971 if (!pxclk)
2972 break;
2973
2974 if (chip_version < 0x25) {
2975 /* nv17 behaviour */
2976 /* it seems the old style lvds script pointer is reused
2977 * to select 18/24 bit colour depth for EDID panels */
2978 lvdsmanufacturerindex = (bios->legacy.lvds_single_a_script_ptr & 1) ? 2 : 0;
2979 if (pxclk >= bios->fp.duallink_transition_clk)
2980 lvdsmanufacturerindex++;
2981 } else if (chip_version < 0x30) {
2982 /* nv28 behaviour (off-chip encoder) */
2983 /* nv28 does a complex dance of first using byte 121 of
2984 * the EDID to choose the lvdsmanufacturerindex, then
2985 * later attempting to match the EDID manufacturer and
2986 * product IDs in a table (signature 'pidt' (panel id
2987 * table?)), setting an lvdsmanufacturerindex of 0 and
2988 * an fp strap of the match index (or 0xf if none)
2989 */
2990 lvdsmanufacturerindex = 0;
2991 } else {
2992 /* nv31, nv34 behaviour */
2993 lvdsmanufacturerindex = 0;
2994 if (pxclk >= bios->fp.duallink_transition_clk)
2995 lvdsmanufacturerindex = 2;
2996 if (pxclk >= 140000)
2997 lvdsmanufacturerindex = 3;
2998 }
2999
3000 /* nvidia set the high nibble of (cr57=f, cr58) to
3001 * lvdsmanufacturerindex in this case; we don't */
3002 break;
3003 case 0x30: /* NV4x */
3004 case 0x40: /* G80/G90 */
3005 lvdsmanufacturerindex = fpstrapping;
3006 break;
3007 default:
3008 NV_ERROR(pScrn, "LVDS table revision not currently supported\n");
3009 return -ENOSYS;
3010 }
3011
3012 lvdsofs = bios->fp.xlated_entry = bios->fp.lvdsmanufacturerpointer + lth.headerlen + lth.recordlen * lvdsmanufacturerindex;
3013 switch (lth.lvds_ver) {
3014 case 0x0a:
3015 bios->fp.power_off_for_reset = bios->data[lvdsofs] & 1;
3016 bios->fp.reset_after_pclk_change = bios->data[lvdsofs] & 2;
3017 bios->fp.dual_link = bios->data[lvdsofs] & 4;
3018 bios->fp.link_c_increment = bios->data[lvdsofs] & 8;
3019 *if_is_24bit = bios->data[lvdsofs] & 16;
3020 break;
3021 case 0x30:
3022 /* My money would be on there being a 24 bit interface bit in this table,
3023 * but I have no example of a laptop bios with a 24 bit panel to confirm that.
3024 * Hence we shout loudly if any bit other than bit 0 is set (I've not even
3025 * seen bit 1)
3026 */
3027 if (bios->data[lvdsofs] > 1)
3028 NV_ERROR(pScrn,
3029 "You have a very unusual laptop display; please report it\n");
3030 /* no sign of the "power off for reset" or "reset for panel on" bits, but it's safer to assume we should */
3031 bios->fp.power_off_for_reset = true;
3032 bios->fp.reset_after_pclk_change = true;
3033 /* it's ok lvdsofs is wrong for nv4x edid case; dual_link is
3034 * over-written, and BITbit1 isn't used */
3035 bios->fp.dual_link = bios->data[lvdsofs] & 1;
3036 bios->fp.BITbit1 = bios->data[lvdsofs] & 2;
3037 bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
3038#if 0 // currently unused
3039 break;
3040 case 0x40:
3041 /* fairly sure, but not 100% */
3042 bios->fp.dual_link = bios->data[lvdsofs] & 1;
3043 bios->fp.duallink_transition_clk = ROM16(bios->data[bios->fp.lvdsmanufacturerpointer + 5]) * 10;
3044 break;
3045#endif
3046 }
3047
3048 /* set dual_link flag for EDID case */
3049 if (pxclk && (chip_version < 0x25 || chip_version > 0x28))
3050 bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk);
3051
3052 *dl = bios->fp.dual_link;
3053
3054 return 0;
3055}
3056
3057static int
3058find_script_pointers(ScrnInfoPtr pScrn, uint8_t *table, uint16_t *script0,
3059 uint16_t *script1, uint16_t headerlen, int pxclk)
3060{
3061 /* The output script tables describing a particular output type
3062 * look as follows:
3063 *
3064 * offset + 0 (32 bits): output this table matches (hash of DCB)
3065 * offset + 4 ( 8 bits): unknown
3066 * offset + 5 ( 8 bits): number of configurations
3067 * offset + 6 (16 bits): pointer to some script
3068 * offset + 8 (16 bits): pointer to some script
3069 *
3070 * headerlen == 10
3071 * offset + 10 : configuration 0
3072 *
3073 * headerlen == 12
3074 * offset + 10 : pointer to some script
3075 * offset + 12 : configuration 0
3076 *
3077 * Each config entry is as follows:
3078 *
3079 * offset + 0 (16 bits): unknown, assumed to be a match value
3080 * offset + 2 (16 bits): pointer to script table (clock set?)
3081 * offset + 4 (16 bits): pointer to script table (reset?)
3082 *
3083 * There doesn't appear to be a count value to say how many
3084 * entries exist in each script table, instead, a 0 value in
3085 * the first 16-bit word seems to indicate both the end of the
3086 * list and the default entry. The second 16-bit word in the
3087 * script tables is a pointer to the script to execute.
3088 */
3089
3090 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
3091 int i, cmpval = 0x0100;
3092
3093 *script0 = *script1 = 0;
3094 for (i = 0; i < table[5]; i++) {
3095 uint16_t offset;
3096
3097 if (ROM16(table[headerlen + i*6 + 0]) != cmpval)
3098 continue;
3099
3100 offset = ROM16(table[headerlen + i*6 + 2]);
3101 if (offset)
3102 *script0 = clkcmptable(bios, offset, pxclk);
3103
3104 if (!*script0)
3105 NV_WARN(pScrn, "script0 missing!\n");
3106
3107 offset = ROM16(table[headerlen + i*6 + 4]);
3108 if (offset)
3109 *script1 = clkcmptable(bios, offset, pxclk);
3110
3111 return 0;
3112 }
3113
3114 NV_ERROR(pScrn, "couldn't find suitable output scripts\n");
3115 return 1;
3116}
3117
3118int
3119nouveau_bios_run_display_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent,
3120 int pxclk)
3121{
3122 /* The display script table is located by the BIT 'U' table.
3123 *
3124 * It contains an array of pointers to various tables describing
3125 * a particular output type. The first 32-bits of the output
3126 * tables contains similar information to a DCB entry, and is
3127 * used to decide whether that particular table is suitable for
3128 * the output you want to access.
3129 *
3130 * The "record header length" field here seems to indicate the
3131 * offset of the first configuration entry in the output tables.
3132 * This is 10 on most cards I've seen, but 12 has been witnessed
3133 * on DP cards, and there's another script pointer within the
3134 * header.
3135 *
3136 * offset + 0 ( 8 bits): version
3137 * offset + 1 ( 8 bits): header length
3138 * offset + 2 ( 8 bits): record length
3139 * offset + 3 ( 8 bits): number of records
3140 * offset + 4 ( 8 bits): record header length
3141 * offset + 5 (16 bits): pointer to first output script table
3142 */
3143
3144 NVPtr pNv = NVPTR(pScrn);
3145 init_exec_t iexec = {true, false};
3146 struct nvbios *bios = &pNv->VBIOS;
3147 uint8_t *table = &bios->data[bios->display.script_table_ptr];
3148 uint8_t *entry, *otable = NULL;
3149 uint16_t script0, script1;
3150 int i;
3151 bool run_scripts = false;
3152
3153 if (!bios->display.script_table_ptr) {
3154 NV_ERROR(pScrn, "No pointer to output script table\n");
3155 return 1;
3156 }
3157
3158 if (table[0] != 0x20) {
3159 NV_ERROR(pScrn, "Output script table version 0x%02x unknown\n", table[0]);
3160 return 1;
3161 }
3162
3163 NV_DEBUG(pScrn, "Searching for output entry for %d %d %d\n",
3164 dcbent->type, dcbent->location, dcbent->or);
3165 entry = table + table[1];
3166 for (i = 0; i < table[3]; i++, entry += table[2]) {
3167 uint32_t match;
3168
3169 if (ROM16(entry[0]) == 0)
3170 continue;
3171 otable = &bios->data[ROM16(entry[0])];
3172 match = ROM32(otable[0]);
3173
3174 NV_DEBUG(pScrn, " %d: 0x%08x\n", i, match);
3175 if ((((match & 0x000f0000) >> 16) & dcbent->or) &&
3176 ((match & 0x0000000f) >> 0) == dcbent->type &&
3177 ((match & 0x000000f0) >> 4) == dcbent->location)
3178 break;
3179 }
3180
3181 if (i == table[3]) {
3182 NV_ERROR(pScrn, "Couldn't find matching output script table\n");
3183 return 1;
3184 }
3185
3186 if (find_script_pointers(pScrn, otable, &script0, &script1, table[4], pxclk))
3187 return 1;
3188 bios->display.head = ffs(dcbent->or) - 1;
3189
3190 if (script0) {
3191 NV_TRACE(pScrn, "0x%04X: Parsing output Script0\n", script0);
3192 if (run_scripts)
3193 parse_init_table(pScrn, bios, script0, &iexec);
3194 }
3195
3196 if (script1) {
3197 NV_TRACE(pScrn, "0x%04X: Parsing output Script1\n", script1);
3198 if (run_scripts)
3199 parse_init_table(pScrn, bios, script1, &iexec);
3200 }
3201
3202 return run_scripts ? 0 : 1;
3203}
3204
3205int run_tmds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, int pxclk)
3206{
3207 /* the pxclk parameter is in kHz
3208 *
3209 * This runs the TMDS regs setting code found on BIT bios cards
3210 *
3211 * For ffs(or) == 1 use the first table, for ffs(or) == 2 and
3212 * ffs(or) == 3, use the second.
3213 */
3214
3215 NVPtr pNv = NVPTR(pScrn);
3216 struct nvbios *bios = &pNv->VBIOS;
3217 int cv = bios->pub.chip_version;
3218 uint16_t clktable = 0, scriptptr;
3219 uint32_t sel_clk_binding, sel_clk;
3220
3221 /* pre-nv17 off-chip tmds uses scripts, post nv17 doesn't */
3222 if (cv >= 0x17 && cv != 0x1a && cv != 0x20 &&
3223 dcbent->location != DCB_LOC_ON_CHIP)
3224 return 0;
3225
3226 switch (ffs(dcbent->or)) {
3227 case 1:
3228 clktable = bios->tmds.output0_script_ptr;
3229 break;
3230 case 2:
3231 case 3:
3232 clktable = bios->tmds.output1_script_ptr;
3233 break;
3234 }
3235
3236 if (!clktable) {
3237 NV_ERROR(pScrn, "Pixel clock comparison table not found\n");
3238 return -EINVAL;
3239 }
3240
3241 scriptptr = clkcmptable(bios, clktable, pxclk);
3242
3243 if (!scriptptr) {
3244 NV_ERROR(pScrn, "TMDS output init script not found\n");
3245 return -ENOENT;
3246 }
3247
3248 /* don't let script change pll->head binding */
3249 sel_clk_binding = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK) & 0x50000;
3250 run_digital_op_script(pScrn, scriptptr, dcbent, head, pxclk >= 165000);
3251 sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000;
3252 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding);
3253
3254 return 0;
3255}
3256
3257int get_pll_limits(ScrnInfoPtr pScrn, uint32_t limit_match, struct pll_lims *pll_lim)
3258{
3259 /* PLL limits table
3260 *
3261 * Version 0x10: NV30, NV31
3262 * One byte header (version), one record of 24 bytes
3263 * Version 0x11: NV36 - Not implemented
3264 * Seems to have same record style as 0x10, but 3 records rather than 1
3265 * Version 0x20: Found on Geforce 6 cards
3266 * Trivial 4 byte BIT header. 31 (0x1f) byte record length
3267 * Version 0x21: Found on Geforce 7, 8 and some Geforce 6 cards
3268 * 5 byte header, fifth byte of unknown purpose. 35 (0x23) byte record
3269 * length in general, some (integrated) have an extra configuration byte
3270 * Version 0x30: Found on Geforce 8, separates the register mapping
3271 * from the limits tables.
3272 */
3273
3274 NVPtr pNv = NVPTR(pScrn);
3275 struct nvbios *bios = &pNv->VBIOS;
3276 int cv = bios->pub.chip_version, pllindex = 0;
3277 uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0;
3278 uint32_t crystal_strap_mask, crystal_straps;
3279
3280 if (!bios->pll_limit_tbl_ptr) {
3281 if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
3282 cv >= 0x40) {
3283 NV_ERROR(pScrn, "Pointer to PLL limits table invalid\n");
3284 return -EINVAL;
3285 }
3286 } else
3287 pll_lim_ver = bios->data[bios->pll_limit_tbl_ptr];
3288
3289 crystal_strap_mask = 1 << 6;
3290 /* open coded pNv->twoHeads test */
3291 if (cv > 0x10 && cv != 0x15 && cv != 0x1a && cv != 0x20)
3292 crystal_strap_mask |= 1 << 22;
3293 crystal_straps = nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & crystal_strap_mask;
3294
3295 switch (pll_lim_ver) {
3296 /* we use version 0 to indicate a pre limit table bios (single stage pll)
3297 * and load the hard coded limits instead */
3298 case 0:
3299 break;
3300 case 0x10:
3301 case 0x11: /* strictly v0x11 has 3 entries, but the last two don't seem to get used */
3302 headerlen = 1;
3303 recordlen = 0x18;
3304 entries = 1;
3305 pllindex = 0;
3306 break;
3307 case 0x20:
3308 case 0x21:
3309 case 0x30:
3310 headerlen = bios->data[bios->pll_limit_tbl_ptr + 1];
3311 recordlen = bios->data[bios->pll_limit_tbl_ptr + 2];
3312 entries = bios->data[bios->pll_limit_tbl_ptr + 3];
3313 break;
3314 default:
3315 NV_ERROR(pScrn, "PLL limits table revision 0x%X not currently "
3316 "supported\n", pll_lim_ver);
3317 return -ENOSYS;
3318 }
3319
3320 /* initialize all members to zero */
3321 memset(pll_lim, 0, sizeof(struct pll_lims));
3322
3323 if (pll_lim_ver == 0x10 || pll_lim_ver == 0x11) {
3324 uint8_t *pll_rec = &bios->data[bios->pll_limit_tbl_ptr + headerlen + recordlen * pllindex];
3325
3326 pll_lim->vco1.minfreq = ROM32(pll_rec[0]);
3327 pll_lim->vco1.maxfreq = ROM32(pll_rec[4]);
3328 pll_lim->vco2.minfreq = ROM32(pll_rec[8]);
3329 pll_lim->vco2.maxfreq = ROM32(pll_rec[12]);
3330 pll_lim->vco1.min_inputfreq = ROM32(pll_rec[16]);
3331 pll_lim->vco2.min_inputfreq = ROM32(pll_rec[20]);
3332 pll_lim->vco1.max_inputfreq = pll_lim->vco2.max_inputfreq = INT_MAX;
3333
3334 /* these values taken from nv30/31/36 */
3335 pll_lim->vco1.min_n = 0x1;
3336 if (cv == 0x36)
3337 pll_lim->vco1.min_n = 0x5;
3338 pll_lim->vco1.max_n = 0xff;
3339 pll_lim->vco1.min_m = 0x1;
3340 pll_lim->vco1.max_m = 0xd;
3341 pll_lim->vco2.min_n = 0x4;
3342 /* on nv30, 31, 36 (i.e. all cards with two stage PLLs with this
3343 * table version (apart from nv35)), N2 is compared to
3344 * maxN2 (0x46) and 10 * maxM2 (0x4), so set maxN2 to 0x28 and
3345 * save a comparison
3346 */
3347 pll_lim->vco2.max_n = 0x28;
3348 if (cv == 0x30 || cv == 0x35)
3349 /* only 5 bits available for N2 on nv30/35 */
3350 pll_lim->vco2.max_n = 0x1f;
3351 pll_lim->vco2.min_m = 0x1;
3352 pll_lim->vco2.max_m = 0x4;
3353 pll_lim->max_log2p = 0x7;
3354 pll_lim->max_usable_log2p = 0x6;
3355 } else if (pll_lim_ver == 0x20 || pll_lim_ver == 0x21) {
3356 uint16_t plloffs = bios->pll_limit_tbl_ptr + headerlen;
3357 uint32_t reg = 0; /* default match */
3358 uint8_t *pll_rec;
3359 int i;
3360
3361 /* first entry is default match, if nothing better. warn if reg field nonzero */
3362 if (ROM32(bios->data[plloffs]))
3363 NV_WARN(pScrn, "Default PLL limit entry has non-zero "
3364 "register field\n");
3365
3366 if (limit_match > MAX_PLL_TYPES)
3367 /* we've been passed a reg as the match */
3368 reg = limit_match;
3369 else /* limit match is a pll type */
3370 for (i = 1; i < entries && !reg; i++) {
3371 uint32_t cmpreg = ROM32(bios->data[plloffs + recordlen * i]);
3372
3373 if (limit_match == NVPLL &&
3374 (cmpreg == NV_PRAMDAC_NVPLL_COEFF || cmpreg == 0x4000))
3375 reg = cmpreg;
3376 if (limit_match == MPLL &&
3377 (cmpreg == NV_PRAMDAC_MPLL_COEFF || cmpreg == 0x4020))
3378 reg = cmpreg;
3379 if (limit_match == VPLL1 &&
3380 (cmpreg == NV_PRAMDAC_VPLL_COEFF || cmpreg == 0x4010))
3381 reg = cmpreg;
3382 if (limit_match == VPLL2 &&
3383 (cmpreg == NV_RAMDAC_VPLL2 || cmpreg == 0x4018))
3384 reg = cmpreg;
3385 }
3386
3387 for (i = 1; i < entries; i++)
3388 if (ROM32(bios->data[plloffs + recordlen * i]) == reg) {
3389 pllindex = i;
3390 break;
3391 }
3392
3393 pll_rec = &bios->data[plloffs + recordlen * pllindex];
3394
3395 BIOSLOG(pScrn, "Loading PLL limits for reg 0x%08x\n", pllindex ? reg : 0);
3396
3397 /* frequencies are stored in tables in MHz, kHz are more useful, so we convert */
3398
3399 /* What output frequencies can each VCO generate? */
3400 pll_lim->vco1.minfreq = ROM16(pll_rec[4]) * 1000;
3401 pll_lim->vco1.maxfreq = ROM16(pll_rec[6]) * 1000;
3402 pll_lim->vco2.minfreq = ROM16(pll_rec[8]) * 1000;
3403 pll_lim->vco2.maxfreq = ROM16(pll_rec[10]) * 1000;
3404
3405 /* What input frequencies do they accept (past the m-divider)? */
3406 pll_lim->vco1.min_inputfreq = ROM16(pll_rec[12]) * 1000;
3407 pll_lim->vco2.min_inputfreq = ROM16(pll_rec[14]) * 1000;
3408 pll_lim->vco1.max_inputfreq = ROM16(pll_rec[16]) * 1000;
3409 pll_lim->vco2.max_inputfreq = ROM16(pll_rec[18]) * 1000;
3410
3411 /* What values are accepted as multiplier and divider? */
3412 pll_lim->vco1.min_n = pll_rec[20];
3413 pll_lim->vco1.max_n = pll_rec[21];
3414 pll_lim->vco1.min_m = pll_rec[22];
3415 pll_lim->vco1.max_m = pll_rec[23];
3416 pll_lim->vco2.min_n = pll_rec[24];
3417 pll_lim->vco2.max_n = pll_rec[25];
3418 pll_lim->vco2.min_m = pll_rec[26];
3419 pll_lim->vco2.max_m = pll_rec[27];
3420
3421 pll_lim->max_usable_log2p = pll_lim->max_log2p = pll_rec[29];
3422 if (pll_lim->max_log2p > 0x7)
3423 /* pll decoding in nv_hw.c assumes never > 7 */
3424 NV_WARN(pScrn, "Max log2 P value greater than 7 (%d)\n",
3425 pll_lim->max_log2p);
3426 if (cv < 0x60)
3427 pll_lim->max_usable_log2p = 0x6;
3428 pll_lim->log2p_bias = pll_rec[30];
3429
3430 if (recordlen > 0x22)
3431 pll_lim->refclk = ROM32(pll_rec[31]);
3432
3433 if (recordlen > 0x23 && pll_rec[35])
3434 NV_WARN(pScrn,
3435 "Bits set in PLL configuration byte (%x)\n",
3436 pll_rec[35]);
3437
3438 /* C51 special not seen elsewhere */
3439 if (cv == 0x51 && !pll_lim->refclk) {
3440 uint32_t sel_clk = bios_rd32(pScrn, NV_PRAMDAC_SEL_CLK);
3441
3442 if (((limit_match == NV_PRAMDAC_VPLL_COEFF || limit_match == VPLL1) && sel_clk & 0x20) ||
3443 ((limit_match == NV_RAMDAC_VPLL2 || limit_match == VPLL2) && sel_clk & 0x80)) {
3444 if (bios_idxprt_rd(pScrn, NV_CIO_CRX__COLOR, NV_CIO_CRE_CHIP_ID_INDEX) < 0xa3)
3445 pll_lim->refclk = 200000;
3446 else
3447 pll_lim->refclk = 25000;
3448 }
3449 }
3450 } else if (pll_lim_ver) { /* ver 0x30 */
3451 uint8_t *entry = &bios->data[bios->pll_limit_tbl_ptr + headerlen];
3452 uint8_t *record = NULL;
3453 int i;
3454
3455 BIOSLOG(pScrn, "Loading PLL limits for register 0x%08x\n",
3456 limit_match);
3457
3458 for (i = 0; i < entries; i++, entry += recordlen) {
3459 if (ROM32(entry[3]) == limit_match) {
3460 record = &bios->data[ROM16(entry[1])];
3461 break;
3462 }
3463 }
3464
3465 if (!record) {
3466 NV_ERROR(pScrn, "Register 0x%08x not found in PLL "
3467 "limits table", limit_match);
3468 return -ENOENT;
3469 }
3470
3471 pll_lim->vco1.minfreq = ROM16(record[0]) * 1000;
3472 pll_lim->vco1.maxfreq = ROM16(record[2]) * 1000;
3473 pll_lim->vco2.minfreq = ROM16(record[4]) * 1000;
3474 pll_lim->vco2.maxfreq = ROM16(record[6]) * 1000;
3475 pll_lim->vco1.min_inputfreq = ROM16(record[8]) * 1000;
3476 pll_lim->vco2.min_inputfreq = ROM16(record[10]) * 1000;
3477 pll_lim->vco1.max_inputfreq = ROM16(record[12]) * 1000;
3478 pll_lim->vco2.max_inputfreq = ROM16(record[14]) * 1000;
3479 pll_lim->vco1.min_n = record[16];
3480 pll_lim->vco1.max_n = record[17];
3481 pll_lim->vco1.min_m = record[18];
3482 pll_lim->vco1.max_m = record[19];
3483 pll_lim->vco2.min_n = record[20];
3484 pll_lim->vco2.max_n = record[21];
3485 pll_lim->vco2.min_m = record[22];
3486 pll_lim->vco2.max_m = record[23];
3487 pll_lim->max_usable_log2p = pll_lim->max_log2p = record[25];
3488 pll_lim->log2p_bias = record[27];
3489 pll_lim->refclk = ROM32(record[28]);
3490 }
3491
3492 /* By now any valid limit table ought to have set a max frequency for
3493 * vco1, so if it's zero it's either a pre limit table bios, or one
3494 * with an empty limit table (seen on nv18)
3495 */
3496 if (!pll_lim->vco1.maxfreq) {
3497 pll_lim->vco1.minfreq = bios->fminvco;
3498 pll_lim->vco1.maxfreq = bios->fmaxvco;
3499 pll_lim->vco1.min_inputfreq = 0;
3500 pll_lim->vco1.max_inputfreq = INT_MAX;
3501 pll_lim->vco1.min_n = 0x1;
3502 pll_lim->vco1.max_n = 0xff;
3503 pll_lim->vco1.min_m = 0x1;
3504 if (crystal_straps == 0) {
3505 /* nv05 does this, nv11 doesn't, nv10 unknown */
3506 if (cv < 0x11)
3507 pll_lim->vco1.min_m = 0x7;
3508 pll_lim->vco1.max_m = 0xd;
3509 } else {
3510 if (cv < 0x11)
3511 pll_lim->vco1.min_m = 0x8;
3512 pll_lim->vco1.max_m = 0xe;
3513 }
3514 if (cv < 0x17 || cv == 0x1a || cv == 0x20)
3515 pll_lim->max_log2p = 4;
3516 else
3517 pll_lim->max_log2p = 5;
3518 pll_lim->max_usable_log2p = pll_lim->max_log2p;
3519 }
3520
3521 if (!pll_lim->refclk)
3522 switch (crystal_straps) {
3523 case 0:
3524 pll_lim->refclk = 13500;
3525 break;
3526 case (1 << 6):
3527 pll_lim->refclk = 14318;
3528 break;
3529 case (1 << 22):
3530 pll_lim->refclk = 27000;
3531 break;
3532 case (1 << 22 | 1 << 6):
3533 pll_lim->refclk = 25000;
3534 break;
3535 }
3536
3537#if 0 /* for easy debugging */
3538 ErrorF("pll.vco1.minfreq: %d\n", pll_lim->vco1.minfreq);
3539 ErrorF("pll.vco1.maxfreq: %d\n", pll_lim->vco1.maxfreq);
3540 ErrorF("pll.vco2.minfreq: %d\n", pll_lim->vco2.minfreq);
3541 ErrorF("pll.vco2.maxfreq: %d\n", pll_lim->vco2.maxfreq);
3542
3543 ErrorF("pll.vco1.min_inputfreq: %d\n", pll_lim->vco1.min_inputfreq);
3544 ErrorF("pll.vco1.max_inputfreq: %d\n", pll_lim->vco1.max_inputfreq);
3545 ErrorF("pll.vco2.min_inputfreq: %d\n", pll_lim->vco2.min_inputfreq);
3546 ErrorF("pll.vco2.max_inputfreq: %d\n", pll_lim->vco2.max_inputfreq);
3547
3548 ErrorF("pll.vco1.min_n: %d\n", pll_lim->vco1.min_n);
3549 ErrorF("pll.vco1.max_n: %d\n", pll_lim->vco1.max_n);
3550 ErrorF("pll.vco1.min_m: %d\n", pll_lim->vco1.min_m);
3551 ErrorF("pll.vco1.max_m: %d\n", pll_lim->vco1.max_m);
3552 ErrorF("pll.vco2.min_n: %d\n", pll_lim->vco2.min_n);
3553 ErrorF("pll.vco2.max_n: %d\n", pll_lim->vco2.max_n);
3554 ErrorF("pll.vco2.min_m: %d\n", pll_lim->vco2.min_m);
3555 ErrorF("pll.vco2.max_m: %d\n", pll_lim->vco2.max_m);
3556
3557 ErrorF("pll.max_log2p: %d\n", pll_lim->max_log2p);
3558 ErrorF("pll.log2p_bias: %d\n", pll_lim->log2p_bias);
3559
3560 ErrorF("pll.refclk: %d\n", pll_lim->refclk);
3561#endif
3562
3563 return 0;
3564}
3565
3566static void parse_bios_version(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t offset)
3567{
3568 /* offset + 0 (8 bits): Micro version
3569 * offset + 1 (8 bits): Minor version
3570 * offset + 2 (8 bits): Chip version
3571 * offset + 3 (8 bits): Major version
3572 */
3573
3574 bios->major_version = bios->data[offset + 3];
3575 bios->pub.chip_version = bios->data[offset + 2];
3576 NV_TRACE(pScrn, "Bios version %02x.%02x.%02x.%02x\n",
3577 bios->data[offset + 3], bios->data[offset + 2],
3578 bios->data[offset + 1], bios->data[offset]);
3579}
3580
3581static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset)
3582{
3583 /* Parses the init table segment for pointers used in script execution.
3584 *
3585 * offset + 0 (16 bits): init script tables pointer
3586 * offset + 2 (16 bits): macro index table pointer
3587 * offset + 4 (16 bits): macro table pointer
3588 * offset + 6 (16 bits): condition table pointer
3589 * offset + 8 (16 bits): io condition table pointer
3590 * offset + 10 (16 bits): io flag condition table pointer
3591 * offset + 12 (16 bits): init function table pointer
3592 */
3593
3594 bios->init_script_tbls_ptr = ROM16(bios->data[offset]);
3595 bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]);
3596 bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]);
3597 bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]);
3598 bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]);
3599 bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]);
3600 bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]);
3601}
3602
3603static int parse_bit_A_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3604{
3605 /* Parses the load detect values for g80 cards.
3606 *
3607 * offset + 0 (16 bits): loadval table pointer
3608 */
3609
3610 uint16_t load_table_ptr;
3611 uint8_t version, headerlen, entrylen, num_entries;
3612
3613 if (bitentry->length != 3) {
3614 NV_ERROR(pScrn, "Do not understand BIT A table\n");
3615 return -EINVAL;
3616 }
3617
3618 load_table_ptr = ROM16(bios->data[bitentry->offset]);
3619
3620 if (load_table_ptr == 0x0) {
3621 NV_ERROR(pScrn, "Pointer to BIT loadval table invalid\n");
3622 return -EINVAL;
3623 }
3624
3625 version = bios->data[load_table_ptr];
3626
3627 if (version != 0x10) {
3628 NV_ERROR(pScrn, "BIT loadval table version %d.%d not supported\n",
3629 version >> 4, version & 0xF);
3630 return -ENOSYS;
3631 }
3632
3633 headerlen = bios->data[load_table_ptr + 1];
3634 entrylen = bios->data[load_table_ptr + 2];
3635 num_entries = bios->data[load_table_ptr + 3];
3636
3637 if (headerlen != 4 || entrylen != 4 || num_entries != 2) {
3638 NV_ERROR(pScrn, "Do not understand BIT loadval table\n");
3639 return -EINVAL;
3640 }
3641
3642 /* First entry is normal dac, 2nd tv-out perhaps? */
3643 bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
3644
3645 return 0;
3646}
3647
3648static int parse_bit_C_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3649{
3650 /* offset + 8 (16 bits): PLL limits table pointer
3651 *
3652 * There's more in here, but that's unknown.
3653 */
3654
3655 if (bitentry->length < 10) {
3656 NV_ERROR(pScrn, "Do not understand BIT C table\n");
3657 return -EINVAL;
3658 }
3659
3660 bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]);
3661
3662 return 0;
3663}
3664
3665static int parse_bit_display_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3666{
3667 /* Parses the flat panel table segment that the bit entry points to.
3668 * Starting at bitentry->offset:
3669 *
3670 * offset + 0 (16 bits): ??? table pointer - seems to have 18 byte records beginning with a freq
3671 * offset + 2 (16 bits): mode table pointer
3672 */
3673
3674 if (bitentry->length != 4) {
3675 NV_ERROR(pScrn, "Do not understand BIT display table\n");
3676 return -EINVAL;
3677 }
3678
3679 bios->fp.fptablepointer = ROM16(bios->data[bitentry->offset + 2]);
3680
3681 return 0;
3682}
3683
3684static int parse_bit_init_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3685{
3686 /* Parses the init table segment that the bit entry points to.
3687 *
3688 * See parse_script_table_pointers for layout
3689 */
3690
3691 if (bitentry->length < 14) {
3692 NV_ERROR(pScrn, "Do not understand init table\n");
3693 return -EINVAL;
3694 }
3695
3696 parse_script_table_pointers(bios, bitentry->offset);
3697
3698 return 0;
3699}
3700
3701static int parse_bit_i_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3702{
3703 /* BIT 'i' (info?) table
3704 *
3705 * offset + 0 (32 bits): BIOS version dword (as in B table)
3706 * offset + 5 (8 bits): BIOS feature byte (same as for BMP?)
3707 * offset + 13 (16 bits): pointer to table containing DAC load detection comparison values
3708 *
3709 * There's other things in the table, purpose unknown
3710 */
3711
3712 uint16_t daccmpoffset;
3713 uint8_t dacver, dacheaderlen;
3714
3715 if (bitentry->length < 6) {
3716 NV_ERROR(pScrn, "BIT i table too short for needed information\n");
3717 return -EINVAL;
3718 }
3719
3720 parse_bios_version(pScrn, bios, bitentry->offset);
3721
3722 /* bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's
3723 * Quadro identity crisis), other bits possibly as for BMP feature byte
3724 */
3725 bios->feature_byte = bios->data[bitentry->offset + 5];
3726 bios->is_mobile = bios->feature_byte & FEATURE_MOBILE;
3727
3728 if (bitentry->length < 15) {
3729 NV_WARN(pScrn, "BIT i table not long enough for DAC load "
3730 "detection comparison table\n");
3731 return -EINVAL;
3732 }
3733
3734 daccmpoffset = ROM16(bios->data[bitentry->offset + 13]);
3735
3736 /* doesn't exist on g80 */
3737 if (!daccmpoffset)
3738 return 0;
3739
3740 /* The first value in the table, following the header, is the comparison value
3741 * Purpose of subsequent values unknown -- TV load detection?
3742 */
3743
3744 dacver = bios->data[daccmpoffset];
3745 dacheaderlen = bios->data[daccmpoffset + 1];
3746
3747 if (dacver != 0x00 && dacver != 0x10) {
3748 NV_WARN(pScrn, "DAC load detection comparison table version "
3749 "%d.%d not known\n", dacver >> 4, dacver & 0xf);
3750 return -ENOSYS;
3751 }
3752
3753 bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
3754
3755 return 0;
3756}
3757
3758static int parse_bit_lvds_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3759{
3760 /* Parses the LVDS table segment that the bit entry points to.
3761 * Starting at bitentry->offset:
3762 *
3763 * offset + 0 (16 bits): LVDS strap xlate table pointer
3764 */
3765
3766 if (bitentry->length != 2) {
3767 NV_ERROR(pScrn, "Do not understand BIT LVDS table\n");
3768 return -EINVAL;
3769 }
3770
3771 /* no idea if it's still called the LVDS manufacturer table, but the concept's close enough */
3772 bios->fp.lvdsmanufacturerpointer = ROM16(bios->data[bitentry->offset]);
3773
3774 return 0;
3775}
3776
3777static int parse_bit_M_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3778{
3779 /* offset + 2 (8 bits): number of options in an INIT_RAM_RESTRICT_ZM_REG_GROUP opcode option set
3780 * offset + 3 (16 bits): pointer to strap xlate table for RAM restrict option selection
3781 *
3782 * There's a bunch of bits in this table other than the RAM restrict
3783 * stuff that we don't use - their use currently unknown
3784 */
3785
3786 int i;
3787
3788 /* Older bios versions don't have a sufficiently long table for what we want */
3789 if (bitentry->length < 0x5)
3790 return 0;
3791
3792 /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */
3793 for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++)
3794 ;
3795 itbl_entry[i].length_multiplier = bios->data[bitentry->offset + 2] * 4;
3796 init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier;
3797
3798 bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]);
3799
3800 return 0;
3801}
3802
3803static int parse_bit_tmds_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios, bit_entry_t *bitentry)
3804{
3805 /* Parses the pointer to the TMDS table
3806 *
3807 * Starting at bitentry->offset:
3808 *
3809 * offset + 0 (16 bits): TMDS table pointer
3810 *
3811 * The TMDS table is typically found just before the DCB table, with a
3812 * characteristic signature of 0x11,0x13 (1.1 being version, 0x13 being
3813 * length?)
3814 *
3815 * At offsets +7 and +9 are pointers to scripts, which (when not
3816 * stubbed) seem to be called from the main init tables at POST
3817 * Offset +11 has a pointer to a table where the first word is a pxclk
3818 * frequency and the second word a pointer to a script, which should be
3819 * run if the comparison pxclk frequency is less than the pxclk desired.
3820 * This repeats for decreasing comparison frequencies
3821 * Offset +13 has a pointer to a similar table
3822 * The selection of table (and possibly +7/+9 script) is dictated by
3823 * "or" from the DCB.
3824 */
3825
3826 uint16_t tmdstableptr;
3827
3828 if (bitentry->length != 2) {
3829 NV_ERROR(pScrn, "Do not understand BIT TMDS table\n");
3830 return -EINVAL;
3831 }
3832
3833 tmdstableptr = ROM16(bios->data[bitentry->offset]);
3834
3835 if (tmdstableptr == 0x0) {
3836 NV_ERROR(pScrn, "Pointer to TMDS table invalid\n");
3837 return -EINVAL;
3838 }
3839
3840 /* nv50+ has v2.0, but we don't parse it atm */
3841 if (bios->data[tmdstableptr] != 0x11) {
3842 NV_WARN(pScrn,
3843 "TMDS table revision %d.%d not currently supported\n",
3844 bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf);
3845 return -ENOSYS;
3846 }
3847
3848 bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]);
3849 bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]);
3850
3851 return 0;
3852}
3853
3854static int
3855parse_bit_U_tbl_entry(ScrnInfoPtr pScrn, struct nvbios *bios,
3856 bit_entry_t *bitentry)
3857{
3858 /* Parses the pointer to the G80 output script tables
3859 *
3860 * Starting at bitentry->offset:
3861 *
3862 * offset + 0 (16 bits): output script table pointer
3863 */
3864
3865 uint16_t outputscripttableptr;
3866
3867 if (bitentry->length != 3) {
3868 NV_ERROR(pScrn, "Do not understand BIT U table\n");
3869 return -EINVAL;
3870 }
3871
3872 outputscripttableptr = ROM16(bios->data[bitentry->offset]);
3873 bios->display.script_table_ptr = outputscripttableptr;
3874 return 0;
3875}
3876
3877struct bit_table {
3878 const char id;
3879 int (* const parse_fn)(ScrnInfoPtr, struct nvbios *, bit_entry_t *);
3880};
3881
3882#define BIT_TABLE(id, funcid) ((struct bit_table){ id, parse_bit_##funcid##_tbl_entry })
3883
3884static int parse_bit_table(ScrnInfoPtr pScrn, struct nvbios *bios, const uint16_t bitoffset, struct bit_table *table)
3885{
3886 uint8_t maxentries = bios->data[bitoffset + 4];
3887 int i, offset;
3888 bit_entry_t bitentry;
3889
3890 for (i = 0, offset = bitoffset + 6; i < maxentries; i++, offset += 6) {
3891 bitentry.id[0] = bios->data[offset];
3892
3893 if (bitentry.id[0] != table->id)
3894 continue;
3895
3896 bitentry.id[1] = bios->data[offset + 1];
3897 bitentry.length = ROM16(bios->data[offset + 2]);
3898 bitentry.offset = ROM16(bios->data[offset + 4]);
3899
3900 return table->parse_fn(pScrn, bios, &bitentry);
3901 }
3902
3903 NV_ERROR(pScrn, "BIT table '%c' not found\n", table->id);
3904
3905 return -ENOSYS;
3906}
3907
3908static int parse_bit_structure(ScrnInfoPtr pScrn, struct nvbios *bios, const uint16_t bitoffset)
3909{
3910 int ret;
3911
3912 /* the only restriction on parsing order currently is having 'i' first
3913 * for use of bios->*_version or bios->feature_byte while parsing;
3914 * functions shouldn't be actually *doing* anything apart from pulling
3915 * data from the image into the bios struct, thus no interdependencies
3916 */
3917 if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('i', i)))) /* info? */
3918 return ret;
3919 if (bios->major_version >= 0x60) /* g80+ */
3920 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('A', A));
3921 if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('C', C))))
3922 return ret;
3923 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('D', display));
3924 if ((ret = parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('I', init))))
3925 return ret;
3926 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('M', M)); /* memory? */
3927 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('L', lvds));
3928 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('T', tmds));
3929 parse_bit_table(pScrn, bios, bitoffset, &BIT_TABLE('U', U));
3930
3931 return 0;
3932}
3933
3934static int parse_bmp_structure(ScrnInfoPtr pScrn, struct nvbios *bios, unsigned int offset)
3935{
3936 /* Parses the BMP structure for useful things, but does not act on them
3937 *
3938 * offset + 5: BMP major version
3939 * offset + 6: BMP minor version
3940 * offset + 9: BMP feature byte
3941 * offset + 10: BCD encoded BIOS version
3942 *
3943 * offset + 18: init script table pointer (for bios versions < 5.10h)
3944 * offset + 20: extra init script table pointer (for bios versions < 5.10h)
3945 *
3946 * offset + 24: memory init table pointer (used on early bios versions)
3947 * offset + 26: SDR memory sequencing setup data table
3948 * offset + 28: DDR memory sequencing setup data table
3949 *
3950 * offset + 54: index of I2C CRTC pair to use for CRT output
3951 * offset + 55: index of I2C CRTC pair to use for TV output
3952 * offset + 56: index of I2C CRTC pair to use for flat panel output
3953 * offset + 58: write CRTC index for I2C pair 0
3954 * offset + 59: read CRTC index for I2C pair 0
3955 * offset + 60: write CRTC index for I2C pair 1
3956 * offset + 61: read CRTC index for I2C pair 1
3957 *
3958 * offset + 67: maximum internal PLL frequency (single stage PLL)
3959 * offset + 71: minimum internal PLL frequency (single stage PLL)
3960 *
3961 * offset + 75: script table pointers, as described in parse_script_table_pointers
3962 *
3963 * offset + 89: TMDS single link output A table pointer
3964 * offset + 91: TMDS single link output B table pointer
3965 * offset + 95: LVDS single link output A table pointer
3966 * offset + 105: flat panel timings table pointer
3967 * offset + 107: flat panel strapping translation table pointer
3968 * offset + 117: LVDS manufacturer panel config table pointer
3969 * offset + 119: LVDS manufacturer strapping translation table pointer
3970 *
3971 * offset + 142: PLL limits table pointer
3972 *
3973 * offset + 156: minimum pixel clock for LVDS dual link
3974 */
3975
3976 uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor;
3977 uint16_t bmplength;
3978 uint16_t legacy_scripts_offset, legacy_i2c_offset;
3979
3980 /* load needed defaults in case we can't parse this info */
3981 bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
3982 bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
3983 bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
3984 bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
3985 bios->pub.digital_min_front_porch = 0x4b;
3986 bios->fmaxvco = 256000;
3987 bios->fminvco = 128000;
3988 bios->fp.duallink_transition_clk = 90000;
3989
3990 bmp_version_major = bmp[5];
3991 bmp_version_minor = bmp[6];
3992
3993 NV_TRACE(pScrn, "BMP version %d.%d\n",
3994 bmp_version_major, bmp_version_minor);
3995
3996 /* Make sure that 0x36 is blank and can't be mistaken for a DCB pointer on early versions */
3997 if (bmp_version_major < 5)
3998 *(uint16_t *)&bios->data[0x36] = 0;
3999
4000 /* Seems that the minor version was 1 for all major versions prior to 5 */
4001 /* Version 6 could theoretically exist, but I suspect BIT happened instead */
4002 if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) {
4003 NV_ERROR(pScrn, "You have an unsupported BMP version. "
4004 "Please send in your bios\n");
4005 return -ENOSYS;
4006 }
4007
4008 if (bmp_version_major == 0) /* nothing that's currently useful in this version */
4009 return 0;
4010 else if (bmp_version_major == 1)
4011 bmplength = 44; /* exact for 1.01 */
4012 else if (bmp_version_major == 2)
4013 bmplength = 48; /* exact for 2.01 */
4014 else if (bmp_version_major == 3)
4015 bmplength = 54; /* guessed - mem init tables added in this version */
4016 else if (bmp_version_major == 4 || bmp_version_minor < 0x1) /* don't know if 5.0 exists... */
4017 bmplength = 62; /* guessed - BMP I2C indices added in version 4*/
4018 else if (bmp_version_minor < 0x6)
4019 bmplength = 67; /* exact for 5.01 */
4020 else if (bmp_version_minor < 0x10)
4021 bmplength = 75; /* exact for 5.06 */
4022 else if (bmp_version_minor == 0x10)
4023 bmplength = 89; /* exact for 5.10h */
4024 else if (bmp_version_minor < 0x14)
4025 bmplength = 118; /* exact for 5.11h */
4026 else if (bmp_version_minor < 0x24) /* not sure of version where pll limits came in;
4027 * certainly exist by 0x24 though */
4028 /* length not exact: this is long enough to get lvds members */
4029 bmplength = 123;
4030 else if (bmp_version_minor < 0x27)
4031 /* length not exact: this is long enough to get pll limit member */
4032 bmplength = 144;
4033 else
4034 /* length not exact: this is long enough to get dual link transition clock */
4035 bmplength = 158;
4036
4037 /* checksum */
4038 if (nv_cksum(bmp, 8)) {
4039 NV_ERROR(pScrn, "Bad BMP checksum\n");
4040 return -EINVAL;
4041 }
4042
4043 /* bit 4 seems to indicate either a mobile bios or a quadro card --
4044 * mobile behaviour consistent (nv11+), quadro only seen nv18gl-nv36gl
4045 * (not nv10gl), bit 5 that the flat panel tables are present, and
4046 * bit 6 a tv bios */
4047 bios->feature_byte = bmp[9];
4048
4049 parse_bios_version(pScrn, bios, offset + 10);
4050
4051 if (bmp_version_major < 5 || bmp_version_minor < 0x10)
4052 bios->old_style_init = true;
4053 legacy_scripts_offset = 18;
4054 if (bmp_version_major < 2)
4055 legacy_scripts_offset -= 4;
4056 bios->init_script_tbls_ptr = ROM16(bmp[legacy_scripts_offset]);
4057 bios->extra_init_script_tbl_ptr = ROM16(bmp[legacy_scripts_offset + 2]);
4058
4059 if (bmp_version_major > 2) { /* appears in BMP 3 */
4060 bios->legacy.mem_init_tbl_ptr = ROM16(bmp[24]);
4061 bios->legacy.sdr_seq_tbl_ptr = ROM16(bmp[26]);
4062 bios->legacy.ddr_seq_tbl_ptr = ROM16(bmp[28]);
4063 }
4064
4065 legacy_i2c_offset = 0x48; /* BMP version 2 & 3 */
4066 if (bmplength > 61)
4067 legacy_i2c_offset = offset + 54;
4068 bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
4069 bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
4070 bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
4071 /* don't overwrite defaults with zero (mac braindamage) */
4072 if (bios->data[legacy_i2c_offset + 4])
4073 bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
4074 if (bios->data[legacy_i2c_offset + 5])
4075 bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
4076 if (bios->data[legacy_i2c_offset + 6])
4077 bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
4078 if (bios->data[legacy_i2c_offset + 7])
4079 bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
4080
4081 if (bmplength > 74) {
4082 bios->fmaxvco = ROM32(bmp[67]);
4083 bios->fminvco = ROM32(bmp[71]);
4084 }
4085 if (bmplength > 88)
4086 parse_script_table_pointers(bios, offset + 75);
4087 if (bmplength > 94) {
4088 bios->tmds.output0_script_ptr = ROM16(bmp[89]);
4089 bios->tmds.output1_script_ptr = ROM16(bmp[91]);
4090 /* never observed in use with lvds scripts, but is reused for
4091 * 18/24 bit panel interface default for EDID equipped panels
4092 * (if_is_24bit not set directly to avoid any oscillation) */
4093 bios->legacy.lvds_single_a_script_ptr = ROM16(bmp[95]);
4094 }
4095 if (bmplength > 108) {
4096 bios->fp.fptablepointer = ROM16(bmp[105]);
4097 bios->fp.fpxlatetableptr = ROM16(bmp[107]);
4098 bios->fp.xlatwidth = 1;
4099 }
4100 if (bmplength > 120) {
4101 bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]);
4102 bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]);
4103 }
4104 if (bmplength > 143)
4105 bios->pll_limit_tbl_ptr = ROM16(bmp[142]);
4106
4107 if (bmplength > 157)
4108 bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10;
4109
4110 return 0;
4111}
4112
4113static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
4114{
4115 int i, j;
4116
4117 for (i = 0; i <= (n - len); i++) {
4118 for (j = 0; j < len; j++)
4119 if (data[i + j] != str[j])
4120 break;
4121 if (j == len)
4122 return i;
4123 }
4124
4125 return 0;
4126}
4127
4128static int
4129read_dcb_i2c_entry(ScrnInfoPtr pScrn, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
4130{
4131 uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
4132 int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
4133 int recordoffset = 0, rdofs = 1, wrofs = 0;
4134 uint8_t port_type = 0;
4135
4136 if (!i2ctable)
4137 return -EINVAL;
4138
4139 if (dcb_version >= 0x30) {
4140 if (i2ctable[0] != dcb_version) /* necessary? */
4141 NV_WARN(pScrn,
4142 "DCB I2C table version mismatch (%02X vs %02X)\n",
4143 i2ctable[0], dcb_version);
4144 dcb_i2c_ver = i2ctable[0];
4145 headerlen = i2ctable[1];
4146 if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
4147 i2c_entries = i2ctable[2];
4148 else
4149 NV_WARN(pScrn,
4150 "DCB I2C table has more entries than indexable "
4151 "(%d entries, max index 15)\n", i2ctable[2]);
4152 entry_len = i2ctable[3];
4153 /* [4] is i2c_default_indices, read in parse_dcb_table() */
4154 }
4155 /* it's your own fault if you call this function on a DCB 1.1 BIOS --
4156 * the test below is for DCB 1.2
4157 */
4158 if (dcb_version < 0x14) {
4159 recordoffset = 2;
4160 rdofs = 0;
4161 wrofs = 1;
4162 }
4163
4164 if (index == 0xf)
4165 return 0;
4166 if (index > i2c_entries) {
4167 NV_ERROR(pScrn, "DCB I2C index too big (%d > %d)\n",
4168 index, i2ctable[2]);
4169 return -ENOENT;
4170 }
4171 if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
4172 NV_ERROR(pScrn, "DCB I2C entry invalid\n");
4173 return -EINVAL;
4174 }
4175
4176 if (dcb_i2c_ver >= 0x30) {
4177 port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];
4178
4179 /* fixup for chips using same address offset for read and write */
4180 if (port_type == 4) /* seen on C51 */
4181 rdofs = wrofs = 1;
4182 if (port_type == 5) /* G80+ */
4183 rdofs = wrofs = 0;
4184 }
4185 if (dcb_i2c_ver >= 0x40 && port_type != 5)
4186 NV_WARN(pScrn, "DCB I2C table has port type %d\n", port_type);
4187
4188 i2c->port_type = port_type;
4189 i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
4190 i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];
4191
4192 return 0;
4193}
4194
4195static int init_dcb_i2c_entry(ScrnInfoPtr pScrn, struct nvbios *bios, int index)
4196{
4197 struct dcb_i2c_entry *i2c = &bios->bdcb.dcb.i2c[index];
4198 int ret;
4199 char adaptorname[11];
4200
4201 if (i2c->chan)
4202 return 0;
4203
4204 if (bios->bdcb.version < 0x15) {
4205 NV_ERROR(pScrn, "DCB table not version 1.5 or greater\n");
4206 return -ENOSYS;
4207 }
4208 if (!bios->bdcb.i2c_table) {
4209 NV_ERROR(pScrn, "No parsed DCB I2C port table\n");
4210 return -EINVAL;
4211 }
4212
4213 if ((ret = read_dcb_i2c_entry(pScrn, bios->bdcb.version, bios->bdcb.i2c_table, index, i2c)))
4214 return ret;
4215
4216 snprintf(adaptorname, 11, "DCB-I2C-%d", index);
4217
4218 return NV_I2CInit(pScrn, &i2c->chan, i2c, xstrdup(adaptorname));
4219}
4220
4221static struct dcb_entry * new_dcb_entry(struct parsed_dcb *dcb)
4222{
4223 struct dcb_entry *entry = &dcb->entry[dcb->entries];
4224
4225 memset(entry, 0, sizeof (struct dcb_entry));
4226 entry->index = dcb->entries++;
4227
4228 return entry;
4229}
4230
4231static void
4232fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads, int or)
4233{
4234 struct dcb_entry *entry = new_dcb_entry(dcb);
4235
4236 entry->type = 0;
4237 entry->i2c_index = i2c;
4238 entry->heads = heads;
4239 entry->location = DCB_LOC_ON_CHIP;
4240 /* setting "or" to 0 for early gen crt modesetting is fine (unused) */
4241 entry->or = or;
4242}
4243
4244static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
4245{
4246 struct dcb_entry *entry = new_dcb_entry(dcb);
4247
4248 entry->type = 2;
4249 entry->i2c_index = LEGACY_I2C_PANEL;
4250 entry->heads = twoHeads ? 3 : 1;
4251 entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */
4252 entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */
4253 entry->duallink_possible = false; /* SiI164 and co. are single link */
4254
4255#if 0
4256 /* for dvi-a either crtc probably works, but my card appears to only
4257 * support dvi-d. "nvidia" still attempts to program it for dvi-a,
4258 * doing the full fp output setup (program 0x6808.. fp dimension regs,
4259 * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880);
4260 * the monitor picks up the mode res ok and lights up, but no pixel
4261 * data appears, so the board manufacturer probably connected up the
4262 * sync lines, but missed the video traces / components
4263 *
4264 * with this introduction, dvi-a left as an exercise for the reader.
4265 */
4266 fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads, 0);
4267#endif
4268}
4269
4270static bool
4271parse_dcb20_entry(ScrnInfoPtr pScrn, struct bios_parsed_dcb *bdcb,
4272 uint32_t conn, uint32_t conf, struct dcb_entry *entry)
4273{
4274 entry->type = conn & 0xf;
4275 entry->i2c_index = (conn >> 4) & 0xf;
4276 entry->heads = (conn >> 8) & 0xf;
4277 entry->bus = (conn >> 16) & 0xf;
4278 entry->location = (conn >> 20) & 0x3;
4279 entry->or = (conn >> 24) & 0xf;
4280 /* Normal entries consist of a single bit, but dual link has the
4281 * next most significant bit set too
4282 */
4283 entry->duallink_possible =
4284 ((1 << (ffs(entry->or) - 1)) * 3 == entry->or);
4285
4286 switch (entry->type) {
4287 case OUTPUT_ANALOG:
4288 /* although the rest of a CRT conf dword is usually
4289 * zeros, mac biosen have stuff there so we must mask
4290 */
4291 entry->crtconf.maxfreq = (bdcb->version < 0x30) ?
4292 (conf & 0xffff) * 10 :
4293 (conf & 0xff) * 10000;
4294 break;
4295 case OUTPUT_LVDS:
4296 {
4297 uint32_t mask;
4298 if (conf & 0x1)
4299 entry->lvdsconf.use_straps_for_mode = true;
4300 if (bdcb->version < 0x22) {
4301 mask = ~0xd;
4302 /* the laptop in bug 14567 lies and claims to not use
4303 * straps when it does, so assume all DCB 2.0 laptops
4304 * use straps, until a broken EDID using one is produced
4305 */
4306 entry->lvdsconf.use_straps_for_mode = true;
4307 /* both 0x4 and 0x8 show up in v2.0 tables; assume they
4308 * mean the same thing (probably wrong, but might work)
4309 */
4310 if (conf & 0x4 || conf & 0x8)
4311 entry->lvdsconf.use_power_scripts = true;
4312 } else {
4313 mask = ~0x5;
4314 if (conf & 0x4)
4315 entry->lvdsconf.use_power_scripts = true;
4316 }
4317 if (conf & mask) {
4318 /* I'm bored of getting this reported; left as a reminder for someone to fix it */
4319 if (bdcb->version >= 0x40) {
4320 NV_WARN(pScrn, "G80+ LVDS not initialized by driver; ignoring conf bits\n");
4321 break;
4322 }
4323 NV_ERROR(pScrn, "Unknown LVDS configuration bits, "
4324 "please report\n");
4325 /* cause output setting to fail, so message is seen */
4326 bdcb->dcb.entries = 0;
4327 return false;
4328 }
4329 break;
4330 }
4331 case 0xe:
4332 /* weird g80 mobile type that "nv" treats as a terminator */
4333 bdcb->dcb.entries--;
4334 return false;
4335 }
4336 /* unsure what DCB version introduces this, 3.0? */
4337 if (conf & 0x100000)
4338 entry->i2c_upper_default = true;
4339
4340 return true;
4341}
4342
4343static bool
4344parse_dcb15_entry(ScrnInfoPtr pScrn, struct parsed_dcb *dcb,
4345 uint32_t conn, uint32_t conf, struct dcb_entry *entry)
4346{
4347 if (conn != 0xf0003f00 && conn != 0xf2247f10 &&
4348 conn != 0xf2204001 && conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 && conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 && conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
4349 conn != 0xf2045ff2 &&
4350 conn != 0xf2045f14 && conn != 0xf207df14 && conn != 0xf2205004) {
4351 NV_ERROR(pScrn, "Unknown DCB 1.5 entry, please report\n");
4352
4353 /* cause output setting to fail for !TV, so message is seen */
4354 if ((conn & 0xf) != 0x1)
4355 dcb->entries = 0;
4356
4357 return false;
4358 }
4359 /* most of the below is a "best guess" atm */
4360 entry->type = conn & 0xf;
4361 if (entry->type == 2)
4362 /* another way of specifying straps based lvds... */
4363 entry->type = OUTPUT_LVDS;
4364 if (entry->type == 4) { /* digital */
4365 if (conn & 0x10)
4366 entry->type = OUTPUT_LVDS;
4367 else
4368 entry->type = OUTPUT_TMDS;
4369 }
4370 /* what's in bits 5-13? could be some encoder maker thing, in tv case */
4371 entry->i2c_index = (conn >> 14) & 0xf;
4372 /* raw heads field is in range 0-1, so move to 1-2 */
4373 entry->heads = ((conn >> 18) & 0x7) + 1;
4374 entry->location = (conn >> 21) & 0xf;
4375 /* unused: entry->bus = (conn >> 25) & 0x7; */
4376 /* set or to be same as heads -- hopefully safe enough */
4377 entry->or = entry->heads;
4378 entry->duallink_possible = false;
4379
4380 switch (entry->type) {
4381 case OUTPUT_ANALOG:
4382 entry->crtconf.maxfreq = (conf & 0xffff) * 10;
4383 break;
4384 case OUTPUT_LVDS:
4385 /* this is probably buried in conn's unknown bits */
4386 /* this will upset EDID-ful models, if they exist */
4387 entry->lvdsconf.use_straps_for_mode = true;
4388 entry->lvdsconf.use_power_scripts = true;
4389 break;
4390 case OUTPUT_TMDS:
4391 /* invent a DVI-A output, by copying the fields of the DVI-D
4392 * output; reported to work by math_b on an NV20(!) */
4393 fabricate_vga_output(dcb, entry->i2c_index, entry->heads, 0);
4394 }
4395
4396 return true;
4397}
4398
4399static bool parse_dcb_entry(ScrnInfoPtr pScrn, struct bios_parsed_dcb *bdcb,
4400 uint32_t conn, uint32_t conf)
4401{
4402 struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb);
4403 bool ret;
4404
4405 if (bdcb->version >= 0x20)
4406 ret = parse_dcb20_entry(pScrn, bdcb, conn, conf, entry);
4407 else
4408 ret = parse_dcb15_entry(pScrn, &bdcb->dcb, conn, conf, entry);
4409 if (!ret)
4410 return ret;
4411
4412 read_dcb_i2c_entry(pScrn, bdcb->version, bdcb->i2c_table,
4413 entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]);
4414
4415 return true;
4416}
4417
4418void merge_like_dcb_entries(ScrnInfoPtr pScrn, struct parsed_dcb *dcb)
4419{
4420 /* DCB v2.0 lists each output combination separately.
4421 * Here we merge compatible entries to have fewer outputs, with more options
4422 */
4423
4424 int i, newentries = 0;
4425
4426 for (i = 0; i < dcb->entries; i++) {
4427 struct dcb_entry *ient = &dcb->entry[i];
4428 int j;
4429
4430 for (j = i + 1; j < dcb->entries; j++) {
4431 struct dcb_entry *jent = &dcb->entry[j];
4432
4433 if (jent->type == 100) /* already merged entry */
4434 continue;
4435
4436 /* merge heads field when all other fields the same */
4437 if (jent->i2c_index == ient->i2c_index &&
4438 jent->type == ient->type &&
4439 jent->location == ient->location &&
4440 jent->or == ient->or) {
4441 NV_TRACE(pScrn, "Merging DCB entries %d and %d\n",
4442 i, j);
4443 ient->heads |= jent->heads;
4444 jent->type = 100; /* dummy value */
4445 }
4446 }
4447 }
4448
4449 /* Compact entries merged into others out of dcb */
4450 for (i = 0; i < dcb->entries; i++) {
4451 if (dcb->entry[i].type == 100)
4452 continue;
4453
4454 if (newentries != i) {
4455 dcb->entry[newentries] = dcb->entry[i];
4456 dcb->entry[newentries].index = newentries;
4457 }
4458 newentries++;
4459 }
4460
4461 dcb->entries = newentries;
4462}
4463
4464static int parse_dcb_table(ScrnInfoPtr pScrn, struct nvbios *bios, bool twoHeads)
4465{
4466 struct bios_parsed_dcb *bdcb = &bios->bdcb;
4467 struct parsed_dcb *dcb;
4468 uint16_t dcbptr, i2ctabptr = 0;
4469 uint8_t *dcbtable;
4470 uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
4471 bool configblock = true;
4472 int recordlength = 8, confofs = 4;
4473 int i;
4474
4475 dcb = bios->pub.dcb = &bdcb->dcb;
4476 dcb->entries = 0;
4477
4478 /* get the offset from 0x36 */
4479 dcbptr = ROM16(bios->data[0x36]);
4480
4481 if (dcbptr == 0x0) {
4482#ifdef __powerpc__
4483 if ((NVPTR(pScrn)->Chipset & 0xffff) == 0x0172) {
4484 /* retarded PowerMac G4 has DVI and ADC (#21273) */
4485 NV_WARN(pScrn, "Working around missing output tables\n");
4486 /* this is the dvi-a */
4487 fabricate_vga_output(dcb, LEGACY_I2C_PANEL, 0x3, 2);
4488 return 0;
4489 }
4490#endif
4491 NV_WARN(pScrn, "No output data (DCB) found in BIOS, "
4492 "assuming a CRT output exists\n");
4493 /* this situation likely means a really old card, pre DCB */
4494 fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1, 0);
4495 return 0;
4496 }
4497
4498 dcbtable = &bios->data[dcbptr];
4499
4500 /* get DCB version */
4501 bdcb->version = dcbtable[0];
4502 NV_TRACE(pScrn, "Found Display Configuration Block version %d.%d\n",
4503 bdcb->version >> 4, bdcb->version & 0xf);
4504
4505 if (bdcb->version >= 0x20) { /* NV17+ */
4506 uint32_t sig;
4507
4508 if (bdcb->version >= 0x30) { /* NV40+ */
4509 headerlen = dcbtable[1];
4510 entries = dcbtable[2];
4511 recordlength = dcbtable[3];
4512 i2ctabptr = ROM16(dcbtable[4]);
4513 sig = ROM32(dcbtable[6]);
4514 if (bdcb->version == 0x40) /* G80 */
4515 bdcb->init8e_table_ptr =
4516 ROM16(dcbtable[10]);
4517 } else {
4518 i2ctabptr = ROM16(dcbtable[2]);
4519 sig = ROM32(dcbtable[4]);
4520 headerlen = 8;
4521 }
4522
4523 if (sig != 0x4edcbdcb) {
4524 NV_ERROR(pScrn, "Bad Display Configuration Block "
4525 "signature (%08X)\n", sig);
4526 return -EINVAL;
4527 }
4528 } else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */
4529 char sig[8] = { 0 };
4530
4531 strncpy(sig, (char *)&dcbtable[-7], 7);
4532 i2ctabptr = ROM16(dcbtable[2]);
4533 recordlength = 10;
4534 confofs = 6;
4535
4536 if (strcmp(sig, "DEV_REC")) {
4537 NV_ERROR(pScrn, "Bad Display Configuration Block "
4538 "signature (%s)\n", sig);
4539 return -EINVAL;
4540 }
4541 } else {
4542 /* v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always
4543 * has the same single (crt) entry, even when tv-out present, so
4544 * the conclusion is this version cannot really be used.
4545 * v1.2 tables (some NV6/10, and NV15+) normally have the same
4546 * 5 entries, which are not specific to the card and so no use.
4547 * v1.2 does have an I2C table that read_dcb_i2c_table can
4548 * handle, but cards exist (nv11 in #14821) with a bad i2c table
4549 * pointer, so use the indices parsed in parse_bmp_structure.
4550 * v1.1 (NV5+, maybe some NV4) is entirely unhelpful
4551 */
4552 NV_TRACEWARN(pScrn, "No useful information in BIOS output table; "
4553 "adding all possible outputs\n");
4554 fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1, 0);
4555 if (bios->tmds.output0_script_ptr ||
4556 bios->tmds.output1_script_ptr)
4557 fabricate_dvi_i_output(dcb, twoHeads);
4558 return 0;
4559 }
4560
4561 if (!i2ctabptr)
4562 NV_WARN(pScrn, "No pointer to DCB I2C port table\n");
4563 else {
4564 bdcb->i2c_table = &bios->data[i2ctabptr];
4565 if (bdcb->version >= 0x30)
4566 bdcb->i2c_default_indices = bdcb->i2c_table[4];
4567 }
4568
4569 if (entries > DCB_MAX_NUM_ENTRIES)
4570 entries = DCB_MAX_NUM_ENTRIES;
4571
4572 for (i = 0; i < entries; i++) {
4573 uint32_t connection, config = 0;
4574
4575 connection = ROM32(dcbtable[headerlen + recordlength * i]);
4576 if (configblock)
4577 config = ROM32(dcbtable[headerlen + confofs + recordlength * i]);
4578
4579 /* Should we allow discontinuous DCBs? Certainly DCB I2C tables can be discontinuous */
4580 if ((connection & 0x0000000f) == 0x0000000f) /* end of records */
4581 break;
4582 if (connection == 0x00000000) /* seen on an NV11 with DCB v1.5 */
4583 break;
4584
4585 NV_TRACEWARN(pScrn, "Raw DCB entry %d: %08x %08x\n",
4586 dcb->entries, connection, config);
4587
4588 if (!parse_dcb_entry(pScrn, bdcb, connection, config))
4589 break;
4590 }
4591
4592 /* apart for v2.1+ not being known for requiring merging, this
4593 * guarantees dcbent->index is the index of the entry in the rom image
4594 */
4595 if (bdcb->version < 0x21)
4596 merge_like_dcb_entries(pScrn, dcb);
4597
4598 return (dcb->entries ? 0 : -ENXIO);
4599}
4600
4601static void fixup_legacy_i2c(struct nvbios *bios)
4602{
4603 struct parsed_dcb *dcb = &bios->bdcb.dcb;
4604 int i;
4605
4606 for (i = 0; i < dcb->entries; i++) {
4607 if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT)
4608 dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt;
4609 if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL)
4610 dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel;
4611 }
4612}
4613
4614static int load_nv17_hwsq_ucode_entry(ScrnInfoPtr pScrn, struct nvbios *bios, uint16_t hwsq_offset, int entry)
4615{
4616 /* The header following the "HWSQ" signature has the number of entries,
4617 * and the entry size
4618 *
4619 * An entry consists of a dword to write to the sequencer control reg
4620 * (0x00001304), followed by the ucode bytes, written sequentially,
4621 * starting at reg 0x00001400
4622 */
4623
4624 uint8_t bytes_to_write;
4625 uint16_t hwsq_entry_offset;
4626 int i;
4627
4628 if (bios->data[hwsq_offset] <= entry) {
4629 NV_ERROR(pScrn, "Too few entries in HW sequencer table for "
4630 "requested entry\n");
4631 return -ENOENT;
4632 }
4633
4634 bytes_to_write = bios->data[hwsq_offset + 1];
4635
4636 if (bytes_to_write != 36) {
4637 NV_ERROR(pScrn, "Unknown HW sequencer entry size\n");
4638 return -EINVAL;
4639 }
4640
4641 NV_TRACE(pScrn, "Loading NV17 power sequencing microcode\n");
4642
4643 hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write;
4644
4645 /* set sequencer control */
4646 bios_wr32(pScrn, 0x00001304, ROM32(bios->data[hwsq_entry_offset]));
4647 bytes_to_write -= 4;
4648
4649 /* write ucode */
4650 for (i = 0; i < bytes_to_write; i += 4)
4651 bios_wr32(pScrn, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4]));
4652
4653 /* twiddle NV_PBUS_DEBUG_4 */
4654 bios_wr32(pScrn, NV_PBUS_DEBUG_4, bios_rd32(pScrn, NV_PBUS_DEBUG_4) | 0x18);
4655
4656 return 0;
4657}
4658
4659static int load_nv17_hw_sequencer_ucode(ScrnInfoPtr pScrn, struct nvbios *bios)
4660{
4661 /* BMP based cards, from NV17, need a microcode loading to correctly
4662 * control the GPIO etc for LVDS panels
4663 *
4664 * BIT based cards seem to do this directly in the init scripts
4665 *
4666 * The microcode entries are found by the "HWSQ" signature.
4667 */
4668
4669 const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' };
4670 int hwsq_offset;
4671
4672 if (!(hwsq_offset = findstr(bios->data, bios->length, hwsq_signature,
4673 sizeof(hwsq_signature))))
4674 return 0;
4675
4676 /* always use entry 0? */
4677 return load_nv17_hwsq_ucode_entry(pScrn, bios,
4678 hwsq_offset + sizeof(hwsq_signature), 0);
4679}
4680
4681uint8_t * nouveau_bios_embedded_edid(ScrnInfoPtr pScrn)
4682{
4683 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
4684 const uint8_t edid_sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
4685 uint16_t offset = 0, newoffset;
4686 int searchlen = NV_PROM_SIZE;
4687
4688 if (bios->fp.edid)
4689 return bios->fp.edid;
4690
4691 while (searchlen) {
4692 if (!(newoffset = findstr(&bios->data[offset], searchlen, edid_sig, 8)))
4693 return NULL;
4694 offset += newoffset;
4695 if (!nv_cksum(&bios->data[offset], EDID1_LEN))
4696 break;
4697
4698 searchlen -= offset;
4699 offset++;
4700 }
4701
4702 NV_TRACE(pScrn, "Found EDID in BIOS\n");
4703
4704 return (bios->fp.edid = &bios->data[offset]);
4705}
4706
4707bool NVInitVBIOS(ScrnInfoPtr pScrn)
4708{
4709 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
4710
4711 memset(bios, 0, sizeof(struct nvbios));
4712
4713 if (!NVShadowVBIOS(pScrn, bios->data))
4714 return false;
4715
4716 bios->length = bios->data[2] * 512;
4717 if (bios->length > NV_PROM_SIZE)
4718 bios->length = NV_PROM_SIZE;
4719
4720 return true;
4721}
4722
4723int nouveau_parse_vbios_struct(ScrnInfoPtr pScrn)
4724{
4725 struct nvbios *bios = &NVPTR(pScrn)->VBIOS;
4726 const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
4727 const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
4728 int offset;
4729
4730 if ((offset = findstr(bios->data, bios->length, bit_signature, sizeof(bit_signature)))) {
4731 NV_TRACE(pScrn, "BIT BIOS found\n");
4732 return parse_bit_structure(pScrn, bios, offset + 6);
4733 }
4734 if ((offset = findstr(bios->data, bios->length, bmp_signature, sizeof(bmp_signature)))) {
4735 NV_TRACE(pScrn, "BMP BIOS found\n");
4736 return parse_bmp_structure(pScrn, bios, offset);
4737 }
4738
4739 NV_ERROR(pScrn, "No known BIOS signature found\n");
4740
4741 return -ENODEV;
4742}
4743
4744int nouveau_run_vbios_init(ScrnInfoPtr pScrn)
4745{
4746 NVPtr pNv = NVPTR(pScrn);
4747 struct nvbios *bios = &pNv->VBIOS;
4748 int ret = 0;
4749
4750 NVLockVgaCrtcs(pNv, false);
4751 if (pNv->twoHeads)
4752 NVSetOwner(pNv, crtchead);
4753
4754 if (bios->major_version < 5) /* BMP only */
4755 load_nv17_hw_sequencer_ucode(pScrn, bios);
4756
4757 parse_init_tables(pScrn, bios);
4758
4759 if (bios->major_version < 5)
4760 /* feature_byte on BMP is poor, but init always sets CR4B */
4761 bios->is_mobile = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_4B) & 0x40;
4762
4763 /* all BIT systems need p_f_m_t for digital_min_front_porch */
4764 if (bios->is_mobile || bios->major_version >= 5)
4765 ret = parse_fp_mode_table(pScrn, bios);
4766
4767 NVLockVgaCrtcs(pNv, true);
4768
4769 return ret;
4770}
4771
4772int NVParseBios(ScrnInfoPtr pScrn)
4773{
4774 NVPtr pNv = NVPTR(pScrn);
4775 struct nvbios *bios = &pNv->VBIOS;
4776 uint32_t saved_nv_pextdev_boot_0;
4777 int ret;
4778
4779 if (!NVInitVBIOS(pScrn))
4780 return -ENODEV;
4781 if ((ret = nouveau_parse_vbios_struct(pScrn)))
4782 return ret;
4783 if ((ret = parse_dcb_table(pScrn, bios, pNv->twoHeads)))
4784 return ret;
4785 fixup_legacy_i2c(bios);
4786
4787 if (!bios->major_version) /* we don't run version 0 bios */
4788 return 0;
4789
4790 /* these will need remembering across a suspend */
4791 saved_nv_pextdev_boot_0 = bios_rd32(pScrn, NV_PEXTDEV_BOOT_0);
4792 saved_nv_pfb_cfg0 = bios_rd32(pScrn, NV_PFB_CFG0);
4793
4794 /* init script execution disabled */
4795 bios->execute = false;
4796
4797 bios_wr32(pScrn, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
4798
4799 pNv->vbios = &bios->pub;
4800
4801 if ((ret = nouveau_run_vbios_init(pScrn))) {
4802 pNv->vbios = NULL;
4803 return ret;
4804 }
4805
4806 /* allow subsequent scripts to execute */
4807 bios->execute = true;
4808
4809 return 0;
4810}
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 {
13 OPTION_NOACCEL, 13 OPTION_NOACCEL,
14 OPTION_SHADOW_FB, 14 OPTION_SHADOW_FB,
15 OPTION_VIDEO_KEY, 15 OPTION_VIDEO_KEY,
16 OPTION_FP_DITHER,
17 OPTION_FP_SCALE,
18 OPTION_CMDBUF_LOCATION,
19 OPTION_CMDBUF_SIZE,
20 OPTION_SCALING_MODE,
21 OPTION_EXA_PIXMAPS 16 OPTION_EXA_PIXMAPS
22} NVOpts; 17} NVOpts;
23 18
@@ -28,9 +23,6 @@ static const OptionInfoRec NVOptions[] = {
28 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 23 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
29 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 24 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
30 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 25 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
31 { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE },
32 { OPTION_FP_SCALE, "FPScale", OPTV_BOOLEAN, {0}, FALSE },
33 { OPTION_SCALING_MODE, "ScalingMode", OPTV_STRING, {0}, FALSE },
34 { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE }, 26 { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE },
35 { -1, NULL, OPTV_NONE, {0}, FALSE } 27 { -1, NULL, OPTV_NONE, {0}, FALSE }
36}; 28};
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 @@
1/*
2 * Copyright 1993-2003 NVIDIA, Corporation
3 * Copyright 2006 Dave Airlie
4 * Copyright 2007 Maarten Maathuis
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26#include "nv_include.h"
27
28static void crtc_wr_cio_state(xf86CrtcPtr crtc, int index)
29{
30 NVWriteVgaCrtc(NVPTR(crtc->scrn), to_nouveau_crtc(crtc)->head, index,
31 to_nouveau_crtc(crtc)->state->CRTC[index]);
32}
33
34void nv_crtc_set_digital_vibrance(xf86CrtcPtr crtc, int level)
35{
36 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
37 struct nouveau_crtc_state *regp = nv_crtc->state;
38 NVPtr pNv = NVPTR(crtc->scrn);
39
40 regp->CRTC[NV_CIO_CRE_CSB] = nv_crtc->saturation = level;
41 if (nv_crtc->saturation && pNv->gf4_disp_arch) {
42 regp->CRTC[NV_CIO_CRE_CSB] = 0x80;
43 regp->CRTC[NV_CIO_CRE_5B] = nv_crtc->saturation << 2;
44 crtc_wr_cio_state(crtc, NV_CIO_CRE_5B);
45 }
46 crtc_wr_cio_state(crtc, NV_CIO_CRE_CSB);
47}
48
49void nv_crtc_set_image_sharpening(xf86CrtcPtr crtc, int level)
50{
51 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
52 struct nouveau_crtc_state *regp = nv_crtc->state;
53 NVPtr pNv = NVPTR(crtc->scrn);
54
55 nv_crtc->sharpness = level;
56 if (level < 0) /* blur is in hw range 0x3f -> 0x20 */
57 level += 0x40;
58 regp->ramdac_634 = level;
59 NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_634, regp->ramdac_634);
60}
61
62/* NV4x 0x40.. pll notes:
63 * gpu pll: 0x4000 + 0x4004
64 * ?gpu? pll: 0x4008 + 0x400c
65 * vpll1: 0x4010 + 0x4014
66 * vpll2: 0x4018 + 0x401c
67 * mpll: 0x4020 + 0x4024
68 * mpll: 0x4038 + 0x403c
69 *
70 * the first register of each pair has some unknown details:
71 * bits 0-7: redirected values from elsewhere? (similar to PLL_SETUP_CONTROL?)
72 * bits 20-23: (mpll) something to do with post divider?
73 * bits 28-31: related to single stage mode? (bit 8/12)
74 */
75
76static void nv_crtc_cursor_set(xf86CrtcPtr crtc)
77{
78 NVPtr pNv = NVPTR(crtc->scrn);
79 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
80 struct nouveau_crtc_state *regp = nv_crtc->state;
81 uint32_t cursor_start = nv_crtc->head ? pNv->Cursor2->offset :
82 pNv->Cursor->offset;
83
84 regp->CRTC[NV_CIO_CRE_HCUR_ADDR0_INDEX] = MASK(NV_CIO_CRE_HCUR_ASI) |
85 XLATE(cursor_start, 17,
86 NV_CIO_CRE_HCUR_ADDR0_ADR);
87 regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] = XLATE(cursor_start, 11,
88 NV_CIO_CRE_HCUR_ADDR1_ADR);
89 if (crtc->mode.Flags & V_DBLSCAN)
90 regp->CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX] |= MASK(NV_CIO_CRE_HCUR_ADDR1_CUR_DBL);
91 regp->CRTC[NV_CIO_CRE_HCUR_ADDR2_INDEX] = cursor_start >> 24;
92
93 crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR0_INDEX);
94 crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR1_INDEX);
95 crtc_wr_cio_state(crtc, NV_CIO_CRE_HCUR_ADDR2_INDEX);
96 if (pNv->Architecture == NV_ARCH_40)
97 nv_fix_nv40_hw_cursor(pNv, nv_crtc->head);
98}
99
100static void nv_crtc_calc_state_ext(xf86CrtcPtr crtc, DisplayModePtr mode, int dot_clock)
101{
102 ScrnInfoPtr pScrn = crtc->scrn;
103 NVPtr pNv = NVPTR(pScrn);
104 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
105 struct nouveau_mode_state *state = &pNv->set_state;
106 struct nouveau_crtc_state *regp = &state->head[nv_crtc->head];
107 struct nouveau_pll_vals *pv = &regp->pllvals;
108 struct pll_lims pll_lim;
109 int vclk, arb_burst, arb_fifo_lwm;
110
111 if (get_pll_limits(pScrn, nv_crtc->head ? VPLL2 : VPLL1, &pll_lim))
112 return;
113
114 /* NM2 == 0 is used to determine single stage mode on two stage plls */
115 pv->NM2 = 0;
116
117 /* for newer nv4x the blob uses only the first stage of the vpll below a
118 * certain clock. for a certain nv4b this is 150MHz. since the max
119 * output frequency of the first stage for this card is 300MHz, it is
120 * assumed the threshold is given by vco1 maxfreq/2
121 */
122 /* for early nv4x, specifically nv40 and *some* nv43 (devids 0 and 6,
123 * not 8, others unknown), the blob always uses both plls. no problem
124 * has yet been observed in allowing the use a single stage pll on all
125 * nv43 however. the behaviour of single stage use is untested on nv40
126 */
127 if (pNv->NVArch > 0x40 && dot_clock <= (pll_lim.vco1.maxfreq / 2))
128 memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2));
129
130 if (!(vclk = nouveau_calc_pll_mnp(pScrn, &pll_lim, dot_clock, pv)))
131 return;
132
133 /* The blob uses this always, so let's do the same */
134 if (pNv->Architecture == NV_ARCH_40)
135 state->pllsel |= NV_RAMDAC_PLL_SELECT_USE_VPLL2_TRUE;
136 /* again nv40 and some nv43 act more like nv3x as described above */
137 if (pNv->NVArch < 0x41)
138 state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL |
139 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL;
140 state->pllsel |= (nv_crtc->head ? NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2 |
141 NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2 :
142 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL |
143 NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2);
144
145 if (pv->NM2)
146 NV_TRACE(pScrn, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n",
147 pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P);
148 else
149 NV_TRACE(pScrn, "vpll: n %d m %d log2p %d\n",
150 pv->N1, pv->M1, pv->log2P);
151
152 nouveau_calc_arb(pScrn, vclk, pScrn->bitsPerPixel, &arb_burst, &arb_fifo_lwm);
153
154 regp->CRTC[NV_CIO_CRE_FF_INDEX] = arb_burst;
155 regp->CRTC[NV_CIO_CRE_FFLWM__INDEX] = arb_fifo_lwm & 0xff;
156 if (pNv->Architecture >= NV_ARCH_30)
157 regp->CRTC[NV_CIO_CRE_47] = arb_fifo_lwm >> 8;
158
159 nv_crtc_cursor_set(crtc);
160}
161
162static void
163nv_crtc_dpms(xf86CrtcPtr crtc, int mode)
164{
165 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
166 ScrnInfoPtr pScrn = crtc->scrn;
167 NVPtr pNv = NVPTR(pScrn);
168 unsigned char seq1 = 0, crtc17 = 0;
169 unsigned char crtc1A;
170
171 NV_TRACE(pScrn, "Setting dpms mode %d on CRTC %d\n", mode, nv_crtc->head);
172
173 if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */
174 return;
175
176 nv_crtc->last_dpms = mode;
177
178 if (pNv->twoHeads)
179 NVSetOwner(pNv, nv_crtc->head);
180
181 /* nv4ref indicates these two RPC1 bits inhibit h/v sync */
182 crtc1A = NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RPC1_INDEX) & ~0xC0;
183 switch(mode) {
184 case DPMSModeStandby:
185 /* Screen: Off; HSync: Off, VSync: On -- Not Supported */
186 seq1 = 0x20;
187 crtc17 = 0x80;
188 crtc1A |= 0x80;
189 break;
190 case DPMSModeSuspend:
191 /* Screen: Off; HSync: On, VSync: Off -- Not Supported */
192 seq1 = 0x20;
193 crtc17 = 0x80;
194 crtc1A |= 0x40;
195 break;
196 case DPMSModeOff:
197 /* Screen: Off; HSync: Off, VSync: Off */
198 seq1 = 0x20;
199 crtc17 = 0x00;
200 crtc1A |= 0xC0;
201 break;
202 case DPMSModeOn:
203 default:
204 /* Screen: On; HSync: On, VSync: On */
205 seq1 = 0x00;
206 crtc17 = 0x80;
207 break;
208 }
209
210 NVVgaSeqReset(pNv, nv_crtc->head, true);
211 /* Each head has it's own sequencer, so we can turn it off when we want */
212 seq1 |= (NVReadVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX) & ~0x20);
213 NVWriteVgaSeq(pNv, nv_crtc->head, NV_VIO_SR_CLOCK_INDEX, seq1);
214 crtc17 |= (NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX) & ~0x80);
215 usleep(10000);
216 NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CR_MODE_INDEX, crtc17);
217 NVVgaSeqReset(pNv, nv_crtc->head, false);
218
219 NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RPC1_INDEX, crtc1A);
220}
221
222static Bool
223nv_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
224 DisplayModePtr adjusted_mode)
225{
226 return TRUE;
227}
228
229static void
230nv_crtc_mode_set_vga(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode)
231{
232 ScrnInfoPtr pScrn = crtc->scrn;
233 NVPtr pNv = NVPTR(pScrn);
234 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
235 struct nouveau_crtc_state *regp = nv_crtc->state;
236
237 /* Calculate our timings */
238 int horizDisplay = (mode->CrtcHDisplay >> 3) - 1;
239 int horizStart = (mode->CrtcHSyncStart >> 3) - 1;
240 int horizEnd = (mode->CrtcHSyncEnd >> 3) - 1;
241 int horizTotal = (mode->CrtcHTotal >> 3) - 5;
242 int horizBlankStart = (mode->CrtcHDisplay >> 3) - 1;
243 int horizBlankEnd = (mode->CrtcHTotal >> 3) - 1;
244 int vertDisplay = mode->CrtcVDisplay - 1;
245 int vertStart = mode->CrtcVSyncStart - 1;
246 int vertEnd = mode->CrtcVSyncEnd - 1;
247 int vertTotal = mode->CrtcVTotal - 2;
248 int vertBlankStart = mode->CrtcVDisplay - 1;
249 int vertBlankEnd = mode->CrtcVTotal - 1;
250
251 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
252 bool fp_output = false;
253 int i;
254
255 for (i = 0; i < xf86_config->num_output; i++) {
256 xf86OutputPtr output = xf86_config->output[i];
257 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
258
259 if (output->crtc == crtc && IS_DFP(nv_encoder->dcb->type))
260 fp_output = true;
261 }
262
263 if (fp_output) {
264 vertStart = vertTotal - 3;
265 vertEnd = vertTotal - 2;
266 vertBlankStart = vertStart;
267 horizStart = horizTotal - 5;
268 horizEnd = horizTotal - 2;
269 horizBlankEnd = horizTotal + 4;
270 if (pNv->overlayAdaptor && pNv->Architecture >= NV_ARCH_10)
271 /* This reportedly works around some video overlay bandwidth problems */
272 horizTotal += 2;
273 }
274
275 if (mode->Flags & V_INTERLACE)
276 vertTotal |= 1;
277
278#if 0
279 ErrorF("horizDisplay: 0x%X \n", horizDisplay);
280 ErrorF("horizStart: 0x%X \n", horizStart);
281 ErrorF("horizEnd: 0x%X \n", horizEnd);
282 ErrorF("horizTotal: 0x%X \n", horizTotal);
283 ErrorF("horizBlankStart: 0x%X \n", horizBlankStart);
284 ErrorF("horizBlankEnd: 0x%X \n", horizBlankEnd);
285 ErrorF("vertDisplay: 0x%X \n", vertDisplay);
286 ErrorF("vertStart: 0x%X \n", vertStart);
287 ErrorF("vertEnd: 0x%X \n", vertEnd);
288 ErrorF("vertTotal: 0x%X \n", vertTotal);
289 ErrorF("vertBlankStart: 0x%X \n", vertBlankStart);
290 ErrorF("vertBlankEnd: 0x%X \n", vertBlankEnd);
291#endif
292
293 /*
294 * compute correct Hsync & Vsync polarity
295 */
296 if ((mode->Flags & (V_PHSYNC | V_NHSYNC))
297 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) {
298
299 regp->MiscOutReg = 0x23;
300 if (mode->Flags & V_NHSYNC) regp->MiscOutReg |= 0x40;
301 if (mode->Flags & V_NVSYNC) regp->MiscOutReg |= 0x80;
302 } else {
303 int VDisplay = mode->VDisplay;
304 if (mode->Flags & V_DBLSCAN)
305 VDisplay *= 2;
306 if (mode->VScan > 1)
307 VDisplay *= mode->VScan;
308 if (VDisplay < 400)
309 regp->MiscOutReg = 0xA3; /* +hsync -vsync */
310 else if (VDisplay < 480)
311 regp->MiscOutReg = 0x63; /* -hsync +vsync */
312 else if (VDisplay < 768)
313 regp->MiscOutReg = 0xE3; /* -hsync -vsync */
314 else
315 regp->MiscOutReg = 0x23; /* +hsync +vsync */
316 }
317
318 regp->MiscOutReg |= (mode->ClockIndex & 0x03) << 2;
319
320 /*
321 * Time Sequencer
322 */
323 regp->Sequencer[NV_VIO_SR_RESET_INDEX] = 0x00;
324 /* 0x20 disables the sequencer */
325 if (mode->Flags & V_CLKDIV2)
326 regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x29;
327 else
328 regp->Sequencer[NV_VIO_SR_CLOCK_INDEX] = 0x21;
329 regp->Sequencer[NV_VIO_SR_PLANE_MASK_INDEX] = 0x0F;
330 regp->Sequencer[NV_VIO_SR_CHAR_MAP_INDEX] = 0x00;
331 regp->Sequencer[NV_VIO_SR_MEM_MODE_INDEX] = 0x0E;
332
333 /*
334 * CRTC
335 */
336 regp->CRTC[NV_CIO_CR_HDT_INDEX] = horizTotal;
337 regp->CRTC[NV_CIO_CR_HDE_INDEX] = horizDisplay;
338 regp->CRTC[NV_CIO_CR_HBS_INDEX] = horizBlankStart;
339 regp->CRTC[NV_CIO_CR_HBE_INDEX] = (1 << 7) |
340 XLATE(horizBlankEnd, 0, NV_CIO_CR_HBE_4_0);
341 regp->CRTC[NV_CIO_CR_HRS_INDEX] = horizStart;
342 regp->CRTC[NV_CIO_CR_HRE_INDEX] = XLATE(horizBlankEnd, 5, NV_CIO_CR_HRE_HBE_5) |
343 XLATE(horizEnd, 0, NV_CIO_CR_HRE_4_0);
344 regp->CRTC[NV_CIO_CR_VDT_INDEX] = vertTotal;
345 regp->CRTC[NV_CIO_CR_OVL_INDEX] = XLATE(vertStart, 9, NV_CIO_CR_OVL_VRS_9) |
346 XLATE(vertDisplay, 9, NV_CIO_CR_OVL_VDE_9) |
347 XLATE(vertTotal, 9, NV_CIO_CR_OVL_VDT_9) |
348 (1 << 4) |
349 XLATE(vertBlankStart, 8, NV_CIO_CR_OVL_VBS_8) |
350 XLATE(vertStart, 8, NV_CIO_CR_OVL_VRS_8) |
351 XLATE(vertDisplay, 8, NV_CIO_CR_OVL_VDE_8) |
352 XLATE(vertTotal, 8, NV_CIO_CR_OVL_VDT_8);
353 regp->CRTC[NV_CIO_CR_RSAL_INDEX] = 0x00;
354 regp->CRTC[NV_CIO_CR_CELL_HT_INDEX] = ((mode->Flags & V_DBLSCAN) ? MASK(NV_CIO_CR_CELL_HT_SCANDBL) : 0) |
355 1 << 6 |
356 XLATE(vertBlankStart, 9, NV_CIO_CR_CELL_HT_VBS_9);
357 regp->CRTC[NV_CIO_CR_CURS_ST_INDEX] = 0x00;
358 regp->CRTC[NV_CIO_CR_CURS_END_INDEX] = 0x00;
359 regp->CRTC[NV_CIO_CR_SA_HI_INDEX] = 0x00;
360 regp->CRTC[NV_CIO_CR_SA_LO_INDEX] = 0x00;
361 regp->CRTC[NV_CIO_CR_TCOFF_HI_INDEX] = 0x00;
362 regp->CRTC[NV_CIO_CR_TCOFF_LO_INDEX] = 0x00;
363 regp->CRTC[NV_CIO_CR_VRS_INDEX] = vertStart;
364 regp->CRTC[NV_CIO_CR_VRE_INDEX] = 1 << 5 | XLATE(vertEnd, 0, NV_CIO_CR_VRE_3_0);
365 regp->CRTC[NV_CIO_CR_VDE_INDEX] = vertDisplay;
366 /* framebuffer can be larger than crtc scanout area. */
367 regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = pScrn->displayWidth / 8 * pScrn->bitsPerPixel / 8;
368 regp->CRTC[NV_CIO_CR_ULINE_INDEX] = 0x00;
369 regp->CRTC[NV_CIO_CR_VBS_INDEX] = vertBlankStart;
370 regp->CRTC[NV_CIO_CR_VBE_INDEX] = vertBlankEnd;
371 regp->CRTC[NV_CIO_CR_MODE_INDEX] = 0x43;
372 regp->CRTC[NV_CIO_CR_LCOMP_INDEX] = 0xff;
373
374 /*
375 * Some extended CRTC registers (they are not saved with the rest of the vga regs).
376 */
377
378 /* framebuffer can be larger than crtc scanout area. */
379 regp->CRTC[NV_CIO_CRE_RPC0_INDEX] = XLATE(pScrn->displayWidth / 8 * pScrn->bitsPerPixel / 8, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
380 regp->CRTC[NV_CIO_CRE_RPC1_INDEX] = mode->CrtcHDisplay < 1280 ?
381 MASK(NV_CIO_CRE_RPC1_LARGE) : 0x00;
382 regp->CRTC[NV_CIO_CRE_LSR_INDEX] = XLATE(horizBlankEnd, 6, NV_CIO_CRE_LSR_HBE_6) |
383 XLATE(vertBlankStart, 10, NV_CIO_CRE_LSR_VBS_10) |
384 XLATE(vertStart, 10, NV_CIO_CRE_LSR_VRS_10) |
385 XLATE(vertDisplay, 10, NV_CIO_CRE_LSR_VDE_10) |
386 XLATE(vertTotal, 10, NV_CIO_CRE_LSR_VDT_10);
387 regp->CRTC[NV_CIO_CRE_HEB__INDEX] = XLATE(horizStart, 8, NV_CIO_CRE_HEB_HRS_8) |
388 XLATE(horizBlankStart, 8, NV_CIO_CRE_HEB_HBS_8) |
389 XLATE(horizDisplay, 8, NV_CIO_CRE_HEB_HDE_8) |
390 XLATE(horizTotal, 8, NV_CIO_CRE_HEB_HDT_8);
391 regp->CRTC[NV_CIO_CRE_EBR_INDEX] = XLATE(vertBlankStart, 11, NV_CIO_CRE_EBR_VBS_11) |
392 XLATE(vertStart, 11, NV_CIO_CRE_EBR_VRS_11) |
393 XLATE(vertDisplay, 11, NV_CIO_CRE_EBR_VDE_11) |
394 XLATE(vertTotal, 11, NV_CIO_CRE_EBR_VDT_11);
395
396 if (mode->Flags & V_INTERLACE) {
397 horizTotal = (horizTotal >> 1) & ~1;
398 regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = horizTotal;
399 regp->CRTC[NV_CIO_CRE_HEB__INDEX] |= XLATE(horizTotal, 8, NV_CIO_CRE_HEB_ILC_8);
400 } else
401 regp->CRTC[NV_CIO_CRE_ILACE__INDEX] = 0xff; /* interlace off */
402
403 /*
404 * Graphics Display Controller
405 */
406 regp->Graphics[NV_VIO_GX_SR_INDEX] = 0x00;
407 regp->Graphics[NV_VIO_GX_SREN_INDEX] = 0x00;
408 regp->Graphics[NV_VIO_GX_CCOMP_INDEX] = 0x00;
409 regp->Graphics[NV_VIO_GX_ROP_INDEX] = 0x00;
410 regp->Graphics[NV_VIO_GX_READ_MAP_INDEX] = 0x00;
411 regp->Graphics[NV_VIO_GX_MODE_INDEX] = 0x40; /* 256 color mode */
412 regp->Graphics[NV_VIO_GX_MISC_INDEX] = 0x05; /* map 64k mem + graphic mode */
413 regp->Graphics[NV_VIO_GX_DONT_CARE_INDEX] = 0x0F;
414 regp->Graphics[NV_VIO_GX_BIT_MASK_INDEX] = 0xFF;
415
416 regp->Attribute[0] = 0x00; /* standard colormap translation */
417 regp->Attribute[1] = 0x01;
418 regp->Attribute[2] = 0x02;
419 regp->Attribute[3] = 0x03;
420 regp->Attribute[4] = 0x04;
421 regp->Attribute[5] = 0x05;
422 regp->Attribute[6] = 0x06;
423 regp->Attribute[7] = 0x07;
424 regp->Attribute[8] = 0x08;
425 regp->Attribute[9] = 0x09;
426 regp->Attribute[10] = 0x0A;
427 regp->Attribute[11] = 0x0B;
428 regp->Attribute[12] = 0x0C;
429 regp->Attribute[13] = 0x0D;
430 regp->Attribute[14] = 0x0E;
431 regp->Attribute[15] = 0x0F;
432 regp->Attribute[NV_CIO_AR_MODE_INDEX] = 0x01; /* Enable graphic mode */
433 /* Non-vga */
434 regp->Attribute[NV_CIO_AR_OSCAN_INDEX] = 0x00;
435 regp->Attribute[NV_CIO_AR_PLANE_INDEX] = 0x0F; /* enable all color planes */
436 regp->Attribute[NV_CIO_AR_HPP_INDEX] = 0x00;
437 regp->Attribute[NV_CIO_AR_CSEL_INDEX] = 0x00;
438}
439
440/**
441 * Sets up registers for the given mode/adjusted_mode pair.
442 *
443 * The clocks, CRTCs and outputs attached to this CRTC must be off.
444 *
445 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
446 * be easily turned on/off after this.
447 */
448static void
449nv_crtc_mode_set_regs(xf86CrtcPtr crtc, DisplayModePtr mode)
450{
451 ScrnInfoPtr pScrn = crtc->scrn;
452 NVPtr pNv = NVPTR(pScrn);
453 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
454 struct nouveau_crtc_state *regp = nv_crtc->state;
455 struct nouveau_crtc_state *savep = &pNv->saved_regs.head[nv_crtc->head];
456 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
457 bool lvds_output = false, tmds_output = false, off_chip_digital = false;
458 int i;
459
460 for (i = 0; i < xf86_config->num_output; i++) {
461 xf86OutputPtr output = xf86_config->output[i];
462 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
463 bool digital = false;
464
465 if (output->crtc != crtc || !nv_encoder)
466 continue;
467
468 if (nv_encoder->dcb->type == OUTPUT_LVDS)
469 digital = lvds_output = true;
470 if (nv_encoder->dcb->type == OUTPUT_TMDS)
471 digital = tmds_output = true;
472 if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && digital)
473 off_chip_digital = true;
474 }
475
476 /* Registers not directly related to the (s)vga mode */
477
478 /* What is the meaning of this register? */
479 /* A few popular values are 0x18, 0x1c, 0x38, 0x3c */
480 regp->CRTC[NV_CIO_CRE_ENH_INDEX] = savep->CRTC[NV_CIO_CRE_ENH_INDEX] & ~(1<<5);
481
482 regp->crtc_eng_ctrl = 0;
483 /* Except for rare conditions I2C is enabled on the primary crtc */
484 if (nv_crtc->head == 0)
485 regp->crtc_eng_ctrl |= NV_CRTC_FSEL_I2C;
486 /* Set overlay to desired crtc. */
487 if (pNv->overlayAdaptor) {
488 NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
489 if (pPriv->overlayCRTC == nv_crtc->head)
490 regp->crtc_eng_ctrl |= NV_CRTC_FSEL_OVERLAY;
491 }
492
493 /* ADDRESS_SPACE_PNVM is the same as setting HCUR_ASI */
494 regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 |
495 NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 |
496 NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM;
497 if (pNv->alphaCursor)
498 regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32;
499 if (mode->Flags & V_DBLSCAN)
500 regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE;
501
502 /* Unblock some timings */
503 regp->CRTC[NV_CIO_CRE_53] = 0;
504 regp->CRTC[NV_CIO_CRE_54] = 0;
505
506 /* 0x00 is disabled, 0x11 is lvds, 0x22 crt and 0x88 tmds */
507 if (lvds_output)
508 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x11;
509 else if (tmds_output)
510 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x88;
511 else
512 regp->CRTC[NV_CIO_CRE_SCRATCH3__INDEX] = 0x22;
513
514 /* These values seem to vary */
515 /* This register seems to be used by the bios to make certain decisions on some G70 cards? */
516 regp->CRTC[NV_CIO_CRE_SCRATCH4__INDEX] = savep->CRTC[NV_CIO_CRE_SCRATCH4__INDEX];
517
518 nv_crtc_set_digital_vibrance(crtc, nv_crtc->saturation);
519
520 /* probably a scratch reg, but kept for cargo-cult purposes:
521 * bit0: crtc0?, head A
522 * bit6: lvds, head A
523 * bit7: (only in X), head A
524 */
525 if (nv_crtc->head == 0)
526 regp->CRTC[NV_CIO_CRE_4B] = savep->CRTC[NV_CIO_CRE_4B] | 0x80;
527
528 /* The blob seems to take the current value from crtc 0, add 4 to that
529 * and reuse the old value for crtc 1 */
530 regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] = pNv->saved_regs.head[0].CRTC[NV_CIO_CRE_TVOUT_LATENCY];
531 if (!nv_crtc->head)
532 regp->CRTC[NV_CIO_CRE_TVOUT_LATENCY] += 4;
533
534 /* the blob sometimes sets |= 0x10 (which is the same as setting |=
535 * 1 << 30 on 0x60.830), for no apparent reason */
536 regp->CRTC[NV_CIO_CRE_59] = off_chip_digital;
537
538 regp->crtc_830 = mode->CrtcVDisplay - 3;
539 regp->crtc_834 = mode->CrtcVDisplay - 1;
540
541 if (pNv->Architecture == NV_ARCH_40)
542 /* This is what the blob does */
543 regp->crtc_850 = NVReadCRTC(pNv, 0, NV_PCRTC_850);
544
545 if (pNv->Architecture == NV_ARCH_40)
546 regp->gpio_ext = NVReadCRTC(pNv, 0, NV_PCRTC_GPIO_EXT);
547
548 regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC;
549
550 /* Some misc regs */
551 if (pNv->Architecture == NV_ARCH_40) {
552 regp->CRTC[NV_CIO_CRE_85] = 0xFF;
553 regp->CRTC[NV_CIO_CRE_86] = 0x1;
554 }
555
556 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] = (pScrn->depth + 1) / 8;
557 /* Enable slaved mode (called MODE_TV in nv4ref.h) */
558 if (lvds_output || tmds_output)
559 regp->CRTC[NV_CIO_CRE_PIXEL_INDEX] |= (1 << 7);
560
561 /* Generic PRAMDAC regs */
562
563 if (pNv->Architecture >= NV_ARCH_10)
564 /* Only bit that bios and blob set. */
565 regp->nv10_cursync = (1 << 25);
566
567 regp->ramdac_gen_ctrl = NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
568 NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL |
569 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON;
570 if (pScrn->depth == 16)
571 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL;
572 if (pNv->alphaCursor)
573 regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG;
574
575 regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */
576
577 nv_crtc_set_image_sharpening(crtc, nv_crtc->sharpness);
578
579 /* Some values the blob sets */
580 regp->ramdac_a20 = 0x0;
581 regp->ramdac_a24 = 0xfffff;
582 regp->ramdac_a34 = 0x1;
583}
584
585enum fp_display_regs {
586 FP_DISPLAY_END,
587 FP_TOTAL,
588 FP_CRTC,
589 FP_SYNC_START,
590 FP_SYNC_END,
591 FP_VALID_START,
592 FP_VALID_END
593};
594
595/* this could be set in nv_output, but would require some rework of load/save */
596static void
597nv_crtc_mode_set_fp_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode)
598{
599 ScrnInfoPtr pScrn = crtc->scrn;
600 NVPtr pNv = NVPTR(pScrn);
601 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
602 struct nouveau_crtc_state *regp = nv_crtc->state;
603 struct nouveau_crtc_state *savep = &pNv->saved_regs.head[nv_crtc->head];
604 struct nouveau_encoder *nv_encoder = NULL;
605 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
606 uint32_t mode_ratio, panel_ratio;
607 int i;
608
609 for (i = 0; i < xf86_config->num_output; i++) {
610 xf86OutputPtr output = xf86_config->output[i];
611 struct nouveau_encoder *tmp_nve = to_nouveau_encoder(output);
612
613 if (output->crtc != crtc)
614 continue;
615
616 if (IS_DFP(tmp_nve->dcb->type)) {
617 /* assumes a maximum of one fp output per crtc */
618 nv_encoder = tmp_nve;
619 break;
620 }
621 }
622 if (!nv_encoder)
623 return;
624
625 regp->fp_horiz_regs[FP_DISPLAY_END] = adjusted_mode->HDisplay - 1;
626 regp->fp_horiz_regs[FP_TOTAL] = adjusted_mode->HTotal - 1;
627 if (!pNv->gf4_disp_arch ||
628 (adjusted_mode->HSyncStart - adjusted_mode->HDisplay) >=
629 pNv->vbios->digital_min_front_porch)
630 regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HDisplay;
631 else
632 regp->fp_horiz_regs[FP_CRTC] = adjusted_mode->HSyncStart - pNv->vbios->digital_min_front_porch - 1;
633 regp->fp_horiz_regs[FP_SYNC_START] = adjusted_mode->HSyncStart - 1;
634 regp->fp_horiz_regs[FP_SYNC_END] = adjusted_mode->HSyncEnd - 1;
635 regp->fp_horiz_regs[FP_VALID_START] = adjusted_mode->HSkew;
636 regp->fp_horiz_regs[FP_VALID_END] = adjusted_mode->HDisplay - 1;
637
638 regp->fp_vert_regs[FP_DISPLAY_END] = adjusted_mode->VDisplay - 1;
639 regp->fp_vert_regs[FP_TOTAL] = adjusted_mode->VTotal - 1;
640 regp->fp_vert_regs[FP_CRTC] = adjusted_mode->VTotal - 5 - 1;
641 regp->fp_vert_regs[FP_SYNC_START] = adjusted_mode->VSyncStart - 1;
642 regp->fp_vert_regs[FP_SYNC_END] = adjusted_mode->VSyncEnd - 1;
643 regp->fp_vert_regs[FP_VALID_START] = 0;
644 regp->fp_vert_regs[FP_VALID_END] = adjusted_mode->VDisplay - 1;
645
646 /* bit26: a bit seen on some g7x, no as yet discernable purpose */
647 regp->fp_control = NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |
648 (savep->fp_control & (1 << 26 | NV_PRAMDAC_FP_TG_CONTROL_READ_PROG));
649 /* Deal with vsync/hsync polarity */
650 /* LVDS screens do set this, but modes with +ve syncs are very rare */
651 if (adjusted_mode->Flags & V_PVSYNC)
652 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS;
653 if (adjusted_mode->Flags & V_PHSYNC)
654 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS;
655 /* panel scaling first, as native would get set otherwise */
656 if (nv_encoder->scaling_mode == SCALE_PANEL ||
657 nv_encoder->scaling_mode == SCALE_NOSCALE) /* panel handles it */
658 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER;
659 else if (mode->HDisplay == adjusted_mode->HDisplay &&
660 mode->VDisplay == adjusted_mode->VDisplay) /* native mode */
661 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE;
662 else /* gpu needs to scale */
663 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE;
664 if (nvReadEXTDEV(pNv, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT)
665 regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12;
666 if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP &&
667 adjusted_mode->Clock > 165000)
668 regp->fp_control |= (2 << 24);
669 if (nv_encoder->dual_link)
670 regp->fp_control |= (8 << 28);
671
672 regp->fp_debug_0 = NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND |
673 NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND |
674 NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR |
675 NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR |
676 NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED |
677 NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE |
678 NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE;
679
680 /* We want automatic scaling */
681 regp->fp_debug_1 = 0;
682 /* This can override HTOTAL and VTOTAL */
683 regp->fp_debug_2 = 0;
684
685 /* Use 20.12 fixed point format to avoid floats */
686 mode_ratio = (1 << 12) * mode->HDisplay / mode->VDisplay;
687 panel_ratio = (1 << 12) * adjusted_mode->HDisplay / adjusted_mode->VDisplay;
688 /* if ratios are equal, SCALE_ASPECT will automatically (and correctly)
689 * get treated the same as SCALE_FULLSCREEN */
690 if (nv_encoder->scaling_mode == SCALE_ASPECT && mode_ratio != panel_ratio) {
691 uint32_t diff, scale;
692 bool divide_by_2 = pNv->gf4_disp_arch;
693
694 if (mode_ratio < panel_ratio) {
695 /* vertical needs to expand to glass size (automatic)
696 * horizontal needs to be scaled at vertical scale factor
697 * to maintain aspect */
698
699 scale = (1 << 12) * mode->VDisplay / adjusted_mode->VDisplay;
700 regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE |
701 XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE);
702
703 /* restrict area of screen used, horizontally */
704 diff = adjusted_mode->HDisplay -
705 adjusted_mode->VDisplay * mode_ratio / (1 << 12);
706 regp->fp_horiz_regs[FP_VALID_START] += diff / 2;
707 regp->fp_horiz_regs[FP_VALID_END] -= diff / 2;
708 }
709
710 if (mode_ratio > panel_ratio) {
711 /* horizontal needs to expand to glass size (automatic)
712 * vertical needs to be scaled at horizontal scale factor
713 * to maintain aspect */
714
715 scale = (1 << 12) * mode->HDisplay / adjusted_mode->HDisplay;
716 regp->fp_debug_1 = NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE |
717 XLATE(scale, divide_by_2, NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE);
718
719 /* restrict area of screen used, vertically */
720 diff = adjusted_mode->VDisplay -
721 (1 << 12) * adjusted_mode->HDisplay / mode_ratio;
722 regp->fp_vert_regs[FP_VALID_START] += diff / 2;
723 regp->fp_vert_regs[FP_VALID_END] -= diff / 2;
724 }
725 }
726
727 /* Output property. */
728 if (nv_encoder && nv_encoder->dithering) {
729 if (pNv->NVArch == 0x11)
730 regp->dither = savep->dither | 0x00010000;
731 else {
732 int i;
733 regp->dither = savep->dither | 0x00000001;
734 for (i = 0; i < 3; i++) {
735 regp->dither_regs[i] = 0xe4e4e4e4;
736 regp->dither_regs[i + 3] = 0x44444444;
737 }
738 }
739 } else {
740 if (pNv->NVArch != 0x11) {
741 /* reset them */
742 int i;
743 for (i = 0; i < 3; i++) {
744 regp->dither_regs[i] = savep->dither_regs[i];
745 regp->dither_regs[i + 3] = savep->dither_regs[i + 3];
746 }
747 }
748 regp->dither = savep->dither;
749 }
750}
751
752/**
753 * Sets up registers for the given mode/adjusted_mode pair.
754 *
755 * The clocks, CRTCs and outputs attached to this CRTC must be off.
756 *
757 * This shouldn't enable any clocks, CRTCs, or outputs, but they should
758 * be easily turned on/off after this.
759 */
760static void
761nv_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
762 DisplayModePtr adjusted_mode,
763 int x, int y)
764{
765 ScrnInfoPtr pScrn = crtc->scrn;
766 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
767 NVPtr pNv = NVPTR(pScrn);
768
769 NV_TRACE(pScrn, "CTRC mode on CRTC %d:\n", nv_crtc->head);
770 xf86PrintModeline(pScrn->scrnIndex, mode);
771 NV_TRACE(pScrn, "Output mode on CRTC %d:\n", nv_crtc->head);
772 xf86PrintModeline(pScrn->scrnIndex, adjusted_mode);
773
774 /* unlock must come after turning off FP_TG_CONTROL in output_prepare */
775 nv_lock_vga_crtc_shadow(pNv, nv_crtc->head, -1);
776
777 nv_crtc_mode_set_vga(crtc, mode, adjusted_mode);
778 /* calculated in output_prepare, nv40 needs it written before calculating PLLs */
779 if (pNv->Architecture == NV_ARCH_40)
780 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, pNv->set_state.sel_clk);
781 nv_crtc_mode_set_regs(crtc, mode);
782 nv_crtc_mode_set_fp_regs(crtc, mode, adjusted_mode);
783 nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->Clock);
784
785 nouveau_hw_load_state(pScrn, nv_crtc->head, &pNv->set_state);
786
787 NVCrtcSetBase(crtc, x, y);
788
789#if X_BYTE_ORDER == X_BIG_ENDIAN
790 /* turn on LFB swapping */
791 {
792 uint8_t tmp = NVReadVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RCR);
793 tmp |= MASK(NV_CIO_CRE_RCR_ENDIAN_BIG);
794 NVWriteVgaCrtc(pNv, nv_crtc->head, NV_CIO_CRE_RCR, tmp);
795 }
796#endif
797}
798
799static void nv_crtc_save(xf86CrtcPtr crtc)
800{
801 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
802 NVPtr pNv = NVPTR(crtc->scrn);
803
804 if (pNv->twoHeads)
805 NVSetOwner(pNv, nv_crtc->head);
806
807 nouveau_hw_save_state(crtc->scrn, nv_crtc->head, &pNv->saved_regs);
808
809 /* init some state to saved value */
810 pNv->set_state.sel_clk = pNv->saved_regs.sel_clk & ~(0x5 << 16);
811 nv_crtc->state->CRTC[NV_CIO_CRE_LCD__INDEX] = pNv->saved_regs.head[nv_crtc->head].CRTC[NV_CIO_CRE_LCD__INDEX];
812}
813
814static void nv_crtc_restore(xf86CrtcPtr crtc)
815{
816 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
817 NVPtr pNv = NVPTR(crtc->scrn);
818 int head = nv_crtc->head;
819 uint8_t saved_cr21 = pNv->saved_regs.head[head].CRTC[NV_CIO_CRE_21];
820
821 if (pNv->twoHeads)
822 NVSetOwner(pNv, head);
823
824 nouveau_hw_load_state(crtc->scrn, head, &pNv->saved_regs);
825 nv_lock_vga_crtc_shadow(pNv, head, saved_cr21);
826
827 nv_crtc->last_dpms = NV_DPMS_CLEARED;
828}
829
830static void nv_crtc_prepare(xf86CrtcPtr crtc)
831{
832 ScrnInfoPtr pScrn = crtc->scrn;
833 NVPtr pNv = NVPTR(pScrn);
834 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
835
836 if (pNv->twoHeads)
837 NVSetOwner(pNv, nv_crtc->head);
838
839 crtc->funcs->dpms(crtc, DPMSModeOff);
840
841 /* Sync the engine before adjust mode */
842 if (pNv->EXADriverPtr) {
843 exaMarkSync(pScrn->pScreen);
844 exaWaitSync(pScrn->pScreen);
845 }
846
847 NVBlankScreen(pNv, nv_crtc->head, true);
848
849 /* Some more preperation. */
850 NVWriteCRTC(pNv, nv_crtc->head, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
851 if (pNv->Architecture == NV_ARCH_40) {
852 uint32_t reg900 = NVReadRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_900);
853 NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_900, reg900 & ~0x10000);
854 }
855}
856
857static void nv_crtc_commit(xf86CrtcPtr crtc)
858{
859 crtc->funcs->dpms (crtc, DPMSModeOn);
860
861 if (crtc->scrn->pScreen != NULL) {
862 NVPtr pNv = NVPTR(crtc->scrn);
863
864 xf86_reload_cursors (crtc->scrn->pScreen);
865 if (!pNv->alphaCursor) {
866 /* this works round the fact that xf86_reload_cursors
867 * will quite happily show the hw cursor when it knows
868 * the hardware can't do alpha, and the current cursor
869 * has an alpha channel
870 */
871 xf86ForceHWCursor(crtc->scrn->pScreen, 1);
872 xf86ForceHWCursor(crtc->scrn->pScreen, 0);
873 }
874 }
875}
876
877static void nv_crtc_destroy(xf86CrtcPtr crtc)
878{
879 xfree(to_nouveau_crtc(crtc));
880}
881
882static Bool nv_crtc_lock(xf86CrtcPtr crtc)
883{
884 return FALSE;
885}
886
887static void nv_crtc_unlock(xf86CrtcPtr crtc)
888{
889}
890
891static void
892nv_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
893 int size)
894{
895 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
896 NVPtr pNv = NVPTR(crtc->scrn);
897 struct rgb { uint8_t r, g, b; } __attribute__((packed)) *rgbs;
898 int i;
899
900 rgbs = (struct rgb *)nv_crtc->state->DAC;
901
902 for (i = 0; i < 256; i++) {
903 rgbs[i].r = red[i] >> 8;
904 rgbs[i].g = green[i] >> 8;
905 rgbs[i].b = blue[i] >> 8;
906 }
907
908 nouveau_hw_load_state_palette(pNv, nv_crtc->head, &pNv->set_state);
909}
910
911/**
912 * Allocates memory for a locked-in-framebuffer shadow of the given
913 * width and height for this CRTC's rotated shadow framebuffer.
914 */
915
916static void *
917nv_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
918{
919 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
920 ScrnInfoPtr pScrn = crtc->scrn;
921 ScreenPtr pScreen = pScrn->pScreen;
922 NVPtr pNv = NVPTR(pScrn);
923 void *offset;
924 int size, align = 64;
925
926 nv_crtc->shadow_pitch = pScrn->displayWidth * (pScrn->bitsPerPixel/8);
927 size = nv_crtc->shadow_pitch * height;
928
929 assert(nv_crtc->shadow == NULL);
930 if (!pScreen) {
931 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
932 "Can't allocate shadow memory for rotated CRTC at server regeneration\n");
933 return NULL;
934 }
935 nv_crtc->shadow = exaOffscreenAlloc(pScreen, size, align, TRUE, NULL, NULL);
936 if (nv_crtc->shadow == NULL) {
937 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
938 "Couldn't allocate shadow memory for rotated CRTC.\n");
939 return NULL;
940 }
941 offset = pNv->offscreen_map + nv_crtc->shadow->offset;
942
943 return offset;
944}
945
946/**
947 * Creates a pixmap for this CRTC's rotated shadow framebuffer.
948 */
949static PixmapPtr
950nv_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
951{
952 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
953 ScrnInfoPtr pScrn = crtc->scrn;
954 PixmapPtr rotate_pixmap;
955
956 if (!data)
957 data = crtc->funcs->shadow_allocate (crtc, width, height);
958
959 rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, width, height,
960 pScrn->depth,
961 pScrn->bitsPerPixel,
962 nv_crtc->shadow_pitch, data);
963 if (rotate_pixmap == NULL) {
964 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
965 "Couldn't allocate shadow pixmap for rotated CRTC\n");
966 }
967
968 return rotate_pixmap;
969}
970
971static void
972nv_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
973{
974 ScrnInfoPtr pScrn = crtc->scrn;
975 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
976 ScreenPtr pScreen = pScrn->pScreen;
977
978 if (rotate_pixmap) { /* This should also unmap the buffer object if relevant. */
979 pScreen->DestroyPixmap(rotate_pixmap);
980 }
981
982 if (data && nv_crtc->shadow)
983 exaOffscreenFree(pScreen, nv_crtc->shadow);
984
985 nv_crtc->shadow = NULL;
986}
987
988static const xf86CrtcFuncsRec nv_crtc_funcs = {
989 .dpms = nv_crtc_dpms,
990 .save = nv_crtc_save,
991 .restore = nv_crtc_restore,
992 .mode_fixup = nv_crtc_mode_fixup,
993 .mode_set = nv_crtc_mode_set,
994 .prepare = nv_crtc_prepare,
995 .commit = nv_crtc_commit,
996 .destroy = nv_crtc_destroy,
997 .lock = nv_crtc_lock,
998 .unlock = nv_crtc_unlock,
999 .set_cursor_colors = nv_crtc_set_cursor_colors,
1000 .set_cursor_position = nv_crtc_set_cursor_position,
1001 .show_cursor = nv_crtc_show_cursor,
1002 .hide_cursor = nv_crtc_hide_cursor,
1003 .load_cursor_image = nv_crtc_load_cursor_image,
1004 .load_cursor_argb = nv_crtc_load_cursor_argb,
1005 .gamma_set = nv_crtc_gamma_set,
1006 .shadow_create = nv_crtc_shadow_create,
1007 .shadow_allocate = nv_crtc_shadow_allocate,
1008 .shadow_destroy = nv_crtc_shadow_destroy,
1009#ifdef RANDR_13_INTERFACE
1010 .set_origin = NVCrtcSetBase,
1011#endif
1012};
1013
1014void
1015nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num)
1016{
1017 NVPtr pNv = NVPTR(pScrn);
1018 static xf86CrtcFuncsRec crtcfuncs;
1019 xf86CrtcPtr crtc;
1020 struct nouveau_crtc *nv_crtc;
1021 int i;
1022
1023 crtcfuncs = nv_crtc_funcs;
1024
1025 if (!pNv->alphaCursor)
1026 crtcfuncs.load_cursor_argb = NULL;
1027 if (pNv->NoAccel) {
1028 crtcfuncs.shadow_create = NULL;
1029 crtcfuncs.shadow_allocate = NULL;
1030 crtcfuncs.shadow_destroy = NULL;
1031 }
1032
1033 if (!(crtc = xf86CrtcCreate(pScrn, &crtcfuncs)))
1034 return;
1035
1036 if (!(nv_crtc = xcalloc(1, sizeof (struct nouveau_crtc)))) {
1037 xf86CrtcDestroy(crtc);
1038 return;
1039 }
1040
1041 nv_crtc->head = crtc_num;
1042 nv_crtc->last_dpms = NV_DPMS_CLEARED;
1043 nv_crtc->state = &pNv->set_state.head[crtc_num];
1044
1045 crtc->driver_private = nv_crtc;
1046
1047 /* Initialise the default LUT table. */
1048 for (i = 0; i < 256; i++) {
1049 nv_crtc->state->DAC[i*3] = i;
1050 nv_crtc->state->DAC[(i*3)+1] = i;
1051 nv_crtc->state->DAC[(i*3)+2] = i;
1052 }
1053}
1054
1055void NVCrtcSetBase(xf86CrtcPtr crtc, int x, int y)
1056{
1057 ScrnInfoPtr pScrn = crtc->scrn;
1058 NVPtr pNv = NVPTR(pScrn);
1059 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
1060 struct nouveau_crtc_state *regp = nv_crtc->state;
1061 struct nouveau_bo *bo;
1062 uint32_t start, pitch;
1063
1064 bo = pNv->scanout;
1065 pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
1066 if (crtc->rotatedData != NULL) {
1067 pitch = nv_crtc->shadow_pitch;
1068 bo = pNv->offscreen;
1069 x = 0;
1070 y = 0;
1071 }
1072
1073 if (nv_crtc->bo)
1074 nouveau_bo_unpin(nv_crtc->bo);
1075 nouveau_bo_pin(bo, NOUVEAU_BO_VRAM);
1076 nv_crtc->bo = bo;
1077
1078 start = nv_crtc->bo->offset;
1079 start += (y * pScrn->displayWidth + x) * pScrn->bitsPerPixel / 8;
1080 if (crtc->rotatedData != NULL)
1081 start += nv_crtc->shadow->offset;
1082
1083 regp->CRTC[NV_CIO_CR_OFFSET_INDEX] = pitch >> 3;
1084 regp->CRTC[NV_CIO_CRE_RPC0_INDEX] =
1085 XLATE(pitch >> 3, 8, NV_CIO_CRE_RPC0_OFFSET_10_8);
1086 crtc_wr_cio_state(crtc, NV_CIO_CRE_RPC0_INDEX);
1087 crtc_wr_cio_state(crtc, NV_CIO_CR_OFFSET_INDEX);
1088
1089 start &= ~3;
1090 nv_crtc->state->fb_start = start;
1091 NVWriteCRTC(pNv, nv_crtc->head, NV_PCRTC_START, start);
1092
1093 crtc->x = x;
1094 crtc->y = y;
1095}
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 @@
1/*
2 * Copyright 2003 NVIDIA, Corporation
3 * Copyright 2007 Maarten Maathuis
4 * Copyright 2009 Stuart Bennett
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "nv_include.h"
26
27#define TO_ARGB1555(c) (0x8000 | /* Mask bit */ \
28 ((c & 0xf80000) >> 9 ) | /* Red */ \
29 ((c & 0xf800) >> 6 ) | /* Green */ \
30 ((c & 0xf8) >> 3 )) /* Blue */
31#define TO_ARGB8888(c) (0xff000000 | c)
32
33#define SOURCE_MASK_INTERLEAVE 32
34#define TRANSPARENT_PIXEL 0
35
36/*
37 * Convert a source/mask bitmap cursor to an ARGB cursor, clipping or
38 * padding as necessary. source/mask are assumed to be alternated each
39 * SOURCE_MASK_INTERLEAVE bits.
40 */
41void
42nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride, int dst_stride,
43 int bpp, uint32_t fg, uint32_t bg)
44{
45 int width = min(src_stride, dst_stride);
46 uint32_t b, m, pxval;
47 int i, j, k;
48
49 for (i = 0; i < width; i++) {
50 for (j = 0; j < width / SOURCE_MASK_INTERLEAVE; j++) {
51 int src_off = i*src_stride/SOURCE_MASK_INTERLEAVE + j;
52 int dst_off = i*dst_stride + j*SOURCE_MASK_INTERLEAVE;
53
54 b = src[2*src_off];
55 m = src[2*src_off + 1];
56
57 for (k = 0; k < SOURCE_MASK_INTERLEAVE; k++) {
58 pxval = TRANSPARENT_PIXEL;
59#if X_BYTE_ORDER == X_BIG_ENDIAN
60 if (m & 0x80000000)
61 pxval = (b & 0x80000000) ? fg : bg;
62 b <<= 1;
63 m <<= 1;
64#else
65 if (m & 1)
66 pxval = (b & 1) ? fg : bg;
67 b >>= 1;
68 m >>= 1;
69#endif
70 if (bpp == 32)
71 ((uint32_t *)dst)[dst_off + k] = pxval;
72 else
73 ((uint16_t *)dst)[dst_off + k] = pxval;
74 }
75 }
76 }
77}
78
79static void nv_cursor_transform_cursor(NVPtr pNv, struct nouveau_crtc *nv_crtc)
80{
81 uint16_t *tmp;
82 struct nouveau_bo *cursor = NULL;
83 int px = nv_cursor_pixels(pNv);
84 int width = nv_cursor_width(pNv);
85
86 if (!(tmp = xcalloc(px, 4)))
87 return;
88
89 /* convert to colour cursor */
90 nv_cursor_convert_cursor(pNv->curImage, tmp, width, width,
91 pNv->alphaCursor ? 32 : 16, nv_crtc->cursor_fg,
92 nv_crtc->cursor_bg);
93
94 nouveau_bo_ref(nv_crtc->head ? pNv->Cursor2 : pNv->Cursor, &cursor);
95 nouveau_bo_map(cursor, NOUVEAU_BO_WR);
96
97 memcpy(cursor->map, tmp, px * 4);
98
99 nouveau_bo_unmap(cursor);
100 nouveau_bo_ref(NULL, &cursor);
101
102 xfree(tmp);
103}
104
105void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
106{
107 NVPtr pNv = NVPTR(crtc->scrn);
108 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
109 uint32_t fore, back;
110
111 if (pNv->alphaCursor) {
112 fore = TO_ARGB8888(fg);
113 back = TO_ARGB8888(bg);
114#if X_BYTE_ORDER == X_BIG_ENDIAN
115 if ((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
116 fore = lswapl(fore);
117 back = lswapl(back);
118 }
119#endif
120 } else {
121 fore = TO_ARGB1555(fg);
122 back = TO_ARGB1555(bg);
123 }
124
125 if (nv_crtc->cursor_fg != fore || nv_crtc->cursor_bg != back) {
126 nv_crtc->cursor_fg = fore;
127 nv_crtc->cursor_bg = back;
128 nv_cursor_transform_cursor(pNv, nv_crtc);
129 }
130}
131
132void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
133{
134 NVPtr pNv = NVPTR(crtc->scrn);
135
136 /* save copy of image for colour changes */
137 memcpy(pNv->curImage, image, nv_cursor_pixels(pNv) / 4);
138
139 nv_cursor_transform_cursor(pNv, to_nouveau_crtc(crtc));
140}
141
142void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
143{
144 NVPtr pNv = NVPTR(crtc->scrn);
145 int head = to_nouveau_crtc(crtc)->head, i, alpha;
146 struct nouveau_bo *cursor = NULL;
147 uint32_t *dst, *src = (uint32_t *)image, tmp;
148
149 nouveau_bo_ref(head ? pNv->Cursor2 : pNv->Cursor, &cursor);
150 nouveau_bo_map(cursor, NOUVEAU_BO_WR);
151 dst = cursor->map;
152
153 /* nv11+ supports premultiplied (PM), or non-premultiplied (NPM) alpha
154 * cursors (though NPM in combination with fp dithering may not work on
155 * nv11, from "nv" driver history)
156 * NPM mode needs NV_PCRTC_CURSOR_CONFIG_ALPHA_BLEND set and is what the
157 * blob uses, however we get given PM cursors so we use PM mode
158 */
159 for (i = 0; i < nv_cursor_pixels(pNv); i++) {
160 /* hw gets unhappy if alpha <= rgb values. for a PM image "less
161 * than" shouldn't happen; fix "equal to" case by adding one to
162 * alpha channel (slightly inaccurate, but so is attempting to
163 * get back to NPM images, due to limits of integer precision)
164 */
165 alpha = (*src >> 24);
166 if (!alpha || alpha == 0xff)
167 /* alpha == max(r,g,b) works ok for 0x0 and 0xff */
168 tmp = *src;
169 else
170 tmp = ((alpha + 1) << 24) | (*src & 0xffffff);
171#if X_BYTE_ORDER == X_BIG_ENDIAN
172 if (pNv->NVArch == 0x11)
173 tmp = lswapl(tmp);
174#endif
175 *dst++ = tmp;
176 src++;
177 }
178
179 nouveau_bo_unmap(cursor);
180 nouveau_bo_ref(NULL, &cursor);
181}
182
183void nv_crtc_show_cursor(xf86CrtcPtr crtc)
184{
185 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
186
187 nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, true);
188}
189
190void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
191{
192 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
193
194 nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, false);
195}
196
197void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
198{
199 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
200 NVPtr pNv = NVPTR(crtc->scrn);
201
202 NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_CU_START_POS,
203 XLATE(y, 0, NV_PRAMDAC_CU_START_POS_Y) |
204 XLATE(x, 0, NV_PRAMDAC_CU_START_POS_X));
205}
206
207Bool NVCursorInitRandr12(ScreenPtr pScreen)
208{
209 NVPtr pNv = NVPTR(xf86Screens[pScreen->myNum]);
210 int width = nv_cursor_width(pNv);
211 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
212 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
213 (pNv->alphaCursor ? HARDWARE_CURSOR_ARGB : 0);
214
215 return xf86_cursors_init(pScreen, width, width, flags);
216}
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 @@
23 23
24#include <errno.h> 24#include <errno.h>
25#include "nv_include.h" 25#include "nv_include.h"
26#include "nvreg.h"
27 26
28static void 27static void
29NVLockedUp(ScrnInfoPtr pScrn) 28NVLockedUp(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 @@
27#include "xorg-server.h" 27#include "xorg-server.h"
28#include "xf86int10.h" 28#include "xf86int10.h"
29#include "xf86drm.h" 29#include "xf86drm.h"
30#ifdef XF86DRM_MODE
31#include "xf86drmMode.h" 30#include "xf86drmMode.h"
32#endif
33 31
34/* 32/*
35 * Forward definitions for the functions that make up the driver. 33 * Forward definitions for the functions that make up the driver.
@@ -55,8 +53,6 @@ static void NVFreeScreen(int scrnIndex, int flags);
55 53
56static Bool NVMapMem(ScrnInfoPtr pScrn); 54static Bool NVMapMem(ScrnInfoPtr pScrn);
57static Bool NVUnmapMem(ScrnInfoPtr pScrn); 55static Bool NVUnmapMem(ScrnInfoPtr pScrn);
58static void NVSave(ScrnInfoPtr pScrn);
59static void NVRestore(ScrnInfoPtr pScrn);
60 56
61#define NOUVEAU_PCI_DEVICE(_vendor_id, _device_id) \ 57#define NOUVEAU_PCI_DEVICE(_vendor_id, _device_id) \
62 { (_vendor_id), (_device_id), PCI_MATCH_ANY, PCI_MATCH_ANY, \ 58 { (_vendor_id), (_device_id), PCI_MATCH_ANY, PCI_MATCH_ANY, \
@@ -323,50 +319,8 @@ void
323NVAdjustFrame(int scrnIndex, int x, int y, int flags) 319NVAdjustFrame(int scrnIndex, int x, int y, int flags)
324{ 320{
325 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 321 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
326 NVPtr pNv = NVPTR(pScrn);
327
328 if (pNv->kms_enable) {
329 drmmode_adjust_frame(pScrn, x, y, flags);
330 } else {
331 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
332 xf86CrtcPtr crtc = config->output[config->compat_output]->crtc;
333
334 if (crtc && crtc->enabled)
335 NVCrtcSetBase(crtc, x, y);
336 }
337}
338 322
339static Bool 323 drmmode_adjust_frame(pScrn, x, y, flags);
340NV50AcquireDisplay(ScrnInfoPtr pScrn)
341{
342 if (!NV50DispInit(pScrn))
343 return FALSE;
344 if (!NV50CursorAcquire(pScrn))
345 return FALSE;
346
347 return TRUE;
348}
349
350static Bool
351NV50ReleaseDisplay(ScrnInfoPtr pScrn)
352{
353 NVPtr pNv = NVPTR(pScrn);
354
355 NV50CursorRelease(pScrn);
356 NV50DispShutdown(pScrn);
357
358 if (pNv->pInt10 && pNv->Int10Mode) {
359 xf86Int10InfoPtr pInt10 = pNv->pInt10;
360
361 pInt10->num = 0x10;
362 pInt10->ax = 0x4f02;
363 pInt10->bx = pNv->Int10Mode | 0x8000;
364 pInt10->cx =
365 pInt10->dx = 0;
366 xf86ExecX86int10(pInt10);
367 }
368
369 return TRUE;
370} 324}
371 325
372/* 326/*
@@ -393,23 +347,6 @@ NVEnterVT(int scrnIndex, int flags)
393 if (!pNv->NoAccel) 347 if (!pNv->NoAccel)
394 NVAccelCommonInit(pScrn); 348 NVAccelCommonInit(pScrn);
395 349
396 if (!pNv->kms_enable) {
397 /* Save current state, VGA fonts etc */
398 NVSave(pScrn);
399
400 /* Clear the framebuffer, we don't want to see garbage
401 * on-screen up until X decides to draw something
402 */
403 nouveau_bo_map(pNv->scanout, NOUVEAU_BO_WR);
404 memset(pNv->scanout->map, 0, pNv->scanout->size);
405 nouveau_bo_unmap(pNv->scanout);
406
407 if (pNv->Architecture == NV_ARCH_50) {
408 if (!NV50AcquireDisplay(pScrn))
409 return FALSE;
410 }
411 }
412
413 pNv->allow_dpms = FALSE; 350 pNv->allow_dpms = FALSE;
414 if (!xf86SetDesiredModes(pScrn)) 351 if (!xf86SetDesiredModes(pScrn))
415 return FALSE; 352 return FALSE;
@@ -443,13 +380,6 @@ NVLeaveVT(int scrnIndex, int flags)
443 ret = drmDropMaster(nouveau_device(pNv->dev)->fd); 380 ret = drmDropMaster(nouveau_device(pNv->dev)->fd);
444 if (ret) 381 if (ret)
445 ErrorF("Error dropping master: %d\n", ret); 382 ErrorF("Error dropping master: %d\n", ret);
446
447 if (!pNv->kms_enable) {
448 if (pNv->Architecture < NV_ARCH_50)
449 NVRestore(pScrn);
450 else
451 NV50ReleaseDisplay(pScrn);
452 }
453} 383}
454 384
455static void 385static void
@@ -577,97 +507,10 @@ NVFreeScreen(int scrnIndex, int flags)
577 507
578 NVCloseDRM(pScrn); 508 NVCloseDRM(pScrn);
579 509
580 if (pNv->Architecture == NV_ARCH_50 && !pNv->kms_enable) {
581 NV50ConnectorDestroy(pScrn);
582 NV50OutputDestroy(pScrn);
583 NV50CrtcDestroy(pScrn);
584 }
585
586 /* Free this here and not in CloseScreen, as it's needed after the first server generation. */
587 if (pNv->pInt10)
588 xf86FreeInt10(pNv->pInt10);
589
590 xfree(pScrn->driverPrivate); 510 xfree(pScrn->driverPrivate);
591 pScrn->driverPrivate = NULL; 511 pScrn->driverPrivate = NULL;
592} 512}
593 513
594static Bool
595nouveau_xf86crtc_resize(ScrnInfoPtr scrn, int width, int height)
596{
597 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
598 ScreenPtr screen = screenInfo.screens[scrn->scrnIndex];
599 NVPtr pNv = NVPTR(scrn);
600 uint32_t pitch, old_width, old_height, old_pitch;
601 struct nouveau_bo *old_bo = NULL;
602 uint32_t tile_mode = 0, tile_flags = 0, ah = height;
603 PixmapPtr ppix = screen->GetScreenPixmap(screen);
604 int ret, i;
605
606 ErrorF("resize called %d %d\n", width, height);
607
608 if (scrn->virtualX == width && scrn->virtualY == height)
609 return TRUE;
610
611 pitch = nv_pitch_align(pNv, width, scrn->depth);
612 pitch *= (scrn->bitsPerPixel >> 3);
613
614 old_width = scrn->virtualX;
615 old_height = scrn->virtualY;
616 old_pitch = scrn->displayWidth;
617 nouveau_bo_ref(pNv->scanout, &old_bo);
618 nouveau_bo_ref(NULL, &pNv->scanout);
619
620 scrn->virtualX = width;
621 scrn->virtualY = height;
622 scrn->displayWidth = pitch / (scrn->bitsPerPixel >> 3);
623
624 ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
625 0, pitch * ah, tile_mode, tile_flags,
626 &pNv->scanout);
627 if (ret)
628 goto fail;
629
630 if (pNv->ShadowPtr) {
631 xfree(pNv->ShadowPtr);
632 pNv->ShadowPitch = pitch;
633 pNv->ShadowPtr = xalloc(pNv->ShadowPitch * height);
634 }
635
636 nouveau_bo_map(pNv->scanout, NOUVEAU_BO_RDWR);
637 screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch,
638 (!pNv->NoAccel || pNv->ShadowFB) ?
639 pNv->ShadowPtr : pNv->scanout->map);
640 scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
641 nouveau_bo_unmap(pNv->scanout);
642
643 for (i = 0; i < xf86_config->num_crtc; i++) {
644 xf86CrtcPtr crtc = xf86_config->crtc[i];
645
646 if (!crtc->enabled)
647 continue;
648
649 xf86CrtcSetMode(crtc, &crtc->mode, crtc->rotation,
650 crtc->x, crtc->y);
651 }
652
653 nouveau_bo_ref(NULL, &old_bo);
654
655 NVDRIFinishScreenInit(scrn, true);
656 return TRUE;
657
658 fail:
659 nouveau_bo_ref(old_bo, &pNv->scanout);
660 scrn->virtualX = old_width;
661 scrn->virtualY = old_height;
662 scrn->displayWidth = old_pitch;
663
664 return FALSE;
665}
666
667static const xf86CrtcConfigFuncsRec nv_xf86crtc_config_funcs = {
668 nouveau_xf86crtc_resize
669};
670
671#define NVPreInitFail(fmt, args...) do { \ 514#define NVPreInitFail(fmt, args...) do { \
672 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%d: "fmt, __LINE__, ##args); \ 515 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "%d: "fmt, __LINE__, ##args); \
673 NVFreeScreen(pScrn->scrnIndex, 0); \ 516 NVFreeScreen(pScrn->scrnIndex, 0); \
@@ -736,14 +579,14 @@ NVPreInitDRM(ScrnInfoPtr pScrn)
736 /* Check if KMS is enabled before we do anything, we don't want to 579 /* Check if KMS is enabled before we do anything, we don't want to
737 * go stomping on registers behind its back 580 * go stomping on registers behind its back
738 */ 581 */
739#ifdef XF86DRM_MODE 582 if (drmCheckModesettingSupported(bus_id)) {
740 pNv->kms_enable = !drmCheckModesettingSupported(bus_id); 583 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
741#endif 584 "[drm] kernel modesetting not available\n");
742 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 585 xfree(bus_id);
743 "[drm] kernel modesetting %s\n", pNv->kms_enable ? 586 return FALSE;
744 "in use" : "not available"); 587 }
745
746 xfree(bus_id); 588 xfree(bus_id);
589
747 return TRUE; 590 return TRUE;
748} 591}
749 592
@@ -852,35 +695,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
852 return FALSE; 695 return FALSE;
853 } 696 }
854 697
855 /* Initialize the card through int10 interface if needed */
856 if (xf86LoadSubModule(pScrn, "int10")) {
857#if !defined(__alpha__) && !defined(__powerpc__)
858 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Initializing int10\n");
859 pNv->pInt10 = xf86InitInt10(pNv->pEnt->index);
860#endif
861 }
862
863 /* Initialise the kernel module */ 698 /* Initialise the kernel module */
864 if (!NVPreInitDRM(pScrn)) 699 if (!NVPreInitDRM(pScrn))
865 NVPreInitFail("\n"); 700 NVPreInitFail("\n");
866 701
867 /* Save current console video mode */
868 if (pNv->Architecture >= NV_ARCH_50 && pNv->pInt10 && !pNv->kms_enable) {
869 const xf86Int10InfoPtr pInt10 = pNv->pInt10;
870
871 pInt10->num = 0x10;
872 pInt10->ax = 0x4f03;
873 pInt10->bx =
874 pInt10->cx =
875 pInt10->dx = 0;
876 xf86ExecX86int10(pInt10);
877 pNv->Int10Mode = pInt10->bx & 0x3fff;
878
879 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
880 "VESA-HACK: Console VGA mode is 0x%x\n",
881 pNv->Int10Mode);
882 }
883
884 /* Set pScrn->monitor */ 702 /* Set pScrn->monitor */
885 pScrn->monitor = pScrn->confScreen->monitor; 703 pScrn->monitor = pScrn->confScreen->monitor;
886 704
@@ -899,8 +717,8 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
899 break; 717 break;
900 case 30: 718 case 30:
901 /* OK on NV50 KMS */ 719 /* OK on NV50 KMS */
902 if (!pNv->kms_enable || pNv->Architecture != NV_ARCH_50) 720 if (pNv->Architecture != NV_ARCH_50)
903 NVPreInitFail("Depth 30 supported on G80+KMS only\n"); 721 NVPreInitFail("Depth 30 supported on G80 only\n");
904 break; 722 break;
905 case 15: /* 15 may get done one day, so leave any code for it in place */ 723 case 15: /* 15 may get done one day, so leave any code for it in place */
906 default: 724 default:
@@ -978,13 +796,6 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
978 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 796 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
979 pNv->HWCursor ? "HW" : "SW"); 797 pNv->HWCursor ? "HW" : "SW");
980 798
981 pNv->FpScale = TRUE;
982
983 if (xf86GetOptValBool(pNv->Options, OPTION_FP_SCALE, &pNv->FpScale)) {
984 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Flat panel scaling %s\n",
985 pNv->FpScale ? "on" : "off");
986 }
987
988 if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) { 799 if (xf86ReturnOptValBool(pNv->Options, OPTION_NOACCEL, FALSE)) {
989 pNv->NoAccel = TRUE; 800 pNv->NoAccel = TRUE;
990 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 801 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
@@ -1000,16 +811,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
1000#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5) || EXA_VERSION_MAJOR > 2 811#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 5) || EXA_VERSION_MAJOR > 2
1001 if (!pNv->NoAccel && 812 if (!pNv->NoAccel &&
1002 xf86ReturnOptValBool(pNv->Options, OPTION_EXA_PIXMAPS, TRUE)) { 813 xf86ReturnOptValBool(pNv->Options, OPTION_EXA_PIXMAPS, TRUE)) {
1003 if (pNv->kms_enable) { 814 pNv->exa_driver_pixmaps = TRUE;
1004 pNv->exa_driver_pixmaps = TRUE;
1005 } else {
1006 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1007 "EXAPixmaps support requires KMS\n");
1008 }
1009 } 815 }
1010 816
1011 if (!pNv->NoAccel && pNv->kms_enable && 817 if (!pNv->NoAccel && pNv->Architecture >= NV_ARCH_50) {
1012 pNv->Architecture >= NV_ARCH_50) {
1013 pNv->wfb_enabled = TRUE; 818 pNv->wfb_enabled = TRUE;
1014 pNv->tiled_scanout = TRUE; 819 pNv->tiled_scanout = TRUE;
1015 } 820 }
@@ -1024,113 +829,10 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
1024 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 829 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue);
1025 } 830 }
1026 831
1027 pNv->FPDither = FALSE; 832 ret = drmmode_pre_init(pScrn, nouveau_device(pNv->dev)->fd,
1028 if (xf86GetOptValBool(pNv->Options, OPTION_FP_DITHER, &(pNv->FPDither))) 833 pScrn->bitsPerPixel >> 3);
1029 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "enabling flat panel dither\n"); 834 if (ret == FALSE)
1030 835 NVPreInitFail("Kernel modesetting failed to initialize\n");
1031 if (pNv->pEnt->device->MemBase != 0) {
1032 /* Require that the config file value matches one of the PCI values. */
1033 if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->MemBase)) {
1034 NVPreInitFail(
1035 "MemBase 0x%08lX doesn't match any PCI base register.\n",
1036 pNv->pEnt->device->MemBase);
1037 }
1038 pNv->VRAMPhysical = pNv->pEnt->device->MemBase;
1039 from = X_CONFIG;
1040 } else {
1041 if (pNv->PciInfo->regions[1].base_addr != 0) {
1042 pNv->VRAMPhysical = pNv->PciInfo->regions[1].base_addr & 0xff800000;
1043 from = X_PROBED;
1044 } else {
1045 NVPreInitFail("No valid FB address in PCI config space\n");
1046 return FALSE;
1047 }
1048 }
1049 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
1050 (unsigned long)pNv->VRAMPhysical);
1051
1052 if (pNv->pEnt->device->IOBase != 0) {
1053 /* Require that the config file value matches one of the PCI values. */
1054 if (!xf86CheckPciMemBase(pNv->PciInfo, pNv->pEnt->device->IOBase)) {
1055 NVPreInitFail("IOBase 0x%08lX doesn't match any PCI base register.\n",
1056 pNv->pEnt->device->IOBase);
1057 }
1058 pNv->IOAddress = pNv->pEnt->device->IOBase;
1059 from = X_CONFIG;
1060 } else {
1061 if (pNv->PciInfo->regions[0].base_addr != 0) {
1062 pNv->IOAddress = pNv->PciInfo->regions[0].base_addr & 0xffffc000;
1063 from = X_PROBED;
1064 } else {
1065 NVPreInitFail("No valid MMIO address in PCI config space\n");
1066 }
1067 }
1068 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n",
1069 (unsigned long)pNv->IOAddress);
1070
1071#ifdef XF86DRM_MODE
1072 if (pNv->kms_enable){
1073 ret = drmmode_pre_init(pScrn, nouveau_device(pNv->dev)->fd,
1074 pScrn->bitsPerPixel >> 3);
1075 if (ret == FALSE)
1076 NVPreInitFail("Kernel modesetting failed to initialize\n");
1077 } else
1078#endif
1079 {
1080 int max_width, max_height;
1081
1082 if (pNv->Architecture < NV_ARCH_10) {
1083 max_width = (pScrn->bitsPerPixel > 16) ? 2032 : 2048;
1084 max_height = 2048;
1085 } else if (pNv->Architecture < NV_ARCH_50) {
1086 max_width = (pScrn->bitsPerPixel > 16) ? 4080 : 4096;
1087 max_height = 4096;
1088 } else {
1089 max_width = (pScrn->bitsPerPixel > 16) ? 8176 : 8192;
1090 max_height = 8192;
1091 }
1092
1093 /* Allocate an xf86CrtcConfig */
1094 xf86CrtcConfigInit(pScrn, &nv_xf86crtc_config_funcs);
1095 xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height);
1096 }
1097
1098 NVCommonSetup(pScrn);
1099
1100 if (!pNv->kms_enable) {
1101 if (pNv->Architecture == NV_ARCH_50)
1102 if (!NV50DispPreInit(pScrn))
1103 NVPreInitFail("\n");
1104
1105 /* This is the internal system, not the randr-1.2 ones. */
1106 if (pNv->Architecture == NV_ARCH_50) {
1107 NV50CrtcInit(pScrn);
1108 NV50ConnectorInit(pScrn);
1109 NV50OutputSetup(pScrn);
1110 }
1111
1112 for (i = 0; i <= pNv->twoHeads; i++) {
1113 if (pNv->Architecture == NV_ARCH_50)
1114 nv50_crtc_init(pScrn, i);
1115 else
1116 nv_crtc_init(pScrn, i);
1117 }
1118
1119 if (pNv->Architecture < NV_ARCH_50) {
1120 NVLockVgaCrtcs(pNv, false);
1121 NvSetupOutputs(pScrn);
1122 } else
1123 nv50_output_create(pScrn); /* create randr-1.2 "outputs". */
1124
1125 if (!xf86InitialConfiguration(pScrn, TRUE))
1126 NVPreInitFail("No valid modes.\n");
1127 }
1128
1129 pScrn->videoRam = pNv->RamAmountKBytes;
1130 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kBytes\n",
1131 pScrn->videoRam);
1132
1133 pNv->VRAMPhysicalSize = pScrn->videoRam * 1024;
1134 836
1135 /* 837 /*
1136 * If the driver can do gamma correction, it should call xf86SetGamma() 838 * If the driver can do gamma correction, it should call xf86SetGamma()
@@ -1187,16 +889,13 @@ static Bool
1187NVMapMem(ScrnInfoPtr pScrn) 889NVMapMem(ScrnInfoPtr pScrn)
1188{ 890{
1189 NVPtr pNv = NVPTR(pScrn); 891 NVPtr pNv = NVPTR(pScrn);
892 struct nouveau_device *dev = pNv->dev;
1190 uint64_t res; 893 uint64_t res;
1191 uint32_t tile_mode = 0, tile_flags = 0; 894 uint32_t tile_mode = 0, tile_flags = 0;
1192 int ret, size; 895 int ret, size;
1193 896
1194 nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_FB_SIZE, &res); 897 nouveau_device_get_param(dev, NOUVEAU_GETPARAM_FB_PHYSICAL, &res);
1195 pNv->VRAMSize=res;
1196 nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_FB_PHYSICAL, &res);
1197 pNv->VRAMPhysical=res; 898 pNv->VRAMPhysical=res;
1198 nouveau_device_get_param(pNv->dev, NOUVEAU_GETPARAM_AGP_SIZE, &res);
1199 pNv->AGPSize=res;
1200 899
1201 size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); 900 size = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3);
1202 if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) { 901 if (pNv->Architecture >= NV_ARCH_50 && pNv->tiled_scanout) {
@@ -1207,7 +906,7 @@ NVMapMem(ScrnInfoPtr pScrn)
1207 size *= pScrn->virtualY; 906 size *= pScrn->virtualY;
1208 } 907 }
1209 908
1210 ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 909 ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP,
1211 0, size, tile_mode, tile_flags, 910 0, size, tile_mode, tile_flags,
1212 &pNv->scanout); 911 &pNv->scanout);
1213 if (ret) { 912 if (ret) {
@@ -1220,17 +919,17 @@ NVMapMem(ScrnInfoPtr pScrn)
1220 nouveau_bo_unmap(pNv->scanout); 919 nouveau_bo_unmap(pNv->scanout);
1221 920
1222 if (pNv->NoAccel) 921 if (pNv->NoAccel)
1223 goto skip_offscreen_gart; 922 return TRUE;
1224 923
1225 if (!pNv->exa_driver_pixmaps) { 924 if (!pNv->exa_driver_pixmaps) {
1226 size = (pNv->VRAMPhysicalSize / 2) - size; 925 size = (dev->vm_vram_size / 2) - size;
1227 926
1228 if (pNv->Architecture >= NV_ARCH_50) { 927 if (pNv->Architecture >= NV_ARCH_50) {
1229 tile_mode = 0; 928 tile_mode = 0;
1230 tile_flags = 0x7000; 929 tile_flags = 0x7000;
1231 } 930 }
1232 931
1233 ret = nouveau_bo_new_tile(pNv->dev, NOUVEAU_BO_VRAM | 932 ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM |
1234 NOUVEAU_BO_MAP, 0, size, tile_mode, 933 NOUVEAU_BO_MAP, 0, size, tile_mode,
1235 tile_flags, &pNv->offscreen); 934 tile_flags, &pNv->offscreen);
1236 if (ret) { 935 if (ret) {
@@ -1248,22 +947,16 @@ NVMapMem(ScrnInfoPtr pScrn)
1248 nouveau_bo_unmap(pNv->offscreen); 947 nouveau_bo_unmap(pNv->offscreen);
1249 } 948 }
1250 949
1251 if (pNv->AGPSize) {
1252 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1253 "AGPGART: %dMiB available\n",
1254 (unsigned int)(pNv->AGPSize >> 20));
1255 if (pNv->AGPSize > (16*1024*1024))
1256 size = 16*1024*1024;
1257 else
1258 /* always leave 512kb for other things like the fifos */
1259 size = pNv->AGPSize - 512*1024;
1260 } else {
1261 size = (4 << 20) - (1 << 18) ;
1262 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1263 "GART: PCI DMA - using %dKiB\n", size >> 10);
1264 }
1265 950
1266 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 951 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: %dMiB available\n",
952 (unsigned int)(dev->vm_gart_size >> 20));
953 if (dev->vm_gart_size > (16 * 1024 * 1024))
954 size = 16 * 1024 * 1024;
955 else
956 /* always leave 512kb for other things like the fifos */
957 size = dev->vm_gart_size - 512*1024;
958
959 if (nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
1267 0, size, &pNv->GART)) { 960 0, size, &pNv->GART)) {
1268 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 961 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1269 "Unable to allocate GART memory\n"); 962 "Unable to allocate GART memory\n");
@@ -1274,56 +967,6 @@ NVMapMem(ScrnInfoPtr pScrn)
1274 (unsigned int)(pNv->GART->size >> 20)); 967 (unsigned int)(pNv->GART->size >> 20));
1275 } 968 }
1276 969
1277skip_offscreen_gart:
1278 /* We don't need to allocate cursors / lut here if we're using
1279 * kernel modesetting
1280 **/
1281 if (pNv->kms_enable)
1282 return TRUE;
1283
1284 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN |
1285 NOUVEAU_BO_MAP, 0, 64 * 64 * 4, &pNv->Cursor)) {
1286 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1287 "Failed to allocate memory for hardware cursor\n");
1288 return FALSE;
1289 }
1290
1291 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_PIN |
1292 NOUVEAU_BO_MAP, 0, 64 * 64 * 4, &pNv->Cursor2)) {
1293 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1294 "Failed to allocate memory for hardware cursor\n");
1295 return FALSE;
1296 }
1297
1298 /* This is not the ideal solution, but significant changes are needed
1299 * otherwise. Ideally you do this once upon preinit, but drm is
1300 * closed between screen inits.
1301 */
1302 if (pNv->Architecture == NV_ARCH_50) {
1303 int i;
1304
1305 for(i = 0; i < 2; i++) {
1306 nouveauCrtcPtr crtc = pNv->crtc[i];
1307
1308 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM |
1309 NOUVEAU_BO_PIN |
1310 NOUVEAU_BO_MAP, 0, 0x1000,
1311 &crtc->lut)) {
1312 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1313 "Failed to allocate memory for lut %d\n", i);
1314 return FALSE;
1315 }
1316
1317 /* Copy the last known values. */
1318 if (crtc->lut_values_valid) {
1319 nouveau_bo_map(crtc->lut, NOUVEAU_BO_WR);
1320 memcpy(crtc->lut->map, crtc->lut_values,
1321 4 * 256 * sizeof(uint16_t));
1322 nouveau_bo_unmap(crtc->lut);
1323 }
1324 }
1325 }
1326
1327 return TRUE; 970 return TRUE;
1328} 971}
1329 972
@@ -1336,67 +979,14 @@ NVUnmapMem(ScrnInfoPtr pScrn)
1336{ 979{
1337 NVPtr pNv = NVPTR(pScrn); 980 NVPtr pNv = NVPTR(pScrn);
1338 981
1339 if (!pNv->dev) { 982 drmmode_remove_fb(pScrn);
1340 pci_device_unmap_range(pNv->PciInfo, pNv->VRAMMap,
1341 pNv->PciInfo->regions[1].size);
1342 }
1343 983
1344#ifdef XF86DRM_MODE
1345 if (pNv->kms_enable)
1346 drmmode_remove_fb(pScrn);
1347#endif
1348 nouveau_bo_ref(NULL, &pNv->scanout); 984 nouveau_bo_ref(NULL, &pNv->scanout);
1349 nouveau_bo_ref(NULL, &pNv->offscreen); 985 nouveau_bo_ref(NULL, &pNv->offscreen);
1350 nouveau_bo_ref(NULL, &pNv->GART); 986 nouveau_bo_ref(NULL, &pNv->GART);
1351 nouveau_bo_ref(NULL, &pNv->Cursor);
1352 nouveau_bo_ref(NULL, &pNv->Cursor2);
1353
1354 /* Again not the most ideal way. */
1355 if (pNv->Architecture == NV_ARCH_50 && !pNv->kms_enable) {
1356 int i;
1357
1358 for(i = 0; i < 2; i++) {
1359 nouveauCrtcPtr crtc = pNv->crtc[i];
1360
1361 nouveau_bo_ref(NULL, &crtc->lut);
1362 }
1363 }
1364
1365 return TRUE; 987 return TRUE;
1366} 988}
1367 989
1368
1369/*
1370 * Restore the initial (text) mode.
1371 */
1372static void
1373NVRestore(ScrnInfoPtr pScrn)
1374{
1375 NVPtr pNv = NVPTR(pScrn);
1376
1377 NVLockVgaCrtcs(pNv, false);
1378
1379 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1380 int i;
1381
1382 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring encoders\n");
1383 for (i = 0; i < pNv->vbios->dcb->entries; i++)
1384 nv_encoder_restore(pScrn, &pNv->encoders[i]);
1385
1386 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring crtcs\n");
1387 for (i = 0; i < xf86_config->num_crtc; i++)
1388 xf86_config->crtc[i]->funcs->restore(xf86_config->crtc[i]);
1389
1390 nouveau_hw_save_vga_fonts(pScrn, 0);
1391
1392 if (pNv->twoHeads) {
1393 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Restoring CRTC_OWNER to %d.\n", pNv->vtOWNER);
1394 NVSetOwner(pNv, pNv->vtOWNER);
1395 }
1396
1397 NVLockVgaCrtcs(pNv, true);
1398}
1399
1400static void 990static void
1401NVLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 991NVLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
1402 LOCO * colors, VisualPtr pVisual) 992 LOCO * colors, VisualPtr pVisual)
@@ -1504,9 +1094,6 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1504 for (i = 0; i < xf86_config->num_output; i++) 1094 for (i = 0; i < xf86_config->num_output; i++)
1505 xf86_config->output[i]->scrn = pScrn; 1095 xf86_config->output[i]->scrn = pScrn;
1506 1096
1507 if (!pNv->kms_enable)
1508 NVSave(pScrn);
1509
1510 /* 1097 /*
1511 * The next step is to setup the screen's visuals, and initialise the 1098 * The next step is to setup the screen's visuals, and initialise the
1512 * framebuffer code. In cases where the framebuffer's default 1099 * framebuffer code. In cases where the framebuffer's default
@@ -1601,14 +1188,8 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1601 1188
1602 xf86SetBlackWhitePixels(pScreen); 1189 xf86SetBlackWhitePixels(pScreen);
1603 1190
1604 if (!pNv->NoAccel) { 1191 if (!pNv->NoAccel && !nouveau_exa_init(pScreen))
1605 if (!nouveau_exa_init(pScreen))
1606 return FALSE;
1607 } else if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) {
1608 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n");
1609 return FALSE; 1192 return FALSE;
1610 }
1611
1612 1193
1613 miInitializeBackingStore(pScreen); 1194 miInitializeBackingStore(pScreen);
1614 xf86SetBackingStore(pScreen); 1195 xf86SetBackingStore(pScreen);
@@ -1632,17 +1213,10 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1632 * Must follow software cursor initialization. 1213 * Must follow software cursor initialization.
1633 */ 1214 */
1634 if (pNv->HWCursor) { 1215 if (pNv->HWCursor) {
1635 if (pNv->kms_enable) 1216 ret = drmmode_cursor_init(pScreen);
1636 ret = drmmode_cursor_init(pScreen);
1637 else
1638 if (pNv->Architecture < NV_ARCH_50)
1639 ret = NVCursorInitRandr12(pScreen);
1640 else
1641 ret = NV50CursorInit(pScreen);
1642
1643 if (ret != TRUE) { 1217 if (ret != TRUE) {
1644 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1218 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1645 "Hardware cursor initialization failed\n"); 1219 "Hardware cursor initialization failed\n");
1646 pNv->HWCursor = FALSE; 1220 pNv->HWCursor = FALSE;
1647 } 1221 }
1648 } 1222 }
@@ -1665,8 +1239,7 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1665 1239
1666 pScrn->vtSema = TRUE; 1240 pScrn->vtSema = TRUE;
1667 pScrn->pScreen = pScreen; 1241 pScrn->pScreen = pScreen;
1668 if (pNv->kms_enable) 1242 drmmode_fbcon_copy(pScrn);
1669 drmmode_fbcon_copy(pScrn);
1670 1243
1671 if (!NVEnterVT(pScrn->scrnIndex, 0)) 1244 if (!NVEnterVT(pScrn->scrnIndex, 0))
1672 return FALSE; 1245 return FALSE;
@@ -1705,44 +1278,6 @@ NVScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1705static Bool 1278static Bool
1706NVSaveScreen(ScreenPtr pScreen, int mode) 1279NVSaveScreen(ScreenPtr pScreen, int mode)
1707{ 1280{
1708 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1709 NVPtr pNv = NVPTR(pScrn);
1710 bool on = xf86IsUnblank(mode);
1711 int i;
1712
1713 if (pScrn->vtSema && pNv->Architecture < NV_ARCH_50) {
1714 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1715
1716 for (i = 0; i < xf86_config->num_crtc; i++) {
1717 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(xf86_config->crtc[i]);
1718
1719 if (xf86_config->crtc[i]->enabled)
1720 NVBlankScreen(pNv, nv_crtc->head, !on);
1721 }
1722 }
1723
1724 return TRUE; 1281 return TRUE;
1725} 1282}
1726 1283
1727static void
1728NVSave(ScrnInfoPtr pScrn)
1729{
1730 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1731 NVPtr pNv = NVPTR(pScrn);
1732 int i;
1733
1734 if (pNv->Architecture == NV_ARCH_50)
1735 return;
1736
1737 NVLockVgaCrtcs(pNv, false);
1738
1739 nouveau_hw_save_vga_fonts(pScrn, 1);
1740
1741 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Saving crtcs\n");
1742 for (i = 0; i < xf86_config->num_crtc; i++)
1743 xf86_config->crtc[i]->funcs->save(xf86_config->crtc[i]);
1744
1745 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Saving encoders\n");
1746 for (i = 0; i < pNv->vbios->dcb->entries; i++)
1747 nv_encoder_save(pScrn, &pNv->encoders[i]);
1748}
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 @@
1/*
2 * Copyright 2006 Stephane Marchesin
3 * Copyright 2007 Maarten Maathuis
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "nv_include.h"
25
26/*
27 * DDC1 support only requires DDC_SDA_MASK,
28 * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
29 */
30#define DDC_SDA_READ_MASK (1 << 3)
31#define DDC_SCL_READ_MASK (1 << 2)
32#define DDC_SDA_WRITE_MASK (1 << 4)
33#define DDC_SCL_WRITE_MASK (1 << 5)
34
35static void
36NVI2CGetBits(I2CBusPtr b, int *clock, int *data)
37{
38 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
39 struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr;
40 unsigned char val;
41
42 /* Get the result. */
43 /* Doing this on head 0 seems fine. */
44 if (dcb_i2c->port_type == 4) /* C51 */
45 val = NVReadCRTC(pNv, 0, 0x600800 + dcb_i2c->read) >> 16;
46 else
47 val = NVReadVgaCrtc(pNv, 0, dcb_i2c->read);
48
49 *clock = (val & DDC_SCL_READ_MASK) != 0;
50 *data = (val & DDC_SDA_READ_MASK) != 0;
51}
52
53static void
54NVI2CPutBits(I2CBusPtr b, int clock, int data)
55{
56 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
57 struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr;
58 uint32_t val;
59
60 /* Doing this on head 0 seems fine. */
61 if (dcb_i2c->port_type == 4) /* C51 */
62 val = NVReadCRTC(pNv, 0, 0x600800 + dcb_i2c->write);
63 else
64 val = NVReadVgaCrtc(pNv, 0, dcb_i2c->write);
65
66 val = (val & ~0xf) | 1;
67
68 if (clock)
69 val |= DDC_SCL_WRITE_MASK;
70 else
71 val &= ~DDC_SCL_WRITE_MASK;
72
73 if (data)
74 val |= DDC_SDA_WRITE_MASK;
75 else
76 val &= ~DDC_SDA_WRITE_MASK;
77
78 /* Doing this on head 0 seems fine. */
79 if (dcb_i2c->port_type == 4) /* C51 */
80 NVWriteCRTC(pNv, 0, 0x600800 + dcb_i2c->write, val);
81 else
82 NVWriteVgaCrtc(pNv, 0, dcb_i2c->write, val);
83}
84
85static uint32_t NV50_GetI2CPort(ScrnInfoPtr pScrn, int index)
86{
87 NVPtr pNv = NVPTR(pScrn);
88
89 if (index <= 3)
90 return 0xe138 + (index * 24);
91
92 /* I have my doubts that this is 100% correct everywhere,
93 * but this is the best guess based on the data we have.
94 */
95 if (pNv->NVArch >= 0x90) /* 0x90, 0xA0 */
96 return 0xe1d4 + (index * 32);
97 return 0xe1e0 + (index * 24);
98}
99
100static void NV50_I2CPutBits(I2CBusPtr b, int clock, int data)
101{
102 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
103 struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr;
104
105 NVWrite(pNv, NV50_GetI2CPort(xf86Screens[b->scrnIndex], dcb_i2c->write), (4 | clock | data << 1));
106}
107
108static void NV50_I2CGetBits(I2CBusPtr b, int *clock, int *data)
109{
110 NVPtr pNv = NVPTR(xf86Screens[b->scrnIndex]);
111 struct dcb_i2c_entry *dcb_i2c = b->DriverPrivate.ptr;
112 unsigned char val;
113
114 val = NVRead(pNv, NV50_GetI2CPort(xf86Screens[b->scrnIndex], dcb_i2c->read));
115 *clock = !!(val & 1);
116 *data = !!(val & 2);
117}
118
119int
120NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, struct dcb_i2c_entry *dcb_i2c, char *name)
121{
122 I2CBusPtr pI2CBus;
123
124 if (dcb_i2c->chan)
125 goto initialized;
126
127 if (!(pI2CBus = xf86CreateI2CBusRec()))
128 return -ENOMEM;
129
130 pI2CBus->BusName = name;
131 pI2CBus->scrnIndex = pScrn->scrnIndex;
132 if (dcb_i2c->port_type == 5) { /* NV50 */
133 pI2CBus->I2CPutBits = NV50_I2CPutBits;
134 pI2CBus->I2CGetBits = NV50_I2CGetBits;
135 /* Could this be used for the rest as well? */
136 pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
137 pI2CBus->StartTimeout = 550;
138 pI2CBus->BitTimeout = 40;
139 pI2CBus->ByteTimeout = 40;
140 pI2CBus->AcknTimeout = 40;
141 } else {
142 pI2CBus->I2CPutBits = NVI2CPutBits;
143 pI2CBus->I2CGetBits = NVI2CGetBits;
144 pI2CBus->AcknTimeout = 5;
145 }
146 pI2CBus->DriverPrivate.ptr = dcb_i2c;
147
148 if (!xf86I2CBusInit(pI2CBus))
149 return -EINVAL;
150
151 dcb_i2c->chan = pI2CBus;
152
153initialized:
154 *bus_ptr = dcb_i2c->chan;
155
156 return 0;
157}
158
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 @@
71#include "nv_local.h" 71#include "nv_local.h"
72#include "nv_type.h" 72#include "nv_type.h"
73#include "nv_proto.h" 73#include "nv_proto.h"
74#include "nouveau_hw.h"
75#include "nv_dma.h" 74#include "nv_dma.h"
76#include "nouveau_drm.h" 75#include "nouveau_drm.h"
77#include "nouveau_class.h" 76#include "nouveau_class.h"
78#include "nvreg.h"
79#include "nv50reg.h"
80#include "sarea.h" 77#include "sarea.h"
81 78
82#include "nouveau_drmif.h" 79#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 @@
1/*
2 * Copyright 2003 NVIDIA, Corporation
3 * Copyright 2006 Dave Airlie
4 * Copyright 2007 Maarten Maathuis
5 * Copyright 2007-2009 Stuart Bennett
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26
27#include <X11/Xatom.h>
28#include <X11/Xos.h> /* X_GETTIMEOFDAY */
29#include "nv_include.h"
30
31#define MULTIPLE_ENCODERS(e) (e & (e - 1))
32#define FOR_EACH_ENCODER_IN_CONNECTOR(i, c, e) for (i = 0; i < pNv->vbios->dcb->entries; i++) \
33 if (c->possible_encoders & (1 << i) && \
34 (e = &pNv->encoders[i]))
35
36static int nv_output_ramdac_offset(struct nouveau_encoder *nv_encoder)
37{
38 int offset = 0;
39
40 if (nv_encoder->dcb->or & (8 | OUTPUT_C))
41 offset += 0x68;
42 if (nv_encoder->dcb->or & (8 | OUTPUT_B))
43 offset += 0x2000;
44
45 return offset;
46}
47
48static int nv_get_digital_bound_head(NVPtr pNv, int or)
49{
50 /* special case of nv_read_tmds to find crtc associated with an output.
51 * this does not give a correct answer for off-chip dvi, but there's no
52 * use for such an answer anyway
53 */
54 int ramdac = (or & OUTPUT_C) >> 2;
55
56 NVWriteRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_CONTROL,
57 NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE | 0x4);
58 return (((NVReadRAMDAC(pNv, ramdac, NV_PRAMDAC_FP_TMDS_DATA) & 0x8) >> 3) ^ ramdac);
59}
60
61#define WAIT_FOR(cond, timeout_us) __extension__ ({ \
62 struct timeval begin, cur; \
63 long d_secs, d_usecs, diff = 0; \
64 \
65 X_GETTIMEOFDAY(&begin); \
66 while (!(cond) && diff < timeout_us) { \
67 X_GETTIMEOFDAY(&cur); \
68 d_secs = cur.tv_sec - begin.tv_sec; \
69 d_usecs = cur.tv_usec - begin.tv_usec; \
70 diff = d_secs * 1000000 + d_usecs; \
71 }; \
72 diff >= timeout_us ? -EAGAIN : 0; \
73})
74
75/*
76 * arbitrary limit to number of sense oscillations tolerated in one sample
77 * period (observed to be at least 13 in "nvidia")
78 */
79#define MAX_HBLANK_OSC 20
80
81/*
82 * arbitrary limit to number of conflicting sample pairs to tolerate at a
83 * voltage step (observed to be at least 5 in "nvidia")
84 */
85#define MAX_SAMPLE_PAIRS 10
86
87static int sample_load_twice(NVPtr pNv, bool sense[2])
88{
89 int i;
90
91 for (i = 0; i < 2; i++) {
92 bool sense_a, sense_b, sense_b_prime;
93 int j = 0;
94
95 /*
96 * wait for bit 0 clear -- out of hblank -- (say reg value 0x4),
97 * then wait for transition 0x4->0x5->0x4: enter hblank, leave
98 * hblank again
99 * use a 10ms timeout (guards against crtc being inactive, in
100 * which case blank state would never change)
101 */
102 if (WAIT_FOR(!(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1), 10000))
103 return -EWOULDBLOCK;
104 if (WAIT_FOR(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1, 10000))
105 return -EWOULDBLOCK;
106 if (WAIT_FOR(!(VGA_RD08(pNv->REGS, NV_PRMCIO_INP0__COLOR) & 1), 10000))
107 return -EWOULDBLOCK;
108
109 WAIT_FOR(0, 100); /* faster than usleep(100) */
110 /* when level triggers, sense is _LO_ */
111 sense_a = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10;
112
113 /* take another reading until it agrees with sense_a... */
114 do {
115 WAIT_FOR(0, 100);
116 sense_b = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10;
117 if (sense_a != sense_b) {
118 sense_b_prime = VGA_RD08(pNv->REGS, NV_PRMCIO_INP0) & 0x10;
119 if (sense_b == sense_b_prime) {
120 /* ... unless two consecutive subsequent
121 * samples agree; sense_a is replaced */
122 sense_a = sense_b;
123 /* force mis-match so we loop */
124 sense_b = !sense_a;
125 }
126 }
127 } while ((sense_a != sense_b) && ++j < MAX_HBLANK_OSC);
128
129 if (j == MAX_HBLANK_OSC)
130 /* with so much oscillation, default to sense:LO */
131 sense[i] = false;
132 else
133 sense[i] = sense_a;
134 }
135
136 return 0;
137}
138
139static bool nv_legacy_load_detect(ScrnInfoPtr pScrn)
140{
141 NVPtr pNv = NVPTR(pScrn);
142 uint8_t saved_seq1, saved_pi, saved_rpc1;
143 uint8_t saved_palette0[3], saved_palette_mask;
144 uint32_t saved_rtest_ctrl, saved_rgen_ctrl;
145 int i;
146 uint8_t blue;
147 bool sense = true;
148
149 /*
150 * for this detection to work, there needs to be a mode set up on the
151 * CRTC. this is presumed to be the case
152 */
153
154 if (pNv->twoHeads)
155 /* only implemented for head A for now */
156 NVSetOwner(pNv, 0);
157
158 saved_seq1 = NVReadVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX);
159 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1 & ~0x20);
160
161 saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL);
162 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL,
163 saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
164
165 usleep(10000);
166
167 saved_pi = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX);
168 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX,
169 saved_pi & ~(0x80 | MASK(NV_CIO_CRE_PIXEL_FORMAT)));
170 saved_rpc1 = NVReadVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX);
171 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0);
172
173 VGA_WR08(pNv->REGS, NV_PRMDIO_READ_MODE_ADDRESS, 0x0);
174 for (i = 0; i < 3; i++)
175 saved_palette0[i] = NV_RD08(pNv->REGS, NV_PRMDIO_PALETTE_DATA);
176 saved_palette_mask = NV_RD08(pNv->REGS, NV_PRMDIO_PIXEL_MASK);
177 VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK, 0);
178
179 saved_rgen_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL);
180 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL,
181 (saved_rgen_ctrl & ~(NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS |
182 NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM)) |
183 NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON);
184
185 blue = 8; /* start of test range */
186
187 do {
188 bool sense_pair[2];
189
190 VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
191 NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, 0);
192 NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, 0);
193 /* testing blue won't find monochrome monitors. I don't care */
194 NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, blue);
195
196 i = 0;
197 /* take sample pairs until both samples in the pair agree */
198 do {
199 if (sample_load_twice(pNv, sense_pair))
200 goto out;
201 } while ((sense_pair[0] != sense_pair[1]) &&
202 ++i < MAX_SAMPLE_PAIRS);
203
204 if (i == MAX_SAMPLE_PAIRS)
205 /* too much oscillation defaults to LO */
206 sense = false;
207 else
208 sense = sense_pair[0];
209
210 /*
211 * if sense goes LO before blue ramps to 0x18, monitor is not connected.
212 * ergo, if blue gets to 0x18, monitor must be connected
213 */
214 } while (++blue < 0x18 && sense);
215
216out:
217 VGA_WR08(pNv->REGS, NV_PRMDIO_PIXEL_MASK, saved_palette_mask);
218 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl);
219 VGA_WR08(pNv->REGS, NV_PRMDIO_WRITE_MODE_ADDRESS, 0);
220 for (i = 0; i < 3; i++)
221 NV_WR08(pNv->REGS, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]);
222 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl);
223 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi);
224 NVWriteVgaCrtc(pNv, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1);
225 NVWriteVgaSeq(pNv, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1);
226
227 if (blue == 0x18) {
228 NV_TRACE(pScrn, "Load detected on head A\n");
229 return true;
230 }
231
232 return false;
233}
234
235static bool
236nv_nv17_load_detect(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder)
237{
238 NVPtr pNv = NVPTR(pScrn);
239 uint32_t testval, regoffset = nv_output_ramdac_offset(nv_encoder);
240 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, saved_rtest_ctrl, temp;
241 int head, present = 0;
242 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
243
244#define RGB_TEST_DATA(r,g,b) (r << 0 | g << 10 | b << 20)
245 testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
246 if (pNv->vbios->dactestval)
247 testval = pNv->vbios->dactestval;
248
249 saved_rtest_ctrl = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
250 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset,
251 saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF);
252
253 saved_powerctrl_2 = nvReadMC(pNv, NV_PBUS_POWERCTRL_2);
254
255 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff);
256 if (regoffset == 0x68) {
257 saved_powerctrl_4 = nvReadMC(pNv, NV_PBUS_POWERCTRL_4);
258 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
259 }
260
261 usleep(4000);
262
263 saved_routput = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset);
264 head = (saved_routput & 0x100) >> 8;
265 /* if there's a spare crtc, using it will minimise flicker for the case
266 * where the in-use crtc is in use by an off-chip tmds encoder */
267 if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled)
268 head ^= 1;
269 /* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
270 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset,
271 (saved_routput & 0xfffffece) | head << 8);
272 usleep(1000);
273
274 temp = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset);
275 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, temp | 1);
276
277 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TESTPOINT_DATA,
278 NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK | testval);
279 temp = NVReadRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL);
280 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL,
281 temp | NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
282 usleep(1000);
283
284 present = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset) &
285 NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI;
286
287 temp = NVReadRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL);
288 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TEST_CONTROL,
289 temp & ~NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED);
290 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_TESTPOINT_DATA, 0);
291
292 /* bios does something more complex for restoring, but I think this is good enough */
293 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput);
294 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl);
295 if (regoffset == 0x68)
296 nvWriteMC(pNv, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
297 nvWriteMC(pNv, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
298
299 if (present) {
300 NV_TRACE(pScrn, "Load detected on output %c\n",
301 '@' + ffs(nv_encoder->dcb->or));
302 return true;
303 }
304
305 return false;
306}
307
308static void
309update_output_fields(xf86OutputPtr output, struct nouveau_encoder *det_encoder)
310{
311 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
312 NVPtr pNv = NVPTR(output->scrn);
313
314 if (nv_connector->detected_encoder == det_encoder)
315 return;
316
317 nv_connector->detected_encoder = det_encoder;
318 output->possible_crtcs = det_encoder->dcb->heads;
319 if (IS_DFP(det_encoder->dcb->type)) {
320 output->doubleScanAllowed = false;
321 output->interlaceAllowed = false;
322 } else {
323 output->doubleScanAllowed = true;
324 if (pNv->Architecture == NV_ARCH_20 ||
325 (pNv->Architecture == NV_ARCH_10 &&
326 (pNv->Chipset & 0x0ff0) != CHIPSET_NV10 &&
327 (pNv->Chipset & 0x0ff0) != CHIPSET_NV15))
328 /* HW is broken */
329 output->interlaceAllowed = false;
330 else
331 output->interlaceAllowed = true;
332 }
333}
334
335static bool edid_sink_connected(xf86OutputPtr output)
336{
337 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
338 NVPtr pNv = NVPTR(output->scrn);
339 bool waslocked = NVLockVgaCrtcs(pNv, false);
340 bool wastied = nv_heads_tied(pNv);
341
342 if (wastied)
343 NVSetOwner(pNv, 0); /* necessary? */
344
345 nv_connector->edid = xf86OutputGetEDID(output, nv_connector->pDDCBus);
346
347 if (wastied)
348 NVSetOwner(pNv, 0x4);
349 if (waslocked)
350 NVLockVgaCrtcs(pNv, true);
351
352 return !!nv_connector->edid;
353}
354
355static xf86OutputStatus
356nv_output_detect(xf86OutputPtr output)
357{
358 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
359 ScrnInfoPtr pScrn = output->scrn;
360 NVPtr pNv = NVPTR(pScrn);
361 struct nouveau_encoder *det_encoder;
362 xf86OutputStatus ret = XF86OutputStatusDisconnected;
363
364 struct nouveau_encoder *find_encoder_by_type(enum nouveau_encoder_type type)
365 {
366 int i;
367 for (i = 0; i < pNv->vbios->dcb->entries; i++)
368 if (nv_connector->possible_encoders & (1 << i) &&
369 (type == OUTPUT_ANY || pNv->encoders[i].dcb->type == type))
370 return &pNv->encoders[i];
371 return NULL;
372 }
373
374 /* if an LVDS output was ever connected it remains so */
375 if (nv_connector->detected_encoder &&
376 nv_connector->detected_encoder->dcb->type == OUTPUT_LVDS)
377 return XF86OutputStatusConnected;
378
379 if (nv_connector->pDDCBus && edid_sink_connected(output)) {
380 if (MULTIPLE_ENCODERS(nv_connector->possible_encoders)) {
381 if (nv_connector->edid->features.input_type)
382 det_encoder = find_encoder_by_type(OUTPUT_TMDS);
383 else
384 det_encoder = find_encoder_by_type(OUTPUT_ANALOG);
385 } else
386 det_encoder = find_encoder_by_type(OUTPUT_ANY);
387 ret = XF86OutputStatusConnected;
388 } else if ((det_encoder = find_encoder_by_type(OUTPUT_ANALOG))) {
389 /* bind encoder if enabled in xorg.conf */
390 if (output->conf_monitor &&
391 xf86CheckBoolOption(output->conf_monitor->mon_option_lst,
392 "Enable", FALSE))
393 ret = XF86OutputStatusConnected;
394 else if (pNv->gf4_disp_arch) {
395 if (nv_nv17_load_detect(pScrn, det_encoder))
396 ret = XF86OutputStatusConnected;
397 } else
398 if (nv_legacy_load_detect(pScrn))
399 ret = XF86OutputStatusConnected;
400 } else if ((det_encoder = find_encoder_by_type(OUTPUT_LVDS))) {
401 if (det_encoder->dcb->lvdsconf.use_straps_for_mode) {
402 if (nouveau_bios_fp_mode(pScrn, NULL))
403 ret = XF86OutputStatusConnected;
404 } else if (!pNv->vbios->fp_no_ddc &&
405 nouveau_bios_embedded_edid(pScrn)) {
406 nv_connector->edid = xf86InterpretEDID(pScrn->scrnIndex,
407 nouveau_bios_embedded_edid(pScrn));
408 ret = XF86OutputStatusConnected;
409 }
410 }
411
412 if (ret != XF86OutputStatusDisconnected)
413 update_output_fields(output, det_encoder);
414
415 return ret;
416}
417
418static DisplayModePtr
419get_native_mode_from_edid(xf86OutputPtr output, DisplayModePtr edid_modes)
420{
421 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
422 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
423 int max_h_active = 0, max_v_active = 0;
424 int i;
425 DisplayModePtr mode;
426
427 for (i = 0; i < DET_TIMINGS; i++) {
428 struct detailed_timings *dt =
429 &nv_connector->edid->det_mon[i].section.d_timings;
430
431 if (nv_connector->edid->det_mon[i].type != DT)
432 continue;
433 /* Selecting only based on width ok? */
434 if (dt->h_active > max_h_active) {
435 max_h_active = dt->h_active;
436 max_v_active = dt->v_active;
437 }
438 }
439 if (!max_h_active || !max_v_active) /* clearly a joke EDID */
440 for (i = 0; i < STD_TIMINGS; i++) {
441 struct std_timings *st =
442 &nv_connector->edid->timings2[i];
443
444 if (st->hsize > max_h_active) {
445 max_h_active = st->hsize;
446 max_v_active = st->vsize;
447 }
448 }
449 if (!max_h_active || !max_v_active) {
450 NV_ERROR(output->scrn, "EDID too broken to find native mode\n");
451 return NULL;
452 }
453
454 if (nv_encoder->native_mode) {
455 xfree(nv_encoder->native_mode);
456 nv_encoder->native_mode = NULL;
457 }
458
459 for (mode = edid_modes; mode != NULL; mode = mode->next) {
460 if (mode->HDisplay == max_h_active &&
461 mode->VDisplay == max_v_active) {
462 /* Take the preferred mode when it exists. */
463 if (mode->type & M_T_PREFERRED) {
464 nv_encoder->native_mode = xf86DuplicateMode(mode);
465 break;
466 }
467 /* Find the highest refresh mode otherwise. */
468 if (!nv_encoder->native_mode ||
469 (mode->VRefresh > nv_encoder->native_mode->VRefresh)) {
470 if (nv_encoder->native_mode)
471 xfree(nv_encoder->native_mode);
472 mode->type |= M_T_PREFERRED;
473 nv_encoder->native_mode = xf86DuplicateMode(mode);
474 }
475 }
476 }
477
478 return nv_encoder->native_mode;
479}
480
481static DisplayModePtr
482nv_output_get_edid_modes(xf86OutputPtr output)
483{
484 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
485 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
486 DisplayModePtr edid_modes;
487
488 if (IS_DFP(nv_encoder->dcb->type) &&
489 nv_encoder->scaling_mode != SCALE_PANEL)
490 /* the digital scaler is not limited to modes given in the EDID,
491 * so enable the GTF bit in order that the xserver thinks
492 * continuous timing is available and adds the standard modes
493 */
494 nv_connector->edid->features.msc |= 1;
495
496 xf86OutputSetEDID(output, nv_connector->edid);
497 if (!(edid_modes = xf86OutputGetEDIDModes(output)))
498 return edid_modes;
499
500 if (IS_DFP(nv_encoder->dcb->type))
501 if (!get_native_mode_from_edid(output, edid_modes))
502 return NULL;
503 if (nv_encoder->dcb->type == OUTPUT_TMDS)
504 nv_encoder->dual_link = nv_encoder->native_mode->Clock >= 165000;
505
506 return edid_modes;
507}
508
509static DisplayModePtr
510nv_lvds_output_get_modes(xf86OutputPtr output)
511{
512 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
513 struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
514 ScrnInfoPtr pScrn = output->scrn;
515 DisplayModeRec mode, *ret_mode = NULL;
516 int clock = 0; /* needs to be zero for straps case */
517 bool dl, if_is_24bit = false;
518
519 /* panels only have one mode, and it doesn't change */
520 if (nv_encoder->native_mode)
521 return xf86DuplicateMode(nv_encoder->native_mode);
522
523 if (nv_encoder->dcb->lvdsconf.use_straps_for_mode) {
524 if (!nouveau_bios_fp_mode(pScrn, &mode))
525 return NULL;
526
527 mode.status = MODE_OK;
528 mode.type = M_T_DRIVER | M_T_PREFERRED;
529 xf86SetModeDefaultName(&mode);
530
531 nv_encoder->native_mode = xf86DuplicateMode(&mode);
532 ret_mode = xf86DuplicateMode(&mode);
533 } else
534 if ((ret_mode = nv_output_get_edid_modes(output)))
535 clock = nv_encoder->native_mode->Clock;
536
537 if (nouveau_bios_parse_lvds_table(pScrn, clock, &dl, &if_is_24bit)) {
538 if (nv_encoder->native_mode) {
539 xfree(nv_encoder->native_mode);
540 nv_encoder->native_mode = NULL;
541 }
542 return NULL;
543 }
544
545 /* because of the pre-existing native mode exit above, this will only
546 * get run at startup (and before create_resources is called in
547 * mode_fixup), so subsequent user dither settings are not overridden
548 */
549 nv_encoder->dithering |= !if_is_24bit;
550 nv_encoder->dual_link = dl;
551
552 return ret_mode;
553}
554
555static int nv_output_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
556{
557 struct nouveau_encoder *nv_encoder = to_nouveau_connector(output)->detected_encoder;
558
559 /* mode_valid can be called by someone doing addmode on an output
560 * which is disconnected and so without an encoder; avoid crashing
561 */
562 if (!nv_encoder)
563 return MODE_ERROR;
564
565 if (!output->doubleScanAllowed && mode->Flags & V_DBLSCAN)
566 return MODE_NO_DBLESCAN;
567 if (!output->interlaceAllowed && mode->Flags & V_INTERLACE)
568 return MODE_NO_INTERLACE;
569
570 if (nv_encoder->dcb->type == OUTPUT_ANALOG) {
571 if (nv_encoder->dcb->crtconf.maxfreq) {
572 if (mode->Clock > nv_encoder->dcb->crtconf.maxfreq)
573 return MODE_CLOCK_HIGH;
574 } else
575 if (mode->Clock > 350000)
576 return MODE_CLOCK_HIGH;
577 }
578 /* must have a native mode for fp (except in panel scaling case) */
579 if (IS_DFP(nv_encoder->dcb->type) && !nv_encoder->native_mode &&
580 nv_encoder->scaling_mode != SCALE_PANEL)
581 return MODE_NOCLOCK;
582 if (IS_DFP(nv_encoder->dcb->type) && nv_encoder->native_mode)
583 /* No modes > panel's native res */
584 if (mode->HDisplay > nv_encoder->native_mode->HDisplay ||
585 mode->VDisplay > nv_encoder->native_mode->VDisplay)
586 return MODE_PANEL;
587 if (nv_encoder->dcb->type == OUTPUT_TMDS) {
588 if (nv_encoder->dcb->duallink_possible) {
589 if (mode->Clock > 330000) /* 2x165 MHz */
590 return MODE_CLOCK_HIGH;
591 } else
592 if (mode->Clock > 165000) /* 165 MHz */
593 return MODE_CLOCK_HIGH;
594 }
595
596 return MODE_OK;
597}
598
599static void
600nv_output_destroy(xf86OutputPtr output)
601{
602 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
603 struct nouveau_encoder *nv_encoder;
604 NVPtr pNv = NVPTR(output->scrn);
605 int i;
606
607 if (!nv_connector)
608 return;
609
610 if (nv_connector->edid)
611 xfree(nv_connector->edid);
612 FOR_EACH_ENCODER_IN_CONNECTOR(i, nv_connector, nv_encoder)
613 if (nv_encoder->native_mode)
614 xfree(nv_encoder->native_mode);
615 xfree(nv_connector);
616}
617
618static char * get_current_scaling_name(enum scaling_modes mode)
619{
620 static const struct {
621 char *name;
622 enum scaling_modes mode;
623 } scaling_mode[] = {
624 { "panel", SCALE_PANEL },
625 { "fullscreen", SCALE_FULLSCREEN },
626 { "aspect", SCALE_ASPECT },
627 { "noscale", SCALE_NOSCALE },
628 { NULL, SCALE_INVALID }
629 };
630 int i;
631
632 for (i = 0; scaling_mode[i].name; i++)
633 if (scaling_mode[i].mode == mode)
634 return scaling_mode[i].name;
635
636 return NULL;
637}
638
639static int nv_output_create_prop(xf86OutputPtr output, char *name, Atom *atom,
640 INT32 *rangevals, INT32 cur_val, char *cur_str, Bool do_mode_set)
641{
642 int ret = -ENOMEM;
643 Bool range = rangevals ? TRUE : FALSE;
644
645 if ((*atom = MakeAtom(name, strlen(name), TRUE)) == BAD_RESOURCE)
646 goto fail;
647 if (RRQueryOutputProperty(output->randr_output, *atom))
648 return 0; /* already exists */
649 if ((ret = RRConfigureOutputProperty(output->randr_output, *atom,
650 do_mode_set, range, FALSE, range ? 2 : 0, rangevals)))
651 goto fail;
652 if (range)
653 ret = RRChangeOutputProperty(output->randr_output, *atom, XA_INTEGER, 32,
654 PropModeReplace, 1, &cur_val, FALSE, do_mode_set);
655 else
656 ret = RRChangeOutputProperty(output->randr_output, *atom, XA_STRING, 8,
657 PropModeReplace, strlen(cur_str), cur_str,
658 FALSE, do_mode_set);
659
660fail:
661 if (ret)
662 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
663 "Creation of %s property failed: %d\n", name, ret);
664
665 return ret;
666}
667
668static Atom dithering_atom, scaling_mode_atom;
669static Atom dv_atom, sharpness_atom;
670
671static void nv_output_create_resources(xf86OutputPtr output)
672{
673 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
674 NVPtr pNv = NVPTR(output->scrn);
675
676 /* may be called before encoder is picked, resources will be created
677 * by update_output_fields()
678 */
679 if (!nv_encoder)
680 return;
681
682 if (IS_DFP(nv_encoder->dcb->type)) {
683 nv_output_create_prop(output, "DITHERING", &dithering_atom,
684 (INT32 []){ 0, 1 }, nv_encoder->dithering, NULL, TRUE);
685 nv_output_create_prop(output, "SCALING_MODE", &scaling_mode_atom,
686 NULL, 0, get_current_scaling_name(nv_encoder->scaling_mode), TRUE);
687 }
688 if (pNv->NVArch >= 0x11 && output->crtc) {
689 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
690 INT32 dv_range[2] = { 0, !pNv->gf4_disp_arch ? 3 : 63 };
691 /* unsure of correct condition here: blur works on my nv34, but not on my nv31 */
692 INT32 is_range[2] = { pNv->NVArch > 0x31 ? -32 : 0, 31 };
693
694 nv_output_create_prop(output, "DIGITAL_VIBRANCE", &dv_atom,
695 dv_range, nv_crtc->saturation, NULL, FALSE);
696 if (pNv->NVArch >= 0x30)
697 nv_output_create_prop(output, "IMAGE_SHARPENING", &sharpness_atom,
698 is_range, nv_crtc->sharpness, NULL, FALSE);
699 }
700}
701
702static Bool
703nv_output_set_property(xf86OutputPtr output, Atom property,
704 RRPropertyValuePtr value)
705{
706 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
707 NVPtr pNv = NVPTR(output->scrn);
708
709 if (property == scaling_mode_atom) {
710 char *name = (char *) value->data;
711 int32_t val;
712
713 if (value->type != XA_STRING || value->format != 8)
714 return FALSE;
715
716 /* Match a string to a scaling mode */
717 val = nv_scaling_mode_lookup(name, value->size);
718 if (val == SCALE_INVALID)
719 return FALSE;
720
721 /* LVDS must always use gpu scaling. */
722 if (val == SCALE_PANEL && nv_encoder->dcb->type == OUTPUT_LVDS)
723 return FALSE;
724
725 nv_encoder->scaling_mode = val;
726 } else if (property == dithering_atom) {
727 int32_t val = *(int32_t *) value->data;
728
729 if (value->type != XA_INTEGER || value->format != 32)
730 return FALSE;
731
732 if (val < 0 || val > 1)
733 return FALSE;
734
735 nv_encoder->dithering = val;
736 } else if (property == dv_atom || property == sharpness_atom) {
737 int32_t val = *(int32_t *) value->data;
738
739 if (value->type != XA_INTEGER || value->format != 32)
740 return FALSE;
741
742 if (!output->crtc)
743 return FALSE;
744
745 if (property == dv_atom) {
746 if (val < 0 || val > (!pNv->gf4_disp_arch ? 3 : 63))
747 return FALSE;
748
749 nv_crtc_set_digital_vibrance(output->crtc, val);
750 } else {
751 if (val < (pNv->NVArch > 0x31 ? -32 : 0) || val > 31)
752 return FALSE;
753
754 nv_crtc_set_image_sharpening(output->crtc, val);
755 }
756 }
757
758 return TRUE;
759}
760
761static Bool
762nv_output_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
763 DisplayModePtr adjusted_mode)
764{
765 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
766
767 if (nv_connector->nv_encoder != nv_connector->detected_encoder) {
768 nv_connector->nv_encoder = nv_connector->detected_encoder;
769 if (output->randr_output) {
770 RRDeleteOutputProperty(output->randr_output, dithering_atom);
771 RRDeleteOutputProperty(output->randr_output, scaling_mode_atom);
772 output->funcs->create_resources(output);
773 }
774 }
775
776 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
777
778 /* For internal panels and gpu scaling on DVI we need the native mode */
779 if (IS_DFP(nv_encoder->dcb->type) &&
780 nv_encoder->scaling_mode != SCALE_PANEL) {
781 adjusted_mode->HDisplay = nv_encoder->native_mode->HDisplay;
782 adjusted_mode->HSkew = nv_encoder->native_mode->HSkew;
783 adjusted_mode->HSyncStart = nv_encoder->native_mode->HSyncStart;
784 adjusted_mode->HSyncEnd = nv_encoder->native_mode->HSyncEnd;
785 adjusted_mode->HTotal = nv_encoder->native_mode->HTotal;
786 adjusted_mode->VDisplay = nv_encoder->native_mode->VDisplay;
787 adjusted_mode->VScan = nv_encoder->native_mode->VScan;
788 adjusted_mode->VSyncStart = nv_encoder->native_mode->VSyncStart;
789 adjusted_mode->VSyncEnd = nv_encoder->native_mode->VSyncEnd;
790 adjusted_mode->VTotal = nv_encoder->native_mode->VTotal;
791 adjusted_mode->Clock = nv_encoder->native_mode->Clock;
792 adjusted_mode->Flags = nv_encoder->native_mode->Flags;
793
794 xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
795 }
796
797 return TRUE;
798}
799
800static void nv_digital_output_prepare_sel_clk(NVPtr pNv, struct nouveau_encoder *nv_encoder, int head)
801{
802 struct nouveau_mode_state *state = &pNv->set_state;
803 uint32_t bits1618 = nv_encoder->dcb->or & OUTPUT_A ? 0x10000 : 0x40000;
804
805 if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP)
806 return;
807
808 /* SEL_CLK is only used on the primary ramdac
809 * It toggles spread spectrum PLL output and sets the bindings of PLLs
810 * to heads on digital outputs
811 */
812 if (head)
813 state->sel_clk |= bits1618;
814 else
815 state->sel_clk &= ~bits1618;
816
817 /* nv30:
818 * bit 0 NVClk spread spectrum on/off
819 * bit 2 MemClk spread spectrum on/off
820 * bit 4 PixClk1 spread spectrum on/off toggle
821 * bit 6 PixClk2 spread spectrum on/off toggle
822 *
823 * nv40 (observations from bios behaviour and mmio traces):
824 * bits 4&6 as for nv30
825 * bits 5&7 head dependent as for bits 4&6, but do not appear with 4&6;
826 * maybe a different spread mode
827 * bits 8&10 seen on dual-link dvi outputs, purpose unknown (set by POST scripts)
828 * The logic behind turning spread spectrum on/off in the first place,
829 * and which bit-pair to use, is unclear on nv40 (for earlier cards, the fp table
830 * entry has the necessary info)
831 */
832 if (nv_encoder->dcb->type == OUTPUT_LVDS && pNv->saved_regs.sel_clk & 0xf0) {
833 int shift = (pNv->saved_regs.sel_clk & 0x50) ? 0 : 1;
834
835 state->sel_clk &= ~0xf0;
836 state->sel_clk |= (head ? 0x40 : 0x10) << shift;
837 }
838}
839
840#define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \
841 NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \
842 NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS)
843#define FP_TG_CONTROL_OFF (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE | \
844 NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE | \
845 NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE)
846
847static bool is_fpc_off(uint32_t fpc)
848{
849 return ((fpc & (FP_TG_CONTROL_ON | FP_TG_CONTROL_OFF)) ==
850 FP_TG_CONTROL_OFF);
851}
852
853static void
854nv_output_prepare(xf86OutputPtr output)
855{
856 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
857 NVPtr pNv = NVPTR(output->scrn);
858 int head = to_nouveau_crtc(output->crtc)->head;
859 struct nouveau_crtc_state *crtcstate = pNv->set_state.head;
860 uint8_t *cr_lcd = &crtcstate[head].CRTC[NV_CIO_CRE_LCD__INDEX];
861 uint8_t *cr_lcd_oth = &crtcstate[head ^ 1].CRTC[NV_CIO_CRE_LCD__INDEX];
862
863 output->funcs->dpms(output, DPMSModeOff);
864
865 if (nv_encoder->dcb->type == OUTPUT_ANALOG) {
866 if (NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL) &
867 FP_TG_CONTROL_ON) {
868 /* digital remnants must be cleaned before new crtc
869 * values programmed. delay is time for the vga stuff
870 * to realise it's in control again
871 */
872 NVWriteRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL,
873 FP_TG_CONTROL_OFF);
874 usleep(50000);
875 }
876 /* don't inadvertently turn it on when state written later */
877 crtcstate[head].fp_control = FP_TG_CONTROL_OFF;
878 }
879
880 /* calculate some output specific CRTC regs now, so that they can be
881 * written in nv_crtc_set_mode
882 */
883
884 if (IS_DFP(nv_encoder->dcb->type))
885 nv_digital_output_prepare_sel_clk(pNv, nv_encoder, head);
886
887 /* Some NV4x have unknown values (0x3f, 0x50, 0x54, 0x6b, 0x79, 0x7f)
888 * at LCD__INDEX which we don't alter
889 */
890 if (!(*cr_lcd & 0x44)) {
891 *cr_lcd = IS_DFP(nv_encoder->dcb->type) ? 0x3 : 0x0;
892 if (IS_DFP(nv_encoder->dcb->type) && pNv->twoHeads) {
893 if (nv_encoder->dcb->location == DCB_LOC_ON_CHIP)
894 *cr_lcd |= head ? 0x0 : 0x8;
895 else {
896 *cr_lcd |= (nv_encoder->dcb->or << 4) & 0x30;
897 if (nv_encoder->dcb->type == OUTPUT_LVDS)
898 *cr_lcd |= 0x30;
899 if ((*cr_lcd & 0x30) == (*cr_lcd_oth & 0x30)) {
900 /* avoid being connected to both crtcs */
901 *cr_lcd_oth &= ~0x30;
902 NVWriteVgaCrtc(pNv, head ^ 1,
903 NV_CIO_CRE_LCD__INDEX,
904 *cr_lcd_oth);
905 }
906 }
907 }
908 }
909}
910
911static void
912nv_output_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
913{
914 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
915 ScrnInfoPtr pScrn = output->scrn;
916 NVPtr pNv = NVPTR(pScrn);
917 struct dcb_entry *dcbe = nv_encoder->dcb;
918 int head = to_nouveau_crtc(output->crtc)->head;
919
920 NV_TRACE(pScrn, "%s called for encoder %d\n", __func__, dcbe->index);
921
922 if (pNv->gf4_disp_arch && dcbe->type == OUTPUT_ANALOG) {
923 uint32_t dac_offset = nv_output_ramdac_offset(nv_encoder);
924 uint32_t otherdac;
925 int i;
926
927 /* bit 16-19 are bits that are set on some G70 cards,
928 * but don't seem to have much effect */
929 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset,
930 head << 8 | NV_PRAMDAC_DACCLK_SEL_DACCLK);
931 /* force any other vga encoders to bind to the other crtc */
932 for (i = 0; i < pNv->vbios->dcb->entries; i++)
933 if (i != dcbe->index && pNv->encoders[i].dcb &&
934 pNv->encoders[i].dcb->type == OUTPUT_ANALOG) {
935 dac_offset = nv_output_ramdac_offset(&pNv->encoders[i]);
936 otherdac = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset);
937 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + dac_offset,
938 (otherdac & ~0x100) | (head ^ 1) << 8);
939 }
940 }
941 if (dcbe->type == OUTPUT_TMDS)
942 run_tmds_table(pScrn, dcbe, head, adjusted_mode->Clock);
943 else if (dcbe->type == OUTPUT_LVDS)
944 call_lvds_script(pScrn, dcbe, head, LVDS_RESET, adjusted_mode->Clock);
945 if (IS_DFP(dcbe->type))
946 /* update fp_control state for any changes made by scripts,
947 * so correct value is written at DPMS on */
948 pNv->set_state.head[head].fp_control =
949 NVReadRAMDAC(pNv, head, NV_PRAMDAC_FP_TG_CONTROL);
950
951 /* This could use refinement for flatpanels, but it should work this way */
952 if (pNv->NVArch < 0x44)
953 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + nv_output_ramdac_offset(nv_encoder), 0xf0000000);
954 else
955 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_TEST_CONTROL + nv_output_ramdac_offset(nv_encoder), 0x00100000);
956}
957
958static void
959nv_output_commit(xf86OutputPtr output)
960{
961 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
962 ScrnInfoPtr pScrn = output->scrn;
963 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(output->crtc);
964
965 output->funcs->dpms(output, DPMSModeOn);
966
967 NV_TRACE(pScrn, "Output %s is running on CRTC %d using output %c\n",
968 output->name, nv_crtc->head, '@' + ffs(nv_encoder->dcb->or));
969}
970
971static void dpms_update_fp_control(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode)
972{
973 NVPtr pNv = NVPTR(pScrn);
974 struct nouveau_crtc *nv_crtc;
975 uint32_t *fpc;
976 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
977 int i;
978
979 if (mode == DPMSModeOn) {
980 nv_crtc = to_nouveau_crtc(crtc);
981 fpc = &nv_crtc->state->fp_control;
982
983 if (is_fpc_off(*fpc))
984 /* using saved value is ok, as (is_digital && dpms_on &&
985 * fp_control==OFF) is (at present) *only* true when
986 * fpc's most recent change was by below "off" code
987 */
988 *fpc = nv_crtc->dpms_saved_fp_control;
989
990 nv_crtc->fp_users |= 1 << nv_encoder->dcb->index;
991 NVWriteRAMDAC(pNv, nv_crtc->head, NV_PRAMDAC_FP_TG_CONTROL, *fpc);
992 } else
993 for (i = 0; i < xf86_config->num_crtc; i++) {
994 nv_crtc = to_nouveau_crtc(xf86_config->crtc[i]);
995 fpc = &nv_crtc->state->fp_control;
996
997 nv_crtc->fp_users &= ~(1 << nv_encoder->dcb->index);
998 if (!is_fpc_off(*fpc) && !nv_crtc->fp_users) {
999 nv_crtc->dpms_saved_fp_control = *fpc;
1000 /* cut the FP output */
1001 *fpc &= ~FP_TG_CONTROL_ON;
1002 *fpc |= FP_TG_CONTROL_OFF;
1003 NVWriteRAMDAC(pNv, nv_crtc->head,
1004 NV_PRAMDAC_FP_TG_CONTROL, *fpc);
1005 }
1006 }
1007}
1008
1009static bool is_powersaving_dpms(int mode)
1010{
1011 return (mode == DPMSModeStandby || mode == DPMSModeSuspend ||
1012 mode == DPMSModeOff);
1013}
1014
1015static void
1016lvds_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode)
1017{
1018 NVPtr pNv = NVPTR(pScrn);
1019 bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms);
1020
1021 if (nv_encoder->last_dpms == mode)
1022 return;
1023 nv_encoder->last_dpms = mode;
1024
1025 NV_TRACE(pScrn, "Setting dpms mode %d on lvds encoder (output %d)\n",
1026 mode, nv_encoder->dcb->index);
1027
1028 if (was_powersaving && is_powersaving_dpms(mode))
1029 return;
1030
1031 if (nv_encoder->dcb->lvdsconf.use_power_scripts) {
1032 /* when removing an output, crtc may not be set, but PANEL_OFF
1033 * must still be run
1034 */
1035 int head = crtc ? to_nouveau_crtc(crtc)->head :
1036 nv_get_digital_bound_head(pNv, nv_encoder->dcb->or);
1037
1038 if (mode == DPMSModeOn)
1039 call_lvds_script(pScrn, nv_encoder->dcb, head,
1040 LVDS_PANEL_ON, nv_encoder->native_mode->Clock);
1041 else
1042 /* pxclk of 0 is fine for PANEL_OFF, and for a
1043 * disconnected LVDS encoder there is no native_mode
1044 */
1045 call_lvds_script(pScrn, nv_encoder->dcb, head,
1046 LVDS_PANEL_OFF, 0);
1047 }
1048
1049 dpms_update_fp_control(pScrn, nv_encoder, crtc, mode);
1050
1051 if (mode == DPMSModeOn)
1052 nv_digital_output_prepare_sel_clk(pNv, nv_encoder, to_nouveau_crtc(crtc)->head);
1053 else {
1054 pNv->set_state.sel_clk = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK);
1055 pNv->set_state.sel_clk &= ~0xf0;
1056 }
1057 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_SEL_CLK, pNv->set_state.sel_clk);
1058}
1059
1060static void
1061vga_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode)
1062{
1063 NVPtr pNv = NVPTR(pScrn);
1064
1065 if (nv_encoder->last_dpms == mode)
1066 return;
1067 nv_encoder->last_dpms = mode;
1068
1069 NV_TRACE(pScrn, "Setting dpms mode %d on vga encoder (output %d)\n",
1070 mode, nv_encoder->dcb->index);
1071
1072 if (pNv->gf4_disp_arch) {
1073 uint32_t outputval = NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder));
1074
1075 if (mode == DPMSModeOff)
1076 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder),
1077 outputval & ~NV_PRAMDAC_DACCLK_SEL_DACCLK);
1078 else if (mode == DPMSModeOn)
1079 NVWriteRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder),
1080 outputval | NV_PRAMDAC_DACCLK_SEL_DACCLK);
1081 }
1082}
1083
1084static void
1085tmds_encoder_dpms(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder, xf86CrtcPtr crtc, int mode)
1086{
1087 if (nv_encoder->last_dpms == mode)
1088 return;
1089 nv_encoder->last_dpms = mode;
1090
1091 NV_TRACE(pScrn, "Setting dpms mode %d on tmds encoder (output %d)\n",
1092 mode, nv_encoder->dcb->index);
1093
1094 dpms_update_fp_control(pScrn, nv_encoder, crtc, mode);
1095}
1096
1097static void nv_output_dpms(xf86OutputPtr output, int mode)
1098{
1099 struct nouveau_connector *nv_connector = to_nouveau_connector(output);
1100 struct nouveau_encoder *nv_encoder = to_nouveau_encoder(output);
1101 ScrnInfoPtr pScrn = output->scrn;
1102 xf86CrtcPtr crtc = output->crtc;
1103 NVPtr pNv = NVPTR(pScrn);
1104 int i;
1105 void (* const encoder_dpms[4])(ScrnInfoPtr, struct nouveau_encoder *, xf86CrtcPtr, int) =
1106 /* index matches DCB type */
1107 { vga_encoder_dpms, NULL, tmds_encoder_dpms, lvds_encoder_dpms };
1108
1109 struct nouveau_encoder *nv_encoder_i;
1110 FOR_EACH_ENCODER_IN_CONNECTOR(i, nv_connector, nv_encoder_i)
1111 if (nv_encoder_i != nv_encoder)
1112 encoder_dpms[nv_encoder_i->dcb->type](pScrn, nv_encoder_i, crtc, DPMSModeOff);
1113
1114 if (nv_encoder) /* may be called before encoder is picked, but iteration above solves it */
1115 encoder_dpms[nv_encoder->dcb->type](pScrn, nv_encoder, crtc, mode);
1116}
1117
1118void nv_encoder_save(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder)
1119{
1120 NVPtr pNv = NVPTR(pScrn);
1121
1122 if (!nv_encoder->dcb) /* uninitialised encoder */
1123 return;
1124
1125 if (pNv->gf4_disp_arch && nv_encoder->dcb->type == OUTPUT_ANALOG)
1126 nv_encoder->restore.output =
1127 NVReadRAMDAC(pNv, 0, NV_PRAMDAC_DACCLK +
1128 nv_output_ramdac_offset(nv_encoder));
1129 if (pNv->twoHeads && IS_DFP(nv_encoder->dcb->type))
1130 nv_encoder->restore.head =
1131 nv_get_digital_bound_head(pNv, nv_encoder->dcb->or);
1132}
1133
1134void nv_encoder_restore(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder)
1135{
1136 NVPtr pNv = NVPTR(pScrn);
1137 int head = nv_encoder->restore.head;
1138
1139 if (!nv_encoder->dcb) /* uninitialised encoder */
1140 return;
1141
1142 if (pNv->gf4_disp_arch && nv_encoder->dcb->type == OUTPUT_ANALOG)
1143 NVWriteRAMDAC(pNv, 0,
1144 NV_PRAMDAC_DACCLK + nv_output_ramdac_offset(nv_encoder),
1145 nv_encoder->restore.output);
1146 if (nv_encoder->dcb->type == OUTPUT_LVDS)
1147 call_lvds_script(pScrn, nv_encoder->dcb, head, LVDS_PANEL_ON,
1148 nv_encoder->native_mode->Clock);
1149 if (nv_encoder->dcb->type == OUTPUT_TMDS) {
1150 int clock = nouveau_hw_pllvals_to_clk
1151 (&pNv->saved_regs.head[head].pllvals);
1152
1153 run_tmds_table(pScrn, nv_encoder->dcb, head, clock);
1154 }
1155
1156 nv_encoder->last_dpms = NV_DPMS_CLEARED;
1157}
1158
1159static const xf86OutputFuncsRec nv_output_funcs = {
1160 .dpms = nv_output_dpms,
1161 .mode_valid = nv_output_mode_valid,
1162 .mode_fixup = nv_output_mode_fixup,
1163 .mode_set = nv_output_mode_set,
1164 .detect = nv_output_detect,
1165 .get_modes = nv_output_get_edid_modes,
1166 .destroy = nv_output_destroy,
1167 .prepare = nv_output_prepare,
1168 .commit = nv_output_commit,
1169 .create_resources = nv_output_create_resources,
1170 .set_property = nv_output_set_property,
1171};
1172
1173static const xf86OutputFuncsRec nv_lvds_output_funcs = {
1174 .dpms = nv_output_dpms,
1175 .mode_valid = nv_output_mode_valid,
1176 .mode_fixup = nv_output_mode_fixup,
1177 .mode_set = nv_output_mode_set,
1178 .detect = nv_output_detect,
1179 .get_modes = nv_lvds_output_get_modes,
1180 .destroy = nv_output_destroy,
1181 .prepare = nv_output_prepare,
1182 .commit = nv_output_commit,
1183 .create_resources = nv_output_create_resources,
1184 .set_property = nv_output_set_property,
1185};
1186
1187static void
1188nv_add_encoder(ScrnInfoPtr pScrn, struct dcb_entry *dcbent)
1189{
1190 NVPtr pNv = NVPTR(pScrn);
1191 struct nouveau_encoder *nv_encoder = &pNv->encoders[dcbent->index];
1192
1193 nv_encoder->dcb = dcbent;
1194 nv_encoder->last_dpms = NV_DPMS_CLEARED;
1195 nv_encoder->dithering = pNv->FPDither;
1196 if (pNv->FpScale && pNv->gf4_disp_arch) /* GPU Scaling */
1197 nv_encoder->scaling_mode = SCALE_ASPECT;
1198 else if (nv_encoder->dcb->type == OUTPUT_LVDS)
1199 nv_encoder->scaling_mode = SCALE_NOSCALE;
1200 else
1201 nv_encoder->scaling_mode = SCALE_PANEL;
1202 if (xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE)) {
1203 nv_encoder->scaling_mode = nv_scaling_mode_lookup(xf86GetOptValString(pNv->Options, OPTION_SCALING_MODE), -1);
1204 if (nv_encoder->scaling_mode == SCALE_INVALID)
1205 nv_encoder->scaling_mode = SCALE_ASPECT; /* default */
1206 }
1207}
1208
1209static void
1210nv_add_connector(ScrnInfoPtr pScrn, int i2c_index, int encoders, const xf86OutputFuncsRec *output_funcs, char *outputname)
1211{
1212 NVPtr pNv = NVPTR(pScrn);
1213 xf86OutputPtr output;
1214 struct nouveau_connector *nv_connector;
1215
1216 if (!(output = xf86OutputCreate(pScrn, output_funcs, outputname)))
1217 return;
1218 if (!(nv_connector = xcalloc(1, sizeof (struct nouveau_connector)))) {
1219 xf86OutputDestroy(output);
1220 return;
1221 }
1222
1223 output->driver_private = nv_connector;
1224
1225 if (i2c_index < 0xf)
1226 NV_I2CInit(pScrn, &nv_connector->pDDCBus, &pNv->vbios->dcb->i2c[i2c_index], xstrdup(outputname));
1227 nv_connector->possible_encoders = encoders;
1228}
1229
1230void NvSetupOutputs(ScrnInfoPtr pScrn)
1231{
1232 NVPtr pNv = NVPTR(pScrn);
1233 struct parsed_dcb *dcb = pNv->vbios->dcb;
1234 uint16_t connectors[0x10] = { 0 };
1235 int i, vga_count = 0, dvid_count = 0, dvii_count = 0, lvds_count = 0;
1236
1237 if (!(pNv->encoders = xcalloc(dcb->entries, sizeof (struct nouveau_encoder))))
1238 return;
1239
1240 for (i = 0; i < dcb->entries; i++) {
1241 struct dcb_entry *dcbent = &dcb->entry[i];
1242
1243 if (dcbent->type == OUTPUT_TV)
1244 continue;
1245 if (dcbent->type > 3) {
1246 NV_WARN(pScrn, "DCB type %d not known\n", dcbent->type);
1247 continue;
1248 }
1249
1250 connectors[dcbent->i2c_index] |= 1 << i;
1251
1252 nv_add_encoder(pScrn, dcbent);
1253 }
1254
1255 for (i = 0; i < dcb->entries; i++) {
1256 struct dcb_entry *dcbent = &dcb->entry[i];
1257 int i2c_index = dcbent->i2c_index;
1258 uint16_t encoders = connectors[i2c_index];
1259 char outputname[20];
1260 xf86OutputFuncsRec const *funcs = &nv_output_funcs;
1261
1262 if (!encoders)
1263 continue;
1264
1265 switch (dcbent->type) {
1266 case OUTPUT_ANALOG:
1267 if (!MULTIPLE_ENCODERS(encoders))
1268 sprintf(outputname, "VGA-%d", vga_count++);
1269 else
1270 sprintf(outputname, "DVI-I-%d", dvii_count++);
1271 break;
1272 case OUTPUT_TMDS:
1273 if (!MULTIPLE_ENCODERS(encoders))
1274 sprintf(outputname, "DVI-D-%d", dvid_count++);
1275 else
1276 sprintf(outputname, "DVI-I-%d", dvii_count++);
1277 break;
1278 case OUTPUT_LVDS:
1279 sprintf(outputname, "LVDS-%d", lvds_count++);
1280 funcs = &nv_lvds_output_funcs;
1281 /* don't create i2c adapter when lvds ddc not allowed */
1282 if (dcbent->lvdsconf.use_straps_for_mode ||
1283 pNv->vbios->fp_no_ddc)
1284 i2c_index = 0xf;
1285 break;
1286 default:
1287 continue;
1288 }
1289
1290 nv_add_connector(pScrn, i2c_index, encoders, funcs, outputname);
1291 connectors[i2c_index] = 0; /* avoid connectors being added multiply */
1292 }
1293}
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);
9Bool drmmode_cursor_init(ScreenPtr pScreen); 9Bool drmmode_cursor_init(ScreenPtr pScreen);
10void drmmode_fbcon_copy(ScrnInfoPtr pScrn); 10void drmmode_fbcon_copy(ScrnInfoPtr pScrn);
11 11
12/* in nouveau_calc.c */
13void nouveau_calc_arb(ScrnInfoPtr pScrn, int vclk, int bpp, int *burst, int *lwm);
14int nouveau_calc_pll_mnp(ScrnInfoPtr pScrn, struct pll_lims *pll_lim, int clk,
15 struct nouveau_pll_vals *pv);
16
17/* in nv_accel_common.c */ 12/* in nv_accel_common.c */
18Bool NVAccelCommonInit(ScrnInfoPtr pScrn); 13Bool NVAccelCommonInit(ScrnInfoPtr pScrn);
19Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret); 14Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret);
@@ -38,21 +33,6 @@ void NVWaitVSync(ScrnInfoPtr pScrn, int crtc);
38void NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv); 33void NVSetPortDefaults (ScrnInfoPtr pScrn, NVPortPrivPtr pPriv);
39unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr, int, int, int, int); 34unsigned int nv_window_belongs_to_crtc(ScrnInfoPtr, int, int, int, int);
40 35
41/* in nv_setup.c */
42void RivaEnterLeave(ScrnInfoPtr pScrn, Bool enter);
43void NVCommonSetup(ScrnInfoPtr pScrn);
44
45/* in nv_cursor.c */
46Bool NVCursorInitRandr12(ScreenPtr pScreen);
47void nv_crtc_show_cursor(xf86CrtcPtr crtc);
48void nv_crtc_hide_cursor(xf86CrtcPtr crtc);
49void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y);
50void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg);
51void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image);
52void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image);
53void nv_cursor_convert_cursor(uint32_t *src, void *dst, int src_stride,
54 int dst_stride, int bpp, uint32_t fg, uint32_t bg);
55
56/* in nv_dma.c */ 36/* in nv_dma.c */
57void NVSync(ScrnInfoPtr pScrn); 37void NVSync(ScrnInfoPtr pScrn);
58Bool NVInitDma(ScrnInfoPtr pScrn); 38Bool NVInitDma(ScrnInfoPtr pScrn);
@@ -72,52 +52,6 @@ void nouveau_wfb_init();
72/* in nv_shadow.c */ 52/* in nv_shadow.c */
73void NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); 53void NVRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox);
74 54
75/* in nv_bios.c */
76int NVParseBios(ScrnInfoPtr pScrn);
77int call_lvds_script(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, enum LVDS_script script, int pxclk);
78bool nouveau_bios_fp_mode(ScrnInfoPtr pScrn, DisplayModeRec *mode);
79int nouveau_bios_parse_lvds_table(ScrnInfoPtr pScrn, int pxclk, bool *dl, bool *if_is_24bit);
80int run_tmds_table(ScrnInfoPtr pScrn, struct dcb_entry *dcbent, int head, int pxclk);
81int get_pll_limits(ScrnInfoPtr pScrn, uint32_t limit_match, struct pll_lims *pll_lim);
82uint8_t * nouveau_bios_embedded_edid(ScrnInfoPtr pScrn);
83int nouveau_bios_run_display_table(ScrnInfoPtr, struct dcb_entry *, int pxclk);
84
85/* nv_crtc.c */
86void nv_crtc_set_digital_vibrance(xf86CrtcPtr crtc, int level);
87void nv_crtc_set_image_sharpening(xf86CrtcPtr crtc, int level);
88void NVCrtcSetBase(xf86CrtcPtr crtc, int x, int y);
89void nv_crtc_init(ScrnInfoPtr pScrn, int crtc_num);
90
91/* nv_output.c */
92void nv_encoder_restore(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder);
93void nv_encoder_save(ScrnInfoPtr pScrn, struct nouveau_encoder *nv_encoder);
94void NvSetupOutputs(ScrnInfoPtr pScrn);
95
96/* nouveau_hw.c */
97void NVWriteVgaSeq(NVPtr pNv, int head, uint8_t index, uint8_t value);
98uint8_t NVReadVgaSeq(NVPtr pNv, int head, uint8_t index);
99void NVWriteVgaGr(NVPtr pNv, int head, uint8_t index, uint8_t value);
100uint8_t NVReadVgaGr(NVPtr pNv, int head, uint8_t index);
101void NVSetOwner(NVPtr pNv, int owner);
102int nouveau_hw_get_current_head(ScrnInfoPtr pScrn);
103void NVBlankScreen(NVPtr pNv, int head, bool blank);
104void nouveau_hw_setpll(ScrnInfoPtr pScrn, uint32_t reg1,
105 struct nouveau_pll_vals *pv);
106int nouveau_hw_get_pllvals(ScrnInfoPtr pScrn, enum pll_types plltype,
107 struct nouveau_pll_vals *pllvals);
108int nouveau_hw_pllvals_to_clk(struct nouveau_pll_vals *pllvals);
109int nouveau_hw_get_clock(ScrnInfoPtr pScrn, enum pll_types plltype);
110void nouveau_hw_save_vga_fonts(ScrnInfoPtr pScrn, bool save);
111void nouveau_hw_save_state(ScrnInfoPtr pScrn, int head,
112 struct nouveau_mode_state *state);
113void nouveau_hw_load_state(ScrnInfoPtr pScrn, int head,
114 struct nouveau_mode_state *state);
115void nouveau_hw_load_state_palette(NVPtr pNv, int head,
116 struct nouveau_mode_state *state);
117
118/* in nv_i2c.c */
119int NV_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, struct dcb_i2c_entry *dcb_i2c, char *name);
120
121/* in nv04_video_overlay.c */ 55/* in nv04_video_overlay.c */
122void NV04PutOverlayImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int, 56void NV04PutOverlayImage(ScrnInfoPtr, struct nouveau_bo *, int, int, int,
123 BoxPtr, int, int, int, int, short, short, short, 57 BoxPtr, int, int, int, int, short, short, short,
@@ -213,42 +147,6 @@ void NV50EXADoneComposite(PixmapPtr);
213Bool NV50EXAUploadSIFC(const char *src, int src_pitch, 147Bool NV50EXAUploadSIFC(const char *src, int src_pitch,
214 PixmapPtr pdPix, int x, int y, int w, int h, int cpp); 148 PixmapPtr pdPix, int x, int y, int w, int h, int cpp);
215 149
216/* in nv50_display.c */
217Bool NV50DispPreInit(ScrnInfoPtr);
218Bool NV50DispInit(ScrnInfoPtr);
219void NV50DispShutdown(ScrnInfoPtr);
220
221/* in nv50_cursor.c */
222Bool NV50CursorInit(ScreenPtr);
223Bool NV50CursorAcquire(ScrnInfoPtr);
224void NV50CursorRelease(ScrnInfoPtr);
225
226/* in nv50_crtc.c */
227void NV50DisplayCommand(ScrnInfoPtr pScrn, uint32_t addr, uint32_t value);
228void NV50CrtcCommand(nouveauCrtcPtr crtc, uint32_t addr, uint32_t value);
229void NV50CrtcInit(ScrnInfoPtr pScrn);
230void NV50CrtcDestroy(ScrnInfoPtr pScrn);
231
232/* in nv50_output.c */
233int NV50OrOffset(nouveauOutputPtr output);
234void NV50OutputSetup(ScrnInfoPtr pScrn);
235void NV50OutputDestroy(ScrnInfoPtr pScrn);
236
237/* nv50_dac.c */
238void NV50DacSetFunctionPointers(nouveauOutputPtr output);
239
240/* nv50_sor.c */
241void NV50SorSetFunctionPointers(nouveauOutputPtr output);
242
243/* nv50_connector.c */
244void NV50ConnectorInit(ScrnInfoPtr pScrn);
245void NV50ConnectorDestroy(ScrnInfoPtr pScrn);
246
247/* nv50_randr.c */
248void nv50_crtc_init(ScrnInfoPtr pScrn, int crtc_num);
249void nv50_output_create(ScrnInfoPtr pScrn);
250int nv_scaling_mode_lookup(char *name, int size);
251
252/* nv50_xv.c */ 150/* nv50_xv.c */
253int nv50_xv_image_put(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int, 151int nv50_xv_image_put(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int,
254 BoxPtr, int, int, int, int, uint16_t, uint16_t, 152 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 @@
1/*
2 * Copyright 2003 NVIDIA, Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include "nv_include.h"
24
25static void nv4GetConfig (NVPtr pNv)
26{
27 uint32_t reg_FB0 = nvReadFB(pNv, NV_PFB_BOOT_0);
28
29 if (reg_FB0 & 0x00000100)
30 pNv->RamAmountKBytes = ((reg_FB0 >> 12) & 0x0F) * 1024 * 2 + 1024 * 2;
31 else
32 switch (reg_FB0 & 0x00000003) {
33 case 0:
34 pNv->RamAmountKBytes = 1024 * 32;
35 break;
36 case 1:
37 pNv->RamAmountKBytes = 1024 * 4;
38 break;
39 case 2:
40 pNv->RamAmountKBytes = 1024 * 8;
41 break;
42 case 3:
43 default:
44 pNv->RamAmountKBytes = 1024 * 16;
45 break;
46 }
47}
48
49static void nv10GetConfig(ScrnInfoPtr pScrn)
50{
51 NVPtr pNv = NVPTR(pScrn);
52 uint32_t implementation = pNv->Chipset & 0x0ff0;
53 struct pci_device *dev = NULL;
54 uint32_t data;
55
56 if (implementation == CHIPSET_NFORCE ||
57 implementation == CHIPSET_NFORCE2) {
58 dev = pci_device_find_by_slot(0, 0, 0, 1);
59 if (!dev) {
60 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
61 "couldn't find bridge device\n");
62 return;
63 }
64 }
65
66#if X_BYTE_ORDER == X_BIG_ENDIAN
67 if (!(nvReadMC(pNv, 0x0004) & 0x01000001))
68 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
69 "Card is in big endian mode, something is very wrong !\n");
70#endif
71
72 if (implementation == CHIPSET_NFORCE) {
73 pci_device_cfg_read_u32(dev, &data, 0x7c);
74 pNv->RamAmountKBytes = (((data >> 6) & 31) + 1) * 1024;
75 } else if (implementation == CHIPSET_NFORCE2) {
76 pci_device_cfg_read_u32(dev, &data, 0x84);
77 pNv->RamAmountKBytes = (((data >> 4) & 127) + 1) * 1024;
78 } else {
79 pNv->RamAmountKBytes =
80 (nvReadFB(pNv, NV_PFB_CSTATUS) & 0xFFF00000) >> 10;
81 }
82
83 if (pNv->RamAmountKBytes > 256*1024)
84 pNv->RamAmountKBytes = 256*1024;
85}
86
87void
88NVCommonSetup(ScrnInfoPtr pScrn)
89{
90 NVPtr pNv = NVPTR(pScrn);
91 uint16_t implementation = pNv->Chipset & 0x0ff0;
92
93 /* 0x01000000 is the size */
94 pci_device_map_range(pNv->PciInfo, pNv->IOAddress, 0x01000000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->REGS);
95 pci_device_map_range(pNv->PciInfo, pNv->VRAMPhysical, 0x10000, PCI_DEV_MAP_FLAG_WRITABLE, (void *)&pNv->FB_BAR);
96
97 pNv->alphaCursor = (pNv->NVArch >= 0x11);
98
99 pNv->twoHeads = (pNv->Architecture >= NV_ARCH_10) &&
100 (implementation != CHIPSET_NV10) &&
101 (implementation != CHIPSET_NV15) &&
102 (implementation != CHIPSET_NFORCE) &&
103 (implementation != CHIPSET_NV20);
104
105 pNv->gf4_disp_arch = pNv->twoHeads && implementation != CHIPSET_NV11;
106
107 /* nv30 and nv35 have two stage PLLs, but use only one register; they are dealt with separately */
108 pNv->two_reg_pll = (implementation == CHIPSET_NV31) ||
109 (implementation == CHIPSET_NV36) ||
110 (pNv->Architecture >= NV_ARCH_40);
111
112 pNv->WaitVSyncPossible = (pNv->Architecture >= NV_ARCH_10) &&
113 (implementation != CHIPSET_NV10);
114
115 pNv->BlendingPossible = ((pNv->Chipset & 0xffff) > CHIPSET_NV04);
116
117 /* look for known laptop chips */
118 /* FIXME still probably missing some ids (for randr12, pre-nv40 mobile should be auto-detected) */
119 switch(pNv->Chipset & 0xffff) {
120 case 0x0098:
121 case 0x0099:
122 case 0x00C8:
123 case 0x00C9:
124 case 0x00CC:
125 case 0x0112:
126 case 0x0144:
127 case 0x0146:
128 case 0x0148:
129 case 0x0149:
130 case 0x0160:
131 case 0x0164:
132 case 0x0166:
133 case 0x0167:
134 case 0x0168:
135 case 0x0169:
136 case 0x016B:
137 case 0x016C:
138 case 0x016D:
139 case 0x0174:
140 case 0x0175:
141 case 0x0176:
142 case 0x0177:
143 case 0x0179:
144 case 0x017C:
145 case 0x017D:
146 case 0x0186:
147 case 0x0187:
148 case 0x018D:
149 case 0x01D6:
150 case 0x01D7:
151 case 0x01D8:
152 case 0x0228:
153 case 0x0244:
154 case 0x0286:
155 case 0x028C:
156 case 0x0297:
157 case 0x0298:
158 case 0x0299:
159 case 0x0316:
160 case 0x0317:
161 case 0x031A:
162 case 0x031B:
163 case 0x031C:
164 case 0x031D:
165 case 0x031E:
166 case 0x031F:
167 case 0x0324:
168 case 0x0325:
169 case 0x0328:
170 case 0x0329:
171 case 0x032C:
172 case 0x032D:
173 case 0x0347:
174 case 0x0348:
175 case 0x0349:
176 case 0x034B:
177 case 0x034C:
178 case 0x0397:
179 case 0x0398:
180 case 0x039B:
181 pNv->Mobile = TRUE;
182 break;
183 default:
184 break;
185 }
186
187 if (pNv->twoHeads) {
188 pNv->vtOWNER = nouveau_hw_get_current_head(pScrn);
189
190 NV_TRACE(pScrn, "Initial CRTC_OWNER is %d\n", pNv->vtOWNER);
191
192 /* we need to ensure the heads are not tied henceforth, or
193 * reading any 8 bit reg on head B will fail.
194 * setting a single arbitrary head solves that */
195 NVSetOwner(pNv, 0);
196 }
197
198 /* Parse the bios to initialize the card */
199 if (!pNv->kms_enable)
200 NVParseBios(pScrn);
201
202 if (pNv->Architecture == NV_ARCH_04)
203 nv4GetConfig(pNv);
204 else
205 nv10GetConfig(pScrn);
206}
207
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 @@
17#error "This driver requires a DRI-enabled X server" 17#error "This driver requires a DRI-enabled X server"
18#endif 18#endif
19 19
20#include "nouveau_bios.h"
21
22#include "nouveau_ms.h"
23
24#include "nouveau_crtc.h"
25#include "nouveau_connector.h"
26#include "nouveau_output.h"
27
28#define NV_ARCH_03 0x03 20#define NV_ARCH_03 0x03
29#define NV_ARCH_04 0x04 21#define NV_ARCH_04 0x04
30#define NV_ARCH_10 0x10 22#define NV_ARCH_10 0x10
@@ -69,74 +61,31 @@
69#define CHIPSET_C512 0x03D0 61#define CHIPSET_C512 0x03D0
70#define CHIPSET_G73_BRIDGED 0x02E0 62#define CHIPSET_G73_BRIDGED 0x02E0
71 63
72
73#undef SetBit /* some input related header also includes a macro called SetBit, which gives a lot of warnings. */
74#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1) << (b))
75#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
76#define SetBF(mask,value) ((value) << (0?mask))
77#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
78#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
79#define SetBit(n) (1<<(n))
80#define Set8Bits(value) ((value)&0xff)
81
82/* NV50 */ 64/* NV50 */
83typedef enum ORNum {
84 DAC0 = 0,
85 DAC1 = 1,
86 DAC2 = 2,
87 SOR0 = 0,
88 SOR1 = 1,
89 SOR2 = 2,
90} ORNum;
91
92typedef struct _NVRec *NVPtr; 65typedef struct _NVRec *NVPtr;
93typedef struct _NVRec { 66typedef struct _NVRec {
94 struct nouveau_mode_state saved_regs;
95 struct nouveau_mode_state set_state;
96 uint32_t saved_vga_font[4][16384];
97 uint32_t Architecture; 67 uint32_t Architecture;
98 EntityInfoPtr pEnt; 68 EntityInfoPtr pEnt;
99 struct pci_device *PciInfo; 69 struct pci_device *PciInfo;
100 int Chipset; 70 int Chipset;
101 int NVArch; 71 int NVArch;
102 Bool Primary; 72 Bool Primary;
103 CARD32 IOAddress;
104 73
105 /* VRAM physical address */ 74 /* VRAM physical address */
106 unsigned long VRAMPhysical; 75 unsigned long VRAMPhysical;
107 /* Size of VRAM BAR */
108 unsigned long VRAMPhysicalSize;
109 /* Accesible VRAM size (by the GPU) */
110 unsigned long VRAMSize;
111 /* Mapped VRAM BAR */
112 void * VRAMMap;
113 /* Accessible AGP size */
114 unsigned long AGPSize;
115 76
116 /* Various pinned memory regions */ 77 /* Various pinned memory regions */
117 struct nouveau_bo * scanout; 78 struct nouveau_bo * scanout;
118 struct nouveau_bo * offscreen; 79 struct nouveau_bo * offscreen;
119 void * offscreen_map; 80 void * offscreen_map;
120 //struct nouveau_bo * FB_old; /* for KMS */
121 struct nouveau_bo * shadow[2]; /* for easy acces by exa */
122 struct nouveau_bo * Cursor;
123 struct nouveau_bo * Cursor2;
124 struct nouveau_bo * GART; 81 struct nouveau_bo * GART;
125 82
126 struct nvbios VBIOS;
127 struct nouveau_bios_info *vbios;
128 Bool NoAccel; 83 Bool NoAccel;
129 Bool HWCursor; 84 Bool HWCursor;
130 Bool FpScale;
131 Bool ShadowFB; 85 Bool ShadowFB;
132 unsigned char * ShadowPtr; 86 unsigned char * ShadowPtr;
133 int ShadowPitch; 87 int ShadowPitch;
134 uint32_t RamAmountKBytes;
135 88
136 volatile CARD32 *REGS;
137 volatile CARD32 *FB_BAR;
138
139 uint8_t cur_head;
140 ExaDriverPtr EXADriverPtr; 89 ExaDriverPtr EXADriverPtr;
141 Bool exa_driver_pixmaps; 90 Bool exa_driver_pixmaps;
142 Bool exa_force_cp; 91 Bool exa_force_cp;
@@ -146,48 +95,24 @@ typedef struct _NVRec {
146 CreateScreenResourcesProcPtr CreateScreenResources; 95 CreateScreenResourcesProcPtr CreateScreenResources;
147 CloseScreenProcPtr CloseScreen; 96 CloseScreenProcPtr CloseScreen;
148 /* Cursor */ 97 /* Cursor */
149 uint32_t curImage[256]; 98 uint32_t curImage[256];
150 /* I2C / DDC */ 99 void (*VideoTimerCallback)(ScrnInfoPtr, Time);
151 xf86Int10InfoPtr pInt10;
152 unsigned Int10Mode;
153 void (*VideoTimerCallback)(ScrnInfoPtr, Time);
154 XF86VideoAdaptorPtr overlayAdaptor; 100 XF86VideoAdaptorPtr overlayAdaptor;
155 XF86VideoAdaptorPtr blitAdaptor; 101 XF86VideoAdaptorPtr blitAdaptor;
156 XF86VideoAdaptorPtr textureAdaptor[2]; 102 XF86VideoAdaptorPtr textureAdaptor[2];
157 int videoKey; 103 int videoKey;
158 Bool FPDither;
159 int Mobile;
160 int vtOWNER;
161 OptionInfoPtr Options; 104 OptionInfoPtr Options;
162 bool alphaCursor;
163 bool twoHeads;
164 bool gf4_disp_arch;
165 bool two_reg_pll;
166 105
167 Bool LockedUp; 106 Bool LockedUp;
168 107
169 CARD32 currentRop; 108 CARD32 currentRop;
170 109
171 Bool WaitVSyncPossible;
172 Bool BlendingPossible;
173 DRIInfoPtr pDRIInfo; 110 DRIInfoPtr pDRIInfo;
174 drmVersionPtr pLibDRMVersion; 111 drmVersionPtr pLibDRMVersion;
175 drmVersionPtr pKernelDRMVersion; 112 drmVersionPtr pKernelDRMVersion;
176 113
177 Bool kms_enable;
178
179 I2CBusPtr pI2CBus[DCB_MAX_NUM_I2C_ENTRIES];
180 struct nouveau_encoder *encoders;
181
182#ifdef XF86DRM_MODE
183 void *drmmode; /* for KMS */ 114 void *drmmode; /* for KMS */
184 Bool allow_dpms; 115 Bool allow_dpms;
185#endif
186
187 nouveauCrtcPtr crtc[2];
188 nouveauOutputPtr output; /* this a linked list. */
189 /* Assume a connector can exist for each i2c bus. */
190 nouveauConnectorPtr connector[DCB_MAX_NUM_I2C_ENTRIES];
191 116
192 /* DRM interface */ 117 /* DRM interface */
193 struct nouveau_device *dev; 118 struct nouveau_device *dev;
@@ -228,15 +153,6 @@ typedef struct _NVRec {
228 153
229#define NVPTR(p) ((NVPtr)((p)->driverPrivate)) 154#define NVPTR(p) ((NVPtr)((p)->driverPrivate))
230 155
231#define nvReadCurVGA(pNv, reg) NVReadVgaCrtc(pNv, pNv->cur_head, reg)
232#define nvWriteCurVGA(pNv, reg, val) NVWriteVgaCrtc(pNv, pNv->cur_head, reg, val)
233
234#define nvReadCurRAMDAC(pNv, reg) NVReadRAMDAC(pNv, pNv->cur_head, reg)
235#define nvWriteCurRAMDAC(pNv, reg, val) NVWriteRAMDAC(pNv, pNv->cur_head, reg, val)
236
237#define nvReadCurCRTC(pNv, reg) NVReadCRTC(pNv, pNv->cur_head, reg)
238#define nvWriteCurCRTC(pNv, reg, val) NVWriteCRTC(pNv, pNv->cur_head, reg, val)
239
240typedef struct _NVPortPrivRec { 156typedef struct _NVPortPrivRec {
241 short brightness; 157 short brightness;
242 short contrast; 158 short contrast;
@@ -329,4 +245,40 @@ nouveau_pixmap_offset(PixmapPtr ppix)
329 return exaGetPixmapOffset(ppix); 245 return exaGetPixmapOffset(ppix);
330} 246}
331 247
248static inline uint32_t
249 nv_pitch_align(NVPtr pNv, uint32_t width, int bpp)
250{
251 int mask;
252
253 if (bpp == 15)
254 bpp = 16;
255 if (bpp == 24 || bpp == 30)
256 bpp = 8;
257
258 /* Alignment requirements taken from the Haiku driver */
259 if (pNv->Architecture == NV_ARCH_04)
260 mask = 128 / bpp - 1;
261 else
262 mask = 512 / bpp - 1;
263
264 return (width + mask) & ~mask;
265}
266
267/* nv04 cursor max dimensions of 32x32 (A1R5G5B5) */
268#define NV04_CURSOR_SIZE 32
269/* limit nv10 cursors to 64x64 (ARGB8) (we could go to 64x255) */
270#define NV10_CURSOR_SIZE 64
271
272static inline int nv_cursor_width(NVPtr pNv)
273{
274 return pNv->NVArch >= 0x10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE;
275}
276
277static inline int nv_cursor_pixels(NVPtr pNv)
278{
279 int width = nv_cursor_width(pNv);
280
281 return width * width;
282}
283
332#endif /* __NV_STRUCT_H__ */ 284#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 @@
1/* $XConsortium: nvreg.h /main/2 1996/10/28 05:13:41 kaleb $ */
2/*
3 * Copyright 1996-1997 David J. McKay
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * DAVID J. MCKAY BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nvreg.h,v 1.6 2002/01/25 21:56:06 tsi Exp $ */
25
26#ifndef __NVREG_H_
27#define __NVREG_H_
28
29#define NV_PMC_OFFSET 0x00000000
30#define NV_PMC_SIZE 0x00001000
31
32#define NV_PBUS_OFFSET 0x00001000
33#define NV_PBUS_SIZE 0x00001000
34
35#define NV_PFIFO_OFFSET 0x00002000
36#define NV_PFIFO_SIZE 0x00002000
37
38#define NV_HDIAG_OFFSET 0x00005000
39#define NV_HDIAG_SIZE 0x00001000
40
41#define NV_PRAM_OFFSET 0x00006000
42#define NV_PRAM_SIZE 0x00001000
43
44#define NV_PVIDEO_OFFSET 0x00008000
45#define NV_PVIDEO_SIZE 0x00001000
46
47#define NV_PTIMER_OFFSET 0x00009000
48#define NV_PTIMER_SIZE 0x00001000
49
50#define NV_PPM_OFFSET 0x0000A000
51#define NV_PPM_SIZE 0x00001000
52
53#define NV_PRMVGA_OFFSET 0x000A0000
54#define NV_PRMVGA_SIZE 0x00020000
55
56#define NV_PRMVIO0_OFFSET 0x000C0000
57#define NV_PRMVIO_SIZE 0x00002000
58#define NV_PRMVIO1_OFFSET 0x000C2000
59
60#define NV_PFB_OFFSET 0x00100000
61#define NV_PFB_SIZE 0x00001000
62
63#define NV_PEXTDEV_OFFSET 0x00101000
64#define NV_PEXTDEV_SIZE 0x00001000
65
66#define NV_PME_OFFSET 0x00200000
67#define NV_PME_SIZE 0x00001000
68
69#define NV_PROM_OFFSET 0x00300000
70#define NV_PROM_SIZE 0x00010000
71
72#define NV_PGRAPH_OFFSET 0x00400000
73#define NV_PGRAPH_SIZE 0x00010000
74
75#define NV_PCRTC0_OFFSET 0x00600000
76#define NV_PCRTC0_SIZE 0x00002000 /* empirical */
77
78#define NV_PRMCIO0_OFFSET 0x00601000
79#define NV_PRMCIO_SIZE 0x00002000
80#define NV_PRMCIO1_OFFSET 0x00603000
81
82#define NV50_DISPLAY_OFFSET 0x00610000
83#define NV50_DISPLAY_SIZE 0x0000FFFF
84
85#define NV_PRAMDAC0_OFFSET 0x00680000
86#define NV_PRAMDAC0_SIZE 0x00002000
87
88#define NV_PRMDIO0_OFFSET 0x00681000
89#define NV_PRMDIO_SIZE 0x00002000
90#define NV_PRMDIO1_OFFSET 0x00683000
91
92#define NV_PRAMIN_OFFSET 0x00700000
93#define NV_PRAMIN_SIZE 0x00100000
94
95#define NV_FIFO_OFFSET 0x00800000
96#define NV_FIFO_SIZE 0x00800000
97
98#define NV_PMC_BOOT_0 0x00000000
99#define NV_PMC_ENABLE 0x00000200
100
101#define NV_VIO_VSE2 0x000003c3
102#define NV_VIO_SRX 0x000003c4
103
104#define NV_CIO_CRX__COLOR 0x000003d4
105#define NV_CIO_CR__COLOR 0x000003d5
106
107#define NV_PBUS_DEBUG_1 0x00001084
108#define NV_PBUS_DEBUG_4 0x00001098
109#define NV_PBUS_DEBUG_DUALHEAD_CTL 0x000010f0
110#define NV_PBUS_POWERCTRL_1 0x00001584
111#define NV_PBUS_POWERCTRL_2 0x00001588
112#define NV_PBUS_POWERCTRL_4 0x00001590
113#define NV_PBUS_PCI_NV_19 0x0000184C
114#define NV_PBUS_PCI_NV_20 0x00001850
115# define NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0)
116# define NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0)
117
118#define NV_PFIFO_RAMHT 0x00002210
119
120#define NV_PRMVIO_MISC__WRITE 0x000c03c2
121#define NV_PRMVIO_SRX 0x000c03c4
122#define NV_PRMVIO_SR 0x000c03c5
123# define NV_VIO_SR_RESET_INDEX 0x00
124# define NV_VIO_SR_CLOCK_INDEX 0x01
125# define NV_VIO_SR_PLANE_MASK_INDEX 0x02
126# define NV_VIO_SR_CHAR_MAP_INDEX 0x03
127# define NV_VIO_SR_MEM_MODE_INDEX 0x04
128#define NV_PRMVIO_MISC__READ 0x000c03cc
129#define NV_PRMVIO_GRX 0x000c03ce
130#define NV_PRMVIO_GX 0x000c03cf
131# define NV_VIO_GX_SR_INDEX 0x00
132# define NV_VIO_GX_SREN_INDEX 0x01
133# define NV_VIO_GX_CCOMP_INDEX 0x02
134# define NV_VIO_GX_ROP_INDEX 0x03
135# define NV_VIO_GX_READ_MAP_INDEX 0x04
136# define NV_VIO_GX_MODE_INDEX 0x05
137# define NV_VIO_GX_MISC_INDEX 0x06
138# define NV_VIO_GX_DONT_CARE_INDEX 0x07
139# define NV_VIO_GX_BIT_MASK_INDEX 0x08
140
141#define NV_PFB_BOOT_0 0x00100000
142#define NV_PFB_CFG0 0x00100200
143#define NV_PFB_CFG1 0x00100204
144#define NV_PFB_CSTATUS 0x0010020C
145#define NV_PFB_REFCTRL 0x00100210
146# define NV_PFB_REFCTRL_VALID_1 (1 << 31)
147#define NV_PFB_PAD 0x0010021C
148# define NV_PFB_PAD_CKE_NORMAL (1 << 0)
149#define NV_PFB_TILE_NV10 0x00100240
150#define NV_PFB_TILE_SIZE_NV10 0x00100244
151#define NV_PFB_REF 0x001002D0
152# define NV_PFB_REF_CMD_REFRESH (1 << 0)
153#define NV_PFB_PRE 0x001002D4
154# define NV_PFB_PRE_CMD_PRECHARGE (1 << 0)
155#define NV_PFB_CLOSE_PAGE2 0x0010033C
156#define NV_PFB_TILE_NV40 0x00100600
157#define NV_PFB_TILE_SIZE_NV40 0x00100604
158
159#define NV_PEXTDEV_BOOT_0 0x00101000
160# define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT (8 << 12)
161#define NV_PEXTDEV_BOOT_3 0x0010100c
162
163#define NV_PCRTC_INTR_0 0x00600100
164# define NV_PCRTC_INTR_0_VBLANK (1 << 0)
165#define NV_PCRTC_INTR_EN_0 0x00600140
166#define NV_PCRTC_START 0x00600800
167#define NV_PCRTC_CONFIG 0x00600804
168# define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0)
169# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0)
170#define NV_PCRTC_CURSOR_CONFIG 0x00600810
171# define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0)
172# define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4)
173# define NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM (1 << 8)
174# define NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32 (1 << 12)
175# define NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 (1 << 16)
176# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_32 (2 << 24)
177# define NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 (4 << 24)
178# define NV_PCRTC_CURSOR_CONFIG_CUR_BLEND_ALPHA (1 << 28)
179
180/* note: PCRTC_GPIO is not available on nv10, and in fact aliases 0x600810 */
181#define NV_PCRTC_GPIO 0x00600818
182#define NV_PCRTC_GPIO_EXT 0x0060081c
183#define NV_PCRTC_830 0x00600830
184#define NV_PCRTC_834 0x00600834
185#define NV_PCRTC_850 0x00600850
186#define NV_PCRTC_ENGINE_CTRL 0x00600860
187# define NV_CRTC_FSEL_I2C (1 << 4)
188# define NV_CRTC_FSEL_OVERLAY (1 << 12)
189
190#define NV_PRMCIO_ARX 0x006013c0
191#define NV_PRMCIO_AR__WRITE 0x006013c0
192#define NV_PRMCIO_AR__READ 0x006013c1
193# define NV_CIO_AR_MODE_INDEX 0x10
194# define NV_CIO_AR_OSCAN_INDEX 0x11
195# define NV_CIO_AR_PLANE_INDEX 0x12
196# define NV_CIO_AR_HPP_INDEX 0x13
197# define NV_CIO_AR_CSEL_INDEX 0x14
198#define NV_PRMCIO_INP0 0x006013c2
199#define NV_PRMCIO_CRX__COLOR 0x006013d4
200#define NV_PRMCIO_CR__COLOR 0x006013d5
201 /* Standard VGA CRTC registers */
202# define NV_CIO_CR_HDT_INDEX 0x00 /* horizontal display total */
203# define NV_CIO_CR_HDE_INDEX 0x01 /* horizontal display end */
204# define NV_CIO_CR_HBS_INDEX 0x02 /* horizontal blanking start */
205# define NV_CIO_CR_HBE_INDEX 0x03 /* horizontal blanking end */
206# define NV_CIO_CR_HBE_4_0 4:0
207# define NV_CIO_CR_HRS_INDEX 0x04 /* horizontal retrace start */
208# define NV_CIO_CR_HRE_INDEX 0x05 /* horizontal retrace end */
209# define NV_CIO_CR_HRE_4_0 4:0
210# define NV_CIO_CR_HRE_HBE_5 7:7
211# define NV_CIO_CR_VDT_INDEX 0x06 /* vertical display total */
212# define NV_CIO_CR_OVL_INDEX 0x07 /* overflow bits */
213# define NV_CIO_CR_OVL_VDT_8 0:0
214# define NV_CIO_CR_OVL_VDE_8 1:1
215# define NV_CIO_CR_OVL_VRS_8 2:2
216# define NV_CIO_CR_OVL_VBS_8 3:3
217# define NV_CIO_CR_OVL_VDT_9 5:5
218# define NV_CIO_CR_OVL_VDE_9 6:6
219# define NV_CIO_CR_OVL_VRS_9 7:7
220# define NV_CIO_CR_RSAL_INDEX 0x08 /* normally "preset row scan" */
221# define NV_CIO_CR_CELL_HT_INDEX 0x09 /* cell height?! normally "max scan line" */
222# define NV_CIO_CR_CELL_HT_VBS_9 5:5
223# define NV_CIO_CR_CELL_HT_SCANDBL 7:7
224# define NV_CIO_CR_CURS_ST_INDEX 0x0a /* cursor start */
225# define NV_CIO_CR_CURS_END_INDEX 0x0b /* cursor end */
226# define NV_CIO_CR_SA_HI_INDEX 0x0c /* screen start address high */
227# define NV_CIO_CR_SA_LO_INDEX 0x0d /* screen start address low */
228# define NV_CIO_CR_TCOFF_HI_INDEX 0x0e /* cursor offset high */
229# define NV_CIO_CR_TCOFF_LO_INDEX 0x0f /* cursor offset low */
230# define NV_CIO_CR_VRS_INDEX 0x10 /* vertical retrace start */
231# define NV_CIO_CR_VRE_INDEX 0x11 /* vertical retrace end */
232# define NV_CIO_CR_VRE_3_0 3:0
233# define NV_CIO_CR_VDE_INDEX 0x12 /* vertical display end */
234# define NV_CIO_CR_OFFSET_INDEX 0x13 /* sets screen pitch */
235# define NV_CIO_CR_ULINE_INDEX 0x14 /* underline location */
236# define NV_CIO_CR_VBS_INDEX 0x15 /* vertical blank start */
237# define NV_CIO_CR_VBE_INDEX 0x16 /* vertical blank end */
238# define NV_CIO_CR_MODE_INDEX 0x17 /* crtc mode control */
239# define NV_CIO_CR_LCOMP_INDEX 0x18 /* line compare */
240 /* Extended VGA CRTC registers */
241# define NV_CIO_CRE_RPC0_INDEX 0x19 /* repaint control 0 */
242# define NV_CIO_CRE_RPC0_OFFSET_10_8 7:5
243# define NV_CIO_CRE_RPC1_INDEX 0x1a /* repaint control 1 */
244# define NV_CIO_CRE_RPC1_LARGE 2:2
245# define NV_CIO_CRE_FF_INDEX 0x1b /* fifo control */
246# define NV_CIO_CRE_ENH_INDEX 0x1c /* enhanced? */
247# define NV_CIO_SR_LOCK_INDEX 0x1f /* crtc lock */
248# define NV_CIO_SR_UNLOCK_RW_VALUE 0x57
249# define NV_CIO_SR_LOCK_VALUE 0x99
250# define NV_CIO_CRE_FFLWM__INDEX 0x20 /* fifo low water mark */
251# define NV_CIO_CRE_21 0x21 /* vga shadow crtc lock */
252# define NV_CIO_CRE_LSR_INDEX 0x25 /* ? */
253# define NV_CIO_CRE_LSR_VDT_10 0:0
254# define NV_CIO_CRE_LSR_VDE_10 1:1
255# define NV_CIO_CRE_LSR_VRS_10 2:2
256# define NV_CIO_CRE_LSR_VBS_10 3:3
257# define NV_CIO_CRE_LSR_HBE_6 4:4
258# define NV_CIO_CR_ARX_INDEX 0x26 /* attribute index -- ro copy of 0x60.3c0 */
259# define NV_CIO_CRE_CHIP_ID_INDEX 0x27 /* chip revision */
260# define NV_CIO_CRE_PIXEL_INDEX 0x28
261# define NV_CIO_CRE_PIXEL_FORMAT 1:0
262# define NV_CIO_CRE_HEB__INDEX 0x2d /* horizontal extra bits? */
263# define NV_CIO_CRE_HEB_HDT_8 0:0
264# define NV_CIO_CRE_HEB_HDE_8 1:1
265# define NV_CIO_CRE_HEB_HBS_8 2:2
266# define NV_CIO_CRE_HEB_HRS_8 3:3
267# define NV_CIO_CRE_HEB_ILC_8 4:4
268# define NV_CIO_CRE_2E 0x2e /* some scratch or dummy reg to force writes to sink in */
269# define NV_CIO_CRE_HCUR_ADDR2_INDEX 0x2f /* cursor */
270# define NV_CIO_CRE_HCUR_ADDR0_INDEX 0x30 /* pixmap */
271# define NV_CIO_CRE_HCUR_ADDR0_ADR 6:0
272# define NV_CIO_CRE_HCUR_ASI 7:7
273# define NV_CIO_CRE_HCUR_ADDR1_INDEX 0x31 /* address */
274# define NV_CIO_CRE_HCUR_ADDR1_ENABLE 0:0
275# define NV_CIO_CRE_HCUR_ADDR1_CUR_DBL 1:1
276# define NV_CIO_CRE_HCUR_ADDR1_ADR 7:2
277# define NV_CIO_CRE_LCD__INDEX 0x33
278# define NV_CIO_CRE_LCD_LCD_SELECT 0:0
279# define NV_CIO_CRE_DDC0_STATUS__INDEX 0x36
280# define NV_CIO_CRE_DDC0_WR__INDEX 0x37
281# define NV_CIO_CRE_ILACE__INDEX 0x39 /* interlace */
282# define NV_CIO_CRE_SCRATCH3__INDEX 0x3b
283# define NV_CIO_CRE_SCRATCH4__INDEX 0x3c
284# define NV_CIO_CRE_DDC_STATUS__INDEX 0x3e
285# define NV_CIO_CRE_DDC_WR__INDEX 0x3f
286# define NV_CIO_CRE_EBR_INDEX 0x41 /* extra bits ? (vertical) */
287# define NV_CIO_CRE_EBR_VDT_11 0:0
288# define NV_CIO_CRE_EBR_VDE_11 2:2
289# define NV_CIO_CRE_EBR_VRS_11 4:4
290# define NV_CIO_CRE_EBR_VBS_11 6:6
291# define NV_CIO_CRE_44 0x44 /* head control */
292# define NV_CIO_CRE_CSB 0x45 /* colour saturation boost */
293# define NV_CIO_CRE_RCR 0x46
294# define NV_CIO_CRE_RCR_ENDIAN_BIG 7:7
295# define NV_CIO_CRE_47 0x47 /* extended fifo lwm, used on nv30+ */
296# define NV_CIO_CRE_4B 0x4b /* given patterns in 0x[2-3][a-c] regs, probably scratch 6 */
297# define NV_CIO_CRE_TVOUT_LATENCY 0x52
298# define NV_CIO_CRE_53 0x53 /* `fp_htiming' according to Haiku */
299# define NV_CIO_CRE_54 0x54 /* `fp_vtiming' according to Haiku */
300# define NV_CIO_CRE_57 0x57 /* index reg for cr58 */
301# define NV_CIO_CRE_58 0x58 /* data reg for cr57 */
302# define NV_CIO_CRE_59 0x59 /* related to on/off-chip-ness of digital outputs */
303# define NV_CIO_CRE_5B 0x5B /* newer colour saturation reg */
304# define NV_CIO_CRE_85 0x85
305# define NV_CIO_CRE_86 0x86
306#define NV_PRMCIO_INP0__COLOR 0x006013da
307
308#define NV_PRAMDAC_CU_START_POS 0x00680300
309# define NV_PRAMDAC_CU_START_POS_X 15:0
310# define NV_PRAMDAC_CU_START_POS_Y 31:16
311#define NV_RAMDAC_NV10_CURSYNC 0x00680404
312
313#define NV_PRAMDAC_NVPLL_COEFF 0x00680500
314#define NV_PRAMDAC_MPLL_COEFF 0x00680504
315#define NV_PRAMDAC_VPLL_COEFF 0x00680508
316# define NV30_RAMDAC_ENABLE_VCO2 (8 << 4)
317
318#define NV_PRAMDAC_PLL_COEFF_SELECT 0x0068050c
319# define NV_RAMDAC_PLL_SELECT_USE_VPLL2_TRUE (4 << 0)
320# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL (1 << 8)
321# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_VPLL (2 << 8)
322# define NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL (4 << 8)
323# define NV_RAMDAC_PLL_SELECT_PLL_SOURCE_VPLL2 (8 << 8)
324# define NV_PRAMDAC_PLL_COEFF_SELECT_VCLK_RATIO_DB2 (1 << 28)
325# define NV_RAMDAC_PLL_SELECT_VCLK2_RATIO_DB2 (2 << 28)
326
327#define NV_PRAMDAC_PLL_SETUP_CONTROL 0x00680510
328#define NV_RAMDAC_VPLL2 0x00680520
329#define NV_PRAMDAC_SEL_CLK 0x00680524
330#define NV_RAMDAC_DITHER_NV11 0x00680528
331#define NV_PRAMDAC_DACCLK 0x0068052c
332# define NV_PRAMDAC_DACCLK_SEL_DACCLK (1 << 0)
333
334#define NV_RAMDAC_NVPLL_B 0x00680570
335#define NV_RAMDAC_MPLL_B 0x00680574
336#define NV_RAMDAC_VPLL_B 0x00680578
337#define NV_RAMDAC_VPLL2_B 0x0068057c
338# define NV31_RAMDAC_ENABLE_VCO2 (8 << 28)
339#define NV_PRAMDAC_580 0x00680580
340# define NV_RAMDAC_580_VPLL1_ACTIVE (1 << 8)
341# define NV_RAMDAC_580_VPLL2_ACTIVE (1 << 28)
342
343#define NV_PRAMDAC_GENERAL_CONTROL 0x00680600
344# define NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON (3 << 4)
345# define NV_PRAMDAC_GENERAL_CONTROL_VGA_STATE_SEL (1 << 8)
346# define NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL (1 << 12)
347# define NV_PRAMDAC_GENERAL_CONTROL_TERMINATION_75OHM (2 << 16)
348# define NV_PRAMDAC_GENERAL_CONTROL_BPC_8BITS (1 << 20)
349# define NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG (2 << 28)
350#define NV_PRAMDAC_TEST_CONTROL 0x00680608
351# define NV_PRAMDAC_TEST_CONTROL_TP_INS_EN_ASSERTED (1 << 12)
352# define NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF (1 << 16)
353# define NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI (1 << 28)
354#define NV_PRAMDAC_TESTPOINT_DATA 0x00680610
355# define NV_PRAMDAC_TESTPOINT_DATA_NOTBLANK (8 << 28)
356#define NV_PRAMDAC_630 0x00680630
357#define NV_PRAMDAC_634 0x00680634
358
359#define NV_PRAMDAC_FP_VDISPLAY_END 0x00680800
360#define NV_PRAMDAC_FP_VTOTAL 0x00680804
361#define NV_PRAMDAC_FP_VCRTC 0x00680808
362#define NV_PRAMDAC_FP_VSYNC_START 0x0068080c
363#define NV_PRAMDAC_FP_VSYNC_END 0x00680810
364#define NV_PRAMDAC_FP_VVALID_START 0x00680814
365#define NV_PRAMDAC_FP_VVALID_END 0x00680818
366#define NV_PRAMDAC_FP_HDISPLAY_END 0x00680820
367#define NV_PRAMDAC_FP_HTOTAL 0x00680824
368#define NV_PRAMDAC_FP_HCRTC 0x00680828
369#define NV_PRAMDAC_FP_HSYNC_START 0x0068082c
370#define NV_PRAMDAC_FP_HSYNC_END 0x00680830
371#define NV_PRAMDAC_FP_HVALID_START 0x00680834
372#define NV_PRAMDAC_FP_HVALID_END 0x00680838
373
374#define NV_RAMDAC_FP_DITHER 0x0068083c
375#define NV_PRAMDAC_FP_TG_CONTROL 0x00680848
376# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS (1 << 0)
377# define NV_PRAMDAC_FP_TG_CONTROL_VSYNC_DISABLE (2 << 0)
378# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS (1 << 4)
379# define NV_PRAMDAC_FP_TG_CONTROL_HSYNC_DISABLE (2 << 4)
380# define NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE (0 << 8)
381# define NV_PRAMDAC_FP_TG_CONTROL_MODE_CENTER (1 << 8)
382# define NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE (2 << 8)
383# define NV_PRAMDAC_FP_TG_CONTROL_READ_PROG (1 << 20)
384# define NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12 (1 << 24)
385# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS (1 << 28)
386# define NV_PRAMDAC_FP_TG_CONTROL_DISPEN_DISABLE (2 << 28)
387#define NV_PRAMDAC_850 0x00680850
388#define NV_PRAMDAC_85C 0x0068085c
389#define NV_PRAMDAC_FP_DEBUG_0 0x00680880
390# define NV_PRAMDAC_FP_DEBUG_0_XSCALE_ENABLE (1 << 0)
391# define NV_PRAMDAC_FP_DEBUG_0_YSCALE_ENABLE (1 << 4)
392/* This doesn't seem to be essential for tmds, but still often set */
393# define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED (8 << 4)
394# define NV_PRAMDAC_FP_DEBUG_0_XINTERP_BILINEAR (1 << 8)
395# define NV_PRAMDAC_FP_DEBUG_0_YINTERP_BILINEAR (1 << 12)
396# define NV_PRAMDAC_FP_DEBUG_0_XWEIGHT_ROUND (1 << 20)
397# define NV_PRAMDAC_FP_DEBUG_0_YWEIGHT_ROUND (1 << 24)
398# define NV_PRAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1 << 28)
399#define NV_PRAMDAC_FP_DEBUG_1 0x00680884
400# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_VALUE 11:0
401# define NV_PRAMDAC_FP_DEBUG_1_XSCALE_TESTMODE_ENABLE (1 << 12)
402# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_VALUE 27:16
403# define NV_PRAMDAC_FP_DEBUG_1_YSCALE_TESTMODE_ENABLE (1 << 28)
404#define NV_PRAMDAC_FP_DEBUG_2 0x00680888
405#define NV_PRAMDAC_FP_DEBUG_3 0x0068088C
406
407/* see NV_PRAMDAC_INDIR_TMDS in rules.xml */
408#define NV_PRAMDAC_FP_TMDS_CONTROL 0x006808b0
409# define NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE (1 << 16)
410#define NV_PRAMDAC_FP_TMDS_DATA 0x006808b4
411
412/* Some kind of switch */
413#define NV_PRAMDAC_900 0x00680900
414#define NV_PRAMDAC_A20 0x00680A20
415#define NV_PRAMDAC_A24 0x00680A24
416#define NV_PRAMDAC_A34 0x00680A34
417
418/* names fabricated from NV_USER_DAC info */
419#define NV_PRMDIO_PIXEL_MASK 0x006813c6
420# define NV_PRMDIO_PIXEL_MASK_MASK 0xff
421#define NV_PRMDIO_READ_MODE_ADDRESS 0x006813c7
422#define NV_PRMDIO_WRITE_MODE_ADDRESS 0x006813c8
423#define NV_PRMDIO_PALETTE_DATA 0x006813c9
424
425#define NV_PGRAPH_DEBUG_0 0x00400080
426#define NV_PGRAPH_DEBUG_1 0x00400084
427#define NV_PGRAPH_DEBUG_2_NV04 0x00400088
428#define NV_PGRAPH_DEBUG_2 0x00400620
429#define NV_PGRAPH_DEBUG_3 0x0040008c
430#define NV_PGRAPH_DEBUG_4 0x00400090
431#define NV_PGRAPH_INTR 0x00400100
432#define NV_PGRAPH_INTR_EN 0x00400140
433#define NV_PGRAPH_CTX_CONTROL 0x00400144
434#define NV_PGRAPH_CTX_CONTROL_NV04 0x00400170
435#define NV_PGRAPH_ABS_UCLIP_XMIN 0x0040053C
436#define NV_PGRAPH_ABS_UCLIP_YMIN 0x00400540
437#define NV_PGRAPH_ABS_UCLIP_XMAX 0x00400544
438#define NV_PGRAPH_ABS_UCLIP_YMAX 0x00400548
439#define NV_PGRAPH_BETA_AND 0x00400608
440#define NV_PGRAPH_LIMIT_VIOL_PIX 0x00400610
441#define NV_PGRAPH_BOFFSET0 0x00400640
442#define NV_PGRAPH_BOFFSET1 0x00400644
443#define NV_PGRAPH_BOFFSET2 0x00400648
444#define NV_PGRAPH_BLIMIT0 0x00400684
445#define NV_PGRAPH_BLIMIT1 0x00400688
446#define NV_PGRAPH_BLIMIT2 0x0040068c
447#define NV_PGRAPH_STATUS 0x00400700
448#define NV_PGRAPH_SURFACE 0x00400710
449#define NV_PGRAPH_STATE 0x00400714
450#define NV_PGRAPH_FIFO 0x00400720
451#define NV_PGRAPH_PATTERN_SHAPE 0x00400810
452#define NV_PGRAPH_TILE 0x00400b00
453
454#define NV_PVIDEO_INTR_EN 0x00008140
455#define NV_PVIDEO_BUFFER 0x00008700
456#define NV_PVIDEO_STOP 0x00008704
457#define NV_PVIDEO_UVPLANE_BASE(buff) (0x00008800+(buff)*4)
458#define NV_PVIDEO_UVPLANE_LIMIT(buff) (0x00008808+(buff)*4)
459#define NV_PVIDEO_UVPLANE_OFFSET_BUFF(buff) (0x00008820+(buff)*4)
460#define NV_PVIDEO_BASE(buff) (0x00008900+(buff)*4)
461#define NV_PVIDEO_LIMIT(buff) (0x00008908+(buff)*4)
462#define NV_PVIDEO_LUMINANCE(buff) (0x00008910+(buff)*4)
463#define NV_PVIDEO_CHROMINANCE(buff) (0x00008918+(buff)*4)
464#define NV_PVIDEO_OFFSET_BUFF(buff) (0x00008920+(buff)*4)
465#define NV_PVIDEO_SIZE_IN(buff) (0x00008928+(buff)*4)
466#define NV_PVIDEO_POINT_IN(buff) (0x00008930+(buff)*4)
467#define NV_PVIDEO_DS_DX(buff) (0x00008938+(buff)*4)
468#define NV_PVIDEO_DT_DY(buff) (0x00008940+(buff)*4)
469#define NV_PVIDEO_POINT_OUT(buff) (0x00008948+(buff)*4)
470#define NV_PVIDEO_SIZE_OUT(buff) (0x00008950+(buff)*4)
471#define NV_PVIDEO_FORMAT(buff) (0x00008958+(buff)*4)
472# define NV_PVIDEO_FORMAT_PLANAR (1 << 0)
473# define NV_PVIDEO_FORMAT_COLOR_LE_CR8YB8CB8YA8 (1 << 16)
474# define NV_PVIDEO_FORMAT_DISPLAY_COLOR_KEY (1 << 20)
475# define NV_PVIDEO_FORMAT_MATRIX_ITURBT709 (1 << 24)
476#define NV_PVIDEO_COLOR_KEY 0x00008B00
477
478/* NV04 overlay defines from VIDIX & Haiku */
479#define NV_PVIDEO_INTR_EN_0 0x00680140
480#define NV_PVIDEO_STEP_SIZE 0x00680200
481#define NV_PVIDEO_CONTROL_Y 0x00680204
482#define NV_PVIDEO_CONTROL_X 0x00680208
483#define NV_PVIDEO_BUFF0_START_ADDRESS 0x0068020c
484#define NV_PVIDEO_BUFF0_PITCH_LENGTH 0x00680214
485#define NV_PVIDEO_BUFF0_OFFSET 0x0068021c
486#define NV_PVIDEO_BUFF1_START_ADDRESS 0x00680210
487#define NV_PVIDEO_BUFF1_PITCH_LENGTH 0x00680218
488#define NV_PVIDEO_BUFF1_OFFSET 0x00680220
489#define NV_PVIDEO_OE_STATE 0x00680224
490#define NV_PVIDEO_SU_STATE 0x00680228
491#define NV_PVIDEO_RM_STATE 0x0068022c
492#define NV_PVIDEO_WINDOW_START 0x00680230
493#define NV_PVIDEO_WINDOW_SIZE 0x00680234
494#define NV_PVIDEO_FIFO_THRES_SIZE 0x00680238
495#define NV_PVIDEO_FIFO_BURST_LENGTH 0x0068023c
496#define NV_PVIDEO_KEY 0x00680240
497#define NV_PVIDEO_OVERLAY 0x00680244
498#define NV_PVIDEO_RED_CSC_OFFSET 0x00680280
499#define NV_PVIDEO_GREEN_CSC_OFFSET 0x00680284
500#define NV_PVIDEO_BLUE_CSC_OFFSET 0x00680288
501#define NV_PVIDEO_CSC_ADJUST 0x0068028c
502
503#endif