blob: 03a7c1e9ce38ae4d619fc494e578588982e510b5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
3 *
4 * Copyright 2004 Antonino Daplas <adaplas@pol.net>
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive
8 * for more details.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/errno.h>
16#include <linux/string.h>
17#include <linux/mm.h>
18#include <linux/tty.h>
19#include <linux/slab.h>
20#include <linux/delay.h>
21#include <linux/fb.h>
22#include <linux/init.h>
23#include <linux/pci.h>
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -080024#include <linux/console.h>
Michael Hanselmann5474c122006-06-25 05:47:08 -070025#include <linux/backlight.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#ifdef CONFIG_MTRR
27#include <asm/mtrr.h>
28#endif
29#ifdef CONFIG_PPC_OF
30#include <asm/prom.h>
31#include <asm/pci-bridge.h>
32#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include "nv_local.h"
35#include "nv_type.h"
36#include "nv_proto.h"
37#include "nv_dma.h"
38
39#ifndef CONFIG_PCI /* sanity check */
40#error This driver requires PCI support.
41#endif
42
43#undef CONFIG_FB_NVIDIA_DEBUG
44#ifdef CONFIG_FB_NVIDIA_DEBUG
45#define NVTRACE printk
46#else
47#define NVTRACE if (0) printk
48#endif
49
50#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
51#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
52
53#ifdef CONFIG_FB_NVIDIA_DEBUG
54#define assert(expr) \
55 if (!(expr)) { \
56 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
57 #expr,__FILE__,__FUNCTION__,__LINE__); \
58 BUG(); \
59 }
60#else
61#define assert(expr)
62#endif
63
64#define PFX "nvidiafb: "
65
66/* HW cursor parameters */
67#define MAX_CURS 32
68
69static struct pci_device_id nvidiafb_pci_tbl[] = {
70 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
71 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
72 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
73 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
74 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
75 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
76 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
77 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
78 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
79 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
80 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
81 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
82 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
83 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
84 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
85 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
86 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
87 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
88 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
89 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
90 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
91 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
92 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
93 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
94 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
95 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
96 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
97 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
98 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
99 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
100 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
101 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
102 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
103 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
104 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
105 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
106 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
107 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
108 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
109 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
110 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
111 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
112 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
113 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
114 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
115 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
116 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
117 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
118 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
119 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
120 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
121 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
122 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
123 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
124 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
126 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
127 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
128 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
129 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
130 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
131 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
132 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
133 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
134 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
135 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
136 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
137 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
138 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
139 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Antonino A. Daplasbc7fc062006-02-11 17:56:07 -0800140 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
141 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
143 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
144 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
145 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
146 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
147 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
148 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
149 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
150 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
151 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
152 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
153 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
154 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
155 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
156 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
157 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
158 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
159 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
160 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
161 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
162 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
163 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
164 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
165 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
166 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
167 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
168 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
169 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
170 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
171 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
172 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
173 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
174 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
175 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
176 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
177 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
178 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
179 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
180 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
181 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
182 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
183 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
184 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
185 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
186 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
187 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
188 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
189 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
190 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
191 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
192 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
193 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
194 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
195 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
196 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
197 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
198 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
199 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
200 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
201 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
202 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
203 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
204 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
205 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
206 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
207 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
208 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
209 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
210 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
211 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
212 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
213 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
214 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
215 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
216 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
217 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
218 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
219 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
220 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
221 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
222 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
223 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
224 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
225 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
226 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
227 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
228 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
229 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
230 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
231 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
232 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
233 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
234 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
235 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
236 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
237 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
238 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
239 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
240 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
241 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
242 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
243 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
244 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
245 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
246 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
247 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
248 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
249 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
250 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
251 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
252 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
253 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
254 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
255 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
256 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
257 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
258 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
259 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
260 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
261 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
262 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
263 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
264 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
265 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
266 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
267 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
268 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
269 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
270 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
271 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
272 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
273 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
274 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
275 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
276 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
277 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
278 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
279 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
280 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
281 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
282 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
283 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
284 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
285 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
286 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
287 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Antonino A. Daplasc549dc62006-01-09 20:53:33 -0800288 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
289 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
290 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
291 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
292 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
293 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
294 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
295 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
296 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
297 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Pavel Roskined498432006-03-27 01:17:36 -0800298 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280,
299 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 {PCI_VENDOR_ID_NVIDIA, 0x0252,
301 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
302 {PCI_VENDOR_ID_NVIDIA, 0x0313,
303 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
304 {PCI_VENDOR_ID_NVIDIA, 0x0316,
305 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
306 {PCI_VENDOR_ID_NVIDIA, 0x0317,
307 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
308 {PCI_VENDOR_ID_NVIDIA, 0x031D,
309 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
310 {PCI_VENDOR_ID_NVIDIA, 0x031E,
311 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
312 {PCI_VENDOR_ID_NVIDIA, 0x031F,
313 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
314 {PCI_VENDOR_ID_NVIDIA, 0x0329,
315 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
316 {PCI_VENDOR_ID_NVIDIA, 0x032F,
317 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
318 {PCI_VENDOR_ID_NVIDIA, 0x0345,
319 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
320 {PCI_VENDOR_ID_NVIDIA, 0x0349,
321 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
322 {PCI_VENDOR_ID_NVIDIA, 0x034B,
323 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
324 {PCI_VENDOR_ID_NVIDIA, 0x034F,
325 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
326 {PCI_VENDOR_ID_NVIDIA, 0x00c0,
327 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
328 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
329 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
330 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
331 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
332 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
333 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
334 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
335 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
336 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
337 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
338 {PCI_VENDOR_ID_NVIDIA, 0x00cd,
339 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
340 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
341 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
342 {PCI_VENDOR_ID_NVIDIA, 0x0142,
343 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
344 {PCI_VENDOR_ID_NVIDIA, 0x0143,
345 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
346 {PCI_VENDOR_ID_NVIDIA, 0x0144,
347 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
348 {PCI_VENDOR_ID_NVIDIA, 0x0145,
349 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
350 {PCI_VENDOR_ID_NVIDIA, 0x0146,
351 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
352 {PCI_VENDOR_ID_NVIDIA, 0x0147,
353 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
354 {PCI_VENDOR_ID_NVIDIA, 0x0148,
355 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
356 {PCI_VENDOR_ID_NVIDIA, 0x0149,
357 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
358 {PCI_VENDOR_ID_NVIDIA, 0x014b,
359 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
360 {PCI_VENDOR_ID_NVIDIA, 0x14c,
361 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
362 {PCI_VENDOR_ID_NVIDIA, 0x014d,
363 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
364 {PCI_VENDOR_ID_NVIDIA, 0x0160,
365 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
366 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
367 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
368 {PCI_VENDOR_ID_NVIDIA, 0x0162,
369 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
370 {PCI_VENDOR_ID_NVIDIA, 0x0163,
371 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
372 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
373 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
374 {PCI_VENDOR_ID_NVIDIA, 0x0165,
375 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
376 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
377 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
378 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
379 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
380 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
381 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
382 {PCI_VENDOR_ID_NVIDIA, 0x0169,
383 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
384 {PCI_VENDOR_ID_NVIDIA, 0x016b,
385 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
386 {PCI_VENDOR_ID_NVIDIA, 0x016c,
387 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
388 {PCI_VENDOR_ID_NVIDIA, 0x016d,
389 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
390 {PCI_VENDOR_ID_NVIDIA, 0x016e,
391 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
392 {PCI_VENDOR_ID_NVIDIA, 0x0210,
393 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
394 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
395 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
396 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
397 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
398 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
399 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Calin A. Culianu7015faa2005-11-04 20:38:04 -0500400 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT,
401 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
402 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX,
403 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
404 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800,
405 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
406 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX,
407 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 {PCI_VENDOR_ID_NVIDIA, 0x021d,
409 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
410 {PCI_VENDOR_ID_NVIDIA, 0x021e,
411 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
412 {PCI_VENDOR_ID_NVIDIA, 0x0220,
413 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
414 {PCI_VENDOR_ID_NVIDIA, 0x0221,
415 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
416 {PCI_VENDOR_ID_NVIDIA, 0x0222,
417 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
418 {PCI_VENDOR_ID_NVIDIA, 0x0228,
419 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
420 {0,} /* terminate list */
421};
422
423MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
424
425/* command line data, set in nvidiafb_setup() */
426static int flatpanel __devinitdata = -1; /* Autodetect later */
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -0800427static int fpdither __devinitdata = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428static int forceCRTC __devinitdata = -1;
429static int hwcur __devinitdata = 0;
430static int noaccel __devinitdata = 0;
431static int noscale __devinitdata = 0;
432static int paneltweak __devinitdata = 0;
Antonino A. Daplas917bb072005-05-01 08:59:22 -0700433static int vram __devinitdata = 0;
Antonino A. Daplasade91852006-01-09 20:53:39 -0800434static int bpp __devinitdata = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435#ifdef CONFIG_MTRR
436static int nomtrr __devinitdata = 0;
437#endif
438
439static char *mode_option __devinitdata = NULL;
440
441static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
442 .type = FB_TYPE_PACKED_PIXELS,
443 .xpanstep = 8,
444 .ypanstep = 1,
445};
446
447static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
448 .xres = 640,
449 .yres = 480,
450 .xres_virtual = 640,
451 .yres_virtual = 480,
452 .bits_per_pixel = 8,
453 .red = {0, 8, 0},
454 .green = {0, 8, 0},
455 .blue = {0, 8, 0},
456 .transp = {0, 0, 0},
457 .activate = FB_ACTIVATE_NOW,
458 .height = -1,
459 .width = -1,
460 .pixclock = 39721,
461 .left_margin = 40,
462 .right_margin = 24,
463 .upper_margin = 32,
464 .lower_margin = 11,
465 .hsync_len = 96,
466 .vsync_len = 2,
467 .vmode = FB_VMODE_NONINTERLACED
468};
469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
471 u16 bg, u16 fg, u32 w, u32 h)
472{
James Simmonsf1ab5da2005-06-21 17:17:07 -0700473 u32 *data = (u32 *) data8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 int i, j, k = 0;
475 u32 b, tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
477 w = (w + 1) & ~1;
478
479 for (i = 0; i < h; i++) {
480 b = *data++;
481 reverse_order(&b);
482
483 for (j = 0; j < w / 2; j++) {
484 tmp = 0;
485#if defined (__BIG_ENDIAN)
486 tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
487 b <<= 1;
488 tmp |= (b & (1 << 31)) ? fg : bg;
489 b <<= 1;
490#else
491 tmp = (b & 1) ? fg : bg;
492 b >>= 1;
493 tmp |= (b & 1) ? fg << 16 : bg << 16;
494 b >>= 1;
495#endif
496 NV_WR32(&par->CURSOR[k++], 0, tmp);
497 }
498 k += (MAX_CURS - w) / 2;
499 }
500}
501
502static void nvidia_write_clut(struct nvidia_par *par,
503 u8 regnum, u8 red, u8 green, u8 blue)
504{
505 NVWriteDacMask(par, 0xff);
506 NVWriteDacWriteAddr(par, regnum);
507 NVWriteDacData(par, red);
508 NVWriteDacData(par, green);
509 NVWriteDacData(par, blue);
510}
511
512static void nvidia_read_clut(struct nvidia_par *par,
513 u8 regnum, u8 * red, u8 * green, u8 * blue)
514{
515 NVWriteDacMask(par, 0xff);
516 NVWriteDacReadAddr(par, regnum);
517 *red = NVReadDacData(par);
518 *green = NVReadDacData(par);
519 *blue = NVReadDacData(par);
520}
521
522static int nvidia_panel_tweak(struct nvidia_par *par,
523 struct _riva_hw_state *state)
524{
525 int tweak = 0;
526
527 if (par->paneltweak) {
528 tweak = par->paneltweak;
529 } else {
530 /* begin flat panel hacks */
531 /* This is unfortunate, but some chips need this register
532 tweaked or else you get artifacts where adjacent pixels are
533 swapped. There are no hard rules for what to set here so all
534 we can do is experiment and apply hacks. */
535
536 if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
537 /* At least one NV34 laptop needs this workaround. */
538 tweak = -1;
539 }
540
541 if((par->Chipset & 0xfff0) == 0x0310) {
542 tweak = 1;
543 }
544 /* end flat panel hacks */
545 }
546
547 return tweak;
548}
549
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -0800550static void nvidia_vga_protect(struct nvidia_par *par, int on)
551{
552 unsigned char tmp;
553
554 if (on) {
555 /*
556 * Turn off screen and disable sequencer.
557 */
558 tmp = NVReadSeq(par, 0x01);
559
560 NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
561 NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
562 } else {
563 /*
564 * Reenable sequencer, then turn on screen.
565 */
566
567 tmp = NVReadSeq(par, 0x01);
568
569 NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
570 NVWriteSeq(par, 0x00, 0x03); /* End Reset */
571 }
572}
573
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574static void nvidia_save_vga(struct nvidia_par *par,
575 struct _riva_hw_state *state)
576{
577 int i;
578
579 NVTRACE_ENTER();
580 NVLockUnlock(par, 0);
581
582 NVUnloadStateExt(par, state);
583
584 state->misc_output = NVReadMiscOut(par);
585
586 for (i = 0; i < NUM_CRT_REGS; i++)
587 state->crtc[i] = NVReadCrtc(par, i);
588
589 for (i = 0; i < NUM_ATC_REGS; i++)
590 state->attr[i] = NVReadAttr(par, i);
591
592 for (i = 0; i < NUM_GRC_REGS; i++)
593 state->gra[i] = NVReadGr(par, i);
594
595 for (i = 0; i < NUM_SEQ_REGS; i++)
596 state->seq[i] = NVReadSeq(par, i);
597 NVTRACE_LEAVE();
598}
599
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800600#undef DUMP_REG
601
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -0800602static void nvidia_write_regs(struct nvidia_par *par,
603 struct _riva_hw_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 int i;
606
607 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
609 NVLoadStateExt(par, state);
610
611 NVWriteMiscOut(par, state->misc_output);
612
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800613 for (i = 1; i < NUM_SEQ_REGS; i++) {
614#ifdef DUMP_REG
615 printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
616#endif
617 NVWriteSeq(par, i, state->seq[i]);
618 }
619
620 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
621 NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
622
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 for (i = 0; i < NUM_CRT_REGS; i++) {
624 switch (i) {
625 case 0x19:
626 case 0x20 ... 0x40:
627 break;
628 default:
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800629#ifdef DUMP_REG
630 printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
631#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 NVWriteCrtc(par, i, state->crtc[i]);
633 }
634 }
635
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800636 for (i = 0; i < NUM_GRC_REGS; i++) {
637#ifdef DUMP_REG
638 printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
639#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 NVWriteGr(par, i, state->gra[i]);
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800643 for (i = 0; i < NUM_ATC_REGS; i++) {
644#ifdef DUMP_REG
645 printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
646#endif
647 NVWriteAttr(par, i, state->attr[i]);
648 }
649
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 NVTRACE_LEAVE();
651}
652
653static int nvidia_calc_regs(struct fb_info *info)
654{
655 struct nvidia_par *par = info->par;
656 struct _riva_hw_state *state = &par->ModeReg;
Antonino A. Daplasb8c90942005-09-09 13:04:37 -0700657 int i, depth = fb_get_color_depth(&info->var, &info->fix);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 int h_display = info->var.xres / 8 - 1;
659 int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
660 int h_end = (info->var.xres + info->var.right_margin +
661 info->var.hsync_len) / 8 - 1;
662 int h_total = (info->var.xres + info->var.right_margin +
663 info->var.hsync_len + info->var.left_margin) / 8 - 5;
664 int h_blank_s = h_display;
665 int h_blank_e = h_total + 4;
666 int v_display = info->var.yres - 1;
667 int v_start = info->var.yres + info->var.lower_margin - 1;
668 int v_end = (info->var.yres + info->var.lower_margin +
669 info->var.vsync_len) - 1;
670 int v_total = (info->var.yres + info->var.lower_margin +
671 info->var.vsync_len + info->var.upper_margin) - 2;
672 int v_blank_s = v_display;
673 int v_blank_e = v_total + 1;
674
675 /*
676 * Set all CRTC values.
677 */
678
679 if (info->var.vmode & FB_VMODE_INTERLACED)
680 v_total |= 1;
681
682 if (par->FlatPanel == 1) {
683 v_start = v_total - 3;
684 v_end = v_total - 2;
685 v_blank_s = v_start;
686 h_start = h_total - 5;
687 h_end = h_total - 2;
688 h_blank_e = h_total + 4;
689 }
690
691 state->crtc[0x0] = Set8Bits(h_total);
692 state->crtc[0x1] = Set8Bits(h_display);
693 state->crtc[0x2] = Set8Bits(h_blank_s);
694 state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
695 | SetBit(7);
696 state->crtc[0x4] = Set8Bits(h_start);
697 state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
698 | SetBitField(h_end, 4: 0, 4:0);
699 state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
700 state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
701 | SetBitField(v_display, 8: 8, 1:1)
702 | SetBitField(v_start, 8: 8, 2:2)
703 | SetBitField(v_blank_s, 8: 8, 3:3)
704 | SetBit(4)
705 | SetBitField(v_total, 9: 9, 5:5)
706 | SetBitField(v_display, 9: 9, 6:6)
707 | SetBitField(v_start, 9: 9, 7:7);
708 state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
709 | SetBit(6)
710 | ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
711 state->crtc[0x10] = Set8Bits(v_start);
712 state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
713 state->crtc[0x12] = Set8Bits(v_display);
714 state->crtc[0x13] = ((info->var.xres_virtual / 8) *
715 (info->var.bits_per_pixel / 8));
716 state->crtc[0x15] = Set8Bits(v_blank_s);
717 state->crtc[0x16] = Set8Bits(v_blank_e);
718
719 state->attr[0x10] = 0x01;
720
721 if (par->Television)
722 state->attr[0x11] = 0x00;
723
724 state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
725 | SetBitField(v_blank_s, 10: 10, 3:3)
726 | SetBitField(v_start, 10: 10, 2:2)
727 | SetBitField(v_display, 10: 10, 1:1)
728 | SetBitField(v_total, 10: 10, 0:0);
729
730 state->horiz = SetBitField(h_total, 8: 8, 0:0)
731 | SetBitField(h_display, 8: 8, 1:1)
732 | SetBitField(h_blank_s, 8: 8, 2:2)
733 | SetBitField(h_start, 8: 8, 3:3);
734
735 state->extra = SetBitField(v_total, 11: 11, 0:0)
736 | SetBitField(v_display, 11: 11, 2:2)
737 | SetBitField(v_start, 11: 11, 4:4)
738 | SetBitField(v_blank_s, 11: 11, 6:6);
739
740 if (info->var.vmode & FB_VMODE_INTERLACED) {
741 h_total = (h_total >> 1) & ~1;
742 state->interlace = Set8Bits(h_total);
743 state->horiz |= SetBitField(h_total, 8: 8, 4:4);
744 } else {
745 state->interlace = 0xff; /* interlace off */
746 }
747
748 /*
749 * Calculate the extended registers.
750 */
751
752 if (depth < 24)
753 i = depth;
754 else
755 i = 32;
756
757 if (par->Architecture >= NV_ARCH_10)
758 par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
759 par->CursorStart);
760
761 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
762 state->misc_output &= ~0x40;
763 else
764 state->misc_output |= 0x40;
765 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
766 state->misc_output &= ~0x80;
767 else
768 state->misc_output |= 0x80;
769
770 NVCalcStateExt(par, state, i, info->var.xres_virtual,
771 info->var.xres, info->var.yres_virtual,
772 1000000000 / info->var.pixclock, info->var.vmode);
773
774 state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
775 if (par->FlatPanel == 1) {
776 state->pixel |= (1 << 7);
777
778 if (!par->fpScaler || (par->fpWidth <= info->var.xres)
779 || (par->fpHeight <= info->var.yres)) {
780 state->scale |= (1 << 8);
781 }
782
783 if (!par->crtcSync_read) {
784 state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
785 par->crtcSync_read = 1;
786 }
787
788 par->PanelTweak = nvidia_panel_tweak(par, state);
789 }
790
791 state->vpll = state->pll;
792 state->vpll2 = state->pll;
793 state->vpllB = state->pllB;
794 state->vpll2B = state->pllB;
795
796 VGA_WR08(par->PCIO, 0x03D4, 0x1C);
797 state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
798
799 if (par->CRTCnumber) {
800 state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
801 state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
802 state->crtcOwner = 3;
803 state->pllsel |= 0x20000800;
804 state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
805 if (par->twoStagePLL)
806 state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
807 } else if (par->twoHeads) {
808 state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
809 state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
810 state->crtcOwner = 0;
811 state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
812 if (par->twoStagePLL)
813 state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
814 }
815
816 state->cursorConfig = 0x00000100;
817
818 if (info->var.vmode & FB_VMODE_DOUBLE)
819 state->cursorConfig |= (1 << 4);
820
821 if (par->alphaCursor) {
822 if ((par->Chipset & 0x0ff0) != 0x0110)
823 state->cursorConfig |= 0x04011000;
824 else
825 state->cursorConfig |= 0x14011000;
826 state->general |= (1 << 29);
827 } else
828 state->cursorConfig |= 0x02000000;
829
830 if (par->twoHeads) {
831 if ((par->Chipset & 0x0ff0) == 0x0110) {
832 state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
833 ~0x00010000;
834 if (par->FPDither)
835 state->dither |= 0x00010000;
836 } else {
837 state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
838 if (par->FPDither)
839 state->dither |= 1;
840 }
841 }
842
843 state->timingH = 0;
844 state->timingV = 0;
845 state->displayV = info->var.xres;
846
847 return 0;
848}
849
850static void nvidia_init_vga(struct fb_info *info)
851{
852 struct nvidia_par *par = info->par;
853 struct _riva_hw_state *state = &par->ModeReg;
854 int i;
855
856 for (i = 0; i < 0x10; i++)
857 state->attr[i] = i;
858 state->attr[0x10] = 0x41;
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800859 state->attr[0x11] = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 state->attr[0x12] = 0x0f;
861 state->attr[0x13] = 0x00;
862 state->attr[0x14] = 0x00;
863
864 memset(state->crtc, 0x00, NUM_CRT_REGS);
865 state->crtc[0x0a] = 0x20;
866 state->crtc[0x17] = 0xe3;
867 state->crtc[0x18] = 0xff;
868 state->crtc[0x28] = 0x40;
869
870 memset(state->gra, 0x00, NUM_GRC_REGS);
871 state->gra[0x05] = 0x40;
872 state->gra[0x06] = 0x05;
873 state->gra[0x07] = 0x0f;
874 state->gra[0x08] = 0xff;
875
876 state->seq[0x00] = 0x03;
877 state->seq[0x01] = 0x01;
878 state->seq[0x02] = 0x0f;
879 state->seq[0x03] = 0x00;
880 state->seq[0x04] = 0x0e;
881
882 state->misc_output = 0xeb;
883}
884
885static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
886{
887 struct nvidia_par *par = info->par;
888 u8 data[MAX_CURS * MAX_CURS / 8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 int i, set = cursor->set;
James Simmonsf1ab5da2005-06-21 17:17:07 -0700890 u16 fg, bg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Antonino A. Daplas7a482422005-09-21 07:30:21 +0800892 if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
James Simmonsf1ab5da2005-06-21 17:17:07 -0700893 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894
895 NVShowHideCursor(par, 0);
896
897 if (par->cursor_reset) {
898 set = FB_CUR_SETALL;
899 par->cursor_reset = 0;
900 }
901
902 if (set & FB_CUR_SETSIZE)
903 memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
904
905 if (set & FB_CUR_SETPOS) {
906 u32 xx, yy, temp;
907
908 yy = cursor->image.dy - info->var.yoffset;
909 xx = cursor->image.dx - info->var.xoffset;
910 temp = xx & 0xFFFF;
911 temp |= yy << 16;
912
913 NV_WR32(par->PRAMDAC, 0x0000300, temp);
914 }
915
916 if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
917 u32 bg_idx = cursor->image.bg_color;
918 u32 fg_idx = cursor->image.fg_color;
919 u32 s_pitch = (cursor->image.width + 7) >> 3;
920 u32 d_pitch = MAX_CURS / 8;
921 u8 *dat = (u8 *) cursor->image.data;
922 u8 *msk = (u8 *) cursor->mask;
923 u8 *src;
924
925 src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
926
927 if (src) {
928 switch (cursor->rop) {
929 case ROP_XOR:
James Simmonsf1ab5da2005-06-21 17:17:07 -0700930 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 src[i] = dat[i] ^ msk[i];
932 break;
933 case ROP_COPY:
934 default:
James Simmonsf1ab5da2005-06-21 17:17:07 -0700935 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 src[i] = dat[i] & msk[i];
937 break;
938 }
939
James Simmonsf1ab5da2005-06-21 17:17:07 -0700940 fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
941 cursor->image.height);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
943 bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
944 ((info->cmap.green[bg_idx] & 0xf8) << 2) |
945 ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
946
947 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
948 ((info->cmap.green[fg_idx] & 0xf8) << 2) |
949 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
950
951 NVLockUnlock(par, 0);
952
953 nvidiafb_load_cursor_image(par, data, bg, fg,
954 cursor->image.width,
955 cursor->image.height);
956 kfree(src);
957 }
958 }
959
960 if (cursor->enable)
961 NVShowHideCursor(par, 1);
962
963 return 0;
964}
965
966static int nvidiafb_set_par(struct fb_info *info)
967{
968 struct nvidia_par *par = info->par;
969
970 NVTRACE_ENTER();
971
972 NVLockUnlock(par, 1);
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -0800973 if (!par->FlatPanel || !par->twoHeads)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 par->FPDither = 0;
975
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -0800976 if (par->FPDither < 0) {
977 if ((par->Chipset & 0x0ff0) == 0x0110)
978 par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
979 & 0x00010000);
980 else
981 par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
982 printk(KERN_INFO PFX "Flat panel dithering %s\n",
983 par->FPDither ? "enabled" : "disabled");
984 }
985
Antonino A. Daplasb8c90942005-09-09 13:04:37 -0700986 info->fix.visual = (info->var.bits_per_pixel == 8) ?
987 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 nvidia_init_vga(info);
990 nvidia_calc_regs(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
992 NVLockUnlock(par, 0);
993 if (par->twoHeads) {
994 VGA_WR08(par->PCIO, 0x03D4, 0x44);
995 VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
996 NVLockUnlock(par, 0);
997 }
998
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800999 nvidia_vga_protect(par, 1);
1000
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001001 nvidia_write_regs(par, &par->ModeReg);
1002 NVSetStartAddress(par, 0);
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -08001003
1004#if defined (__BIG_ENDIAN)
1005 /* turn on LFB swapping */
1006 {
1007 unsigned char tmp;
1008
1009 VGA_WR08(par->PCIO, 0x3d4, 0x46);
1010 tmp = VGA_RD08(par->PCIO, 0x3d5);
1011 tmp |= (1 << 7);
1012 VGA_WR08(par->PCIO, 0x3d5, tmp);
1013 }
1014#endif
1015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 info->fix.line_length = (info->var.xres_virtual *
1017 info->var.bits_per_pixel) >> 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 if (info->var.accel_flags) {
1019 info->fbops->fb_imageblit = nvidiafb_imageblit;
1020 info->fbops->fb_fillrect = nvidiafb_fillrect;
1021 info->fbops->fb_copyarea = nvidiafb_copyarea;
1022 info->fbops->fb_sync = nvidiafb_sync;
1023 info->pixmap.scan_align = 4;
1024 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1025 NVResetGraphics(info);
1026 } else {
1027 info->fbops->fb_imageblit = cfb_imageblit;
1028 info->fbops->fb_fillrect = cfb_fillrect;
1029 info->fbops->fb_copyarea = cfb_copyarea;
1030 info->fbops->fb_sync = NULL;
1031 info->pixmap.scan_align = 1;
1032 info->flags |= FBINFO_HWACCEL_DISABLED;
1033 }
1034
1035 par->cursor_reset = 1;
1036
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -08001037 nvidia_vga_protect(par, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
1039 NVTRACE_LEAVE();
1040 return 0;
1041}
1042
1043static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1044 unsigned blue, unsigned transp,
1045 struct fb_info *info)
1046{
1047 struct nvidia_par *par = info->par;
1048 int i;
1049
1050 NVTRACE_ENTER();
1051 if (regno >= (1 << info->var.green.length))
1052 return -EINVAL;
1053
1054 if (info->var.grayscale) {
1055 /* gray = 0.30*R + 0.59*G + 0.11*B */
1056 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
1057 }
1058
1059 if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1060 ((u32 *) info->pseudo_palette)[regno] =
1061 (regno << info->var.red.offset) |
1062 (regno << info->var.green.offset) |
1063 (regno << info->var.blue.offset);
1064 }
1065
1066 switch (info->var.bits_per_pixel) {
1067 case 8:
1068 /* "transparent" stuff is completely ignored. */
1069 nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
1070 break;
1071 case 16:
1072 if (info->var.green.length == 5) {
1073 for (i = 0; i < 8; i++) {
1074 nvidia_write_clut(par, regno * 8 + i, red >> 8,
1075 green >> 8, blue >> 8);
1076 }
1077 } else {
1078 u8 r, g, b;
1079
1080 if (regno < 32) {
1081 for (i = 0; i < 8; i++) {
1082 nvidia_write_clut(par, regno * 8 + i,
1083 red >> 8, green >> 8,
1084 blue >> 8);
1085 }
1086 }
1087
1088 nvidia_read_clut(par, regno * 4, &r, &g, &b);
1089
1090 for (i = 0; i < 4; i++)
1091 nvidia_write_clut(par, regno * 4 + i, r,
1092 green >> 8, b);
1093 }
1094 break;
1095 case 32:
1096 nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
1097 break;
1098 default:
1099 /* do nothing */
1100 break;
1101 }
1102
1103 NVTRACE_LEAVE();
1104 return 0;
1105}
1106
1107static int nvidiafb_check_var(struct fb_var_screeninfo *var,
1108 struct fb_info *info)
1109{
1110 struct nvidia_par *par = info->par;
1111 int memlen, vramlen, mode_valid = 0;
1112 int pitch, err = 0;
1113
1114 NVTRACE_ENTER();
1115
1116 var->transp.offset = 0;
1117 var->transp.length = 0;
1118
1119 var->xres &= ~7;
1120
1121 if (var->bits_per_pixel <= 8)
1122 var->bits_per_pixel = 8;
1123 else if (var->bits_per_pixel <= 16)
1124 var->bits_per_pixel = 16;
1125 else
1126 var->bits_per_pixel = 32;
1127
1128 switch (var->bits_per_pixel) {
1129 case 8:
1130 var->red.offset = 0;
1131 var->red.length = 8;
1132 var->green.offset = 0;
1133 var->green.length = 8;
1134 var->blue.offset = 0;
1135 var->blue.length = 8;
1136 var->transp.offset = 0;
1137 var->transp.length = 0;
1138 break;
1139 case 16:
1140 var->green.length = (var->green.length < 6) ? 5 : 6;
1141 var->red.length = 5;
1142 var->blue.length = 5;
1143 var->transp.length = 6 - var->green.length;
1144 var->blue.offset = 0;
1145 var->green.offset = 5;
1146 var->red.offset = 5 + var->green.length;
1147 var->transp.offset = (5 + var->red.offset) & 15;
1148 break;
1149 case 32: /* RGBA 8888 */
1150 var->red.offset = 16;
1151 var->red.length = 8;
1152 var->green.offset = 8;
1153 var->green.length = 8;
1154 var->blue.offset = 0;
1155 var->blue.length = 8;
1156 var->transp.length = 8;
1157 var->transp.offset = 24;
1158 break;
1159 }
1160
1161 var->red.msb_right = 0;
1162 var->green.msb_right = 0;
1163 var->blue.msb_right = 0;
1164 var->transp.msb_right = 0;
1165
1166 if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1167 !info->monspecs.dclkmax || !fb_validate_mode(var, info))
1168 mode_valid = 1;
1169
1170 /* calculate modeline if supported by monitor */
1171 if (!mode_valid && info->monspecs.gtf) {
1172 if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1173 mode_valid = 1;
1174 }
1175
1176 if (!mode_valid) {
1177 struct fb_videomode *mode;
1178
1179 mode = fb_find_best_mode(var, &info->modelist);
1180 if (mode) {
1181 fb_videomode_to_var(var, mode);
1182 mode_valid = 1;
1183 }
1184 }
1185
1186 if (!mode_valid && info->monspecs.modedb_len)
1187 return -EINVAL;
1188
1189 if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
1190 par->fpHeight < var->yres))
1191 return -EINVAL;
1192
1193 if (var->yres_virtual < var->yres)
1194 var->yres_virtual = var->yres;
1195
1196 if (var->xres_virtual < var->xres)
1197 var->xres_virtual = var->xres;
1198
1199 var->xres_virtual = (var->xres_virtual + 63) & ~63;
1200
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001201 vramlen = info->screen_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
1203 memlen = pitch * var->yres_virtual;
1204
1205 if (memlen > vramlen) {
1206 var->yres_virtual = vramlen / pitch;
1207
1208 if (var->yres_virtual < var->yres) {
1209 var->yres_virtual = var->yres;
1210 var->xres_virtual = vramlen / var->yres_virtual;
1211 var->xres_virtual /= var->bits_per_pixel / 8;
1212 var->xres_virtual &= ~63;
1213 pitch = (var->xres_virtual *
1214 var->bits_per_pixel + 7) / 8;
1215 memlen = pitch * var->yres;
1216
1217 if (var->xres_virtual < var->xres) {
1218 printk("nvidiafb: required video memory, "
1219 "%d bytes, for %dx%d-%d (virtual) "
1220 "is out of range\n",
1221 memlen, var->xres_virtual,
1222 var->yres_virtual, var->bits_per_pixel);
1223 err = -ENOMEM;
1224 }
1225 }
1226 }
1227
1228 if (var->accel_flags) {
1229 if (var->yres_virtual > 0x7fff)
1230 var->yres_virtual = 0x7fff;
1231 if (var->xres_virtual > 0x7fff)
1232 var->xres_virtual = 0x7fff;
1233 }
1234
1235 var->xres_virtual &= ~63;
1236
1237 NVTRACE_LEAVE();
1238
1239 return err;
1240}
1241
1242static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
1243 struct fb_info *info)
1244{
1245 struct nvidia_par *par = info->par;
1246 u32 total;
1247
Antonino A. Daplas3c8d61b2005-11-13 16:06:34 -08001248 total = var->yoffset * info->fix.line_length + var->xoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
1250 NVSetStartAddress(par, total);
1251
1252 return 0;
1253}
1254
1255static int nvidiafb_blank(int blank, struct fb_info *info)
1256{
1257 struct nvidia_par *par = info->par;
1258 unsigned char tmp, vesa;
1259
1260 tmp = NVReadSeq(par, 0x01) & ~0x20; /* screen on/off */
1261 vesa = NVReadCrtc(par, 0x1a) & ~0xc0; /* sync on/off */
1262
1263 NVTRACE_ENTER();
1264
1265 if (blank)
1266 tmp |= 0x20;
1267
1268 switch (blank) {
1269 case FB_BLANK_UNBLANK:
1270 case FB_BLANK_NORMAL:
1271 break;
1272 case FB_BLANK_VSYNC_SUSPEND:
1273 vesa |= 0x80;
1274 break;
1275 case FB_BLANK_HSYNC_SUSPEND:
1276 vesa |= 0x40;
1277 break;
1278 case FB_BLANK_POWERDOWN:
1279 vesa |= 0xc0;
1280 break;
1281 }
1282
1283 NVWriteSeq(par, 0x01, tmp);
1284 NVWriteCrtc(par, 0x1a, vesa);
1285
Michael Hanselmann5474c122006-06-25 05:47:08 -07001286#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
1287 mutex_lock(&info->bl_mutex);
1288 if (info->bl_dev) {
1289 down(&info->bl_dev->sem);
1290 info->bl_dev->props->power = blank;
1291 info->bl_dev->props->update_status(info->bl_dev);
1292 up(&info->bl_dev->sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 }
Michael Hanselmann5474c122006-06-25 05:47:08 -07001294 mutex_unlock(&info->bl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295#endif
1296
1297 NVTRACE_LEAVE();
1298
1299 return 0;
1300}
1301
1302static struct fb_ops nvidia_fb_ops = {
1303 .owner = THIS_MODULE,
1304 .fb_check_var = nvidiafb_check_var,
1305 .fb_set_par = nvidiafb_set_par,
1306 .fb_setcolreg = nvidiafb_setcolreg,
1307 .fb_pan_display = nvidiafb_pan_display,
1308 .fb_blank = nvidiafb_blank,
1309 .fb_fillrect = nvidiafb_fillrect,
1310 .fb_copyarea = nvidiafb_copyarea,
1311 .fb_imageblit = nvidiafb_imageblit,
1312 .fb_cursor = nvidiafb_cursor,
1313 .fb_sync = nvidiafb_sync,
1314};
1315
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001316#ifdef CONFIG_PM
1317static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
1318{
1319 struct fb_info *info = pci_get_drvdata(dev);
1320 struct nvidia_par *par = info->par;
1321
1322 acquire_console_sem();
1323 par->pm_state = state.event;
1324
1325 if (state.event == PM_EVENT_FREEZE) {
1326 dev->dev.power.power_state = state;
1327 } else {
1328 fb_set_suspend(info, 1);
1329 nvidiafb_blank(FB_BLANK_POWERDOWN, info);
1330 nvidia_write_regs(par, &par->SavedReg);
1331 pci_save_state(dev);
1332 pci_disable_device(dev);
1333 pci_set_power_state(dev, pci_choose_state(dev, state));
1334 }
1335
1336 release_console_sem();
1337 return 0;
1338}
1339
1340static int nvidiafb_resume(struct pci_dev *dev)
1341{
1342 struct fb_info *info = pci_get_drvdata(dev);
1343 struct nvidia_par *par = info->par;
1344
1345 acquire_console_sem();
1346 pci_set_power_state(dev, PCI_D0);
1347
1348 if (par->pm_state != PM_EVENT_FREEZE) {
1349 pci_restore_state(dev);
1350 pci_enable_device(dev);
1351 pci_set_master(dev);
1352 }
1353
1354 par->pm_state = PM_EVENT_ON;
1355 nvidiafb_set_par(info);
1356 fb_set_suspend (info, 0);
1357 nvidiafb_blank(FB_BLANK_UNBLANK, info);
1358
1359 release_console_sem();
1360 return 0;
1361}
1362#else
1363#define nvidiafb_suspend NULL
1364#define nvidiafb_resume NULL
1365#endif
1366
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367static int __devinit nvidia_set_fbinfo(struct fb_info *info)
1368{
1369 struct fb_monspecs *specs = &info->monspecs;
1370 struct fb_videomode modedb;
1371 struct nvidia_par *par = info->par;
1372 int lpitch;
1373
1374 NVTRACE_ENTER();
1375 info->flags = FBINFO_DEFAULT
1376 | FBINFO_HWACCEL_IMAGEBLIT
1377 | FBINFO_HWACCEL_FILLRECT
1378 | FBINFO_HWACCEL_COPYAREA
1379 | FBINFO_HWACCEL_YPAN;
1380
1381 fb_videomode_to_modelist(info->monspecs.modedb,
1382 info->monspecs.modedb_len, &info->modelist);
1383 fb_var_to_videomode(&modedb, &nvidiafb_default_var);
1384
Antonino A. Daplasade91852006-01-09 20:53:39 -08001385 switch (bpp) {
1386 case 0 ... 8:
1387 bpp = 8;
1388 break;
1389 case 9 ... 16:
1390 bpp = 16;
1391 break;
1392 default:
1393 bpp = 32;
1394 break;
1395 }
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 if (specs->modedb != NULL) {
Antonino A. Daplas5ee1ef962005-11-07 01:00:55 -08001398 struct fb_videomode *modedb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Antonino A. Daplas5ee1ef962005-11-07 01:00:55 -08001400 modedb = fb_find_best_display(specs, &info->modelist);
1401 fb_videomode_to_var(&nvidiafb_default_var, modedb);
Antonino A. Daplasade91852006-01-09 20:53:39 -08001402 nvidiafb_default_var.bits_per_pixel = bpp;
Antonino Daplasdb6778d2005-08-08 14:22:43 +08001403 } else if (par->fpWidth && par->fpHeight) {
1404 char buf[16];
1405
1406 memset(buf, 0, 16);
Antonino A. Daplas948a95f2005-09-09 13:09:59 -07001407 snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
Antonino Daplasdb6778d2005-08-08 14:22:43 +08001408 fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
Antonino A. Daplasade91852006-01-09 20:53:39 -08001409 specs->modedb_len, &modedb, bpp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 }
1411
1412 if (mode_option)
1413 fb_find_mode(&nvidiafb_default_var, info, mode_option,
Antonino A. Daplasade91852006-01-09 20:53:39 -08001414 specs->modedb, specs->modedb_len, &modedb, bpp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 info->var = nvidiafb_default_var;
1417 info->fix.visual = (info->var.bits_per_pixel == 8) ?
1418 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1419 info->pseudo_palette = par->pseudo_palette;
1420 fb_alloc_cmap(&info->cmap, 256, 0);
1421 fb_destroy_modedb(info->monspecs.modedb);
1422 info->monspecs.modedb = NULL;
1423
1424 /* maximize virtual vertical length */
1425 lpitch = info->var.xres_virtual *
1426 ((info->var.bits_per_pixel + 7) >> 3);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001427 info->var.yres_virtual = info->screen_size / lpitch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429 info->pixmap.scan_align = 4;
1430 info->pixmap.buf_align = 4;
James Simmons58a60642005-06-21 17:17:08 -07001431 info->pixmap.access_align = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 info->pixmap.size = 8 * 1024;
1433 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1434
Antonino A. Daplas7a482422005-09-21 07:30:21 +08001435 if (!hwcur)
Antonino A. Daplasc465e052005-11-07 01:00:35 -08001436 info->fbops->fb_cursor = NULL;
Antonino A. Daplas7a482422005-09-21 07:30:21 +08001437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 info->var.accel_flags = (!noaccel);
1439
1440 switch (par->Architecture) {
1441 case NV_ARCH_04:
1442 info->fix.accel = FB_ACCEL_NV4;
1443 break;
1444 case NV_ARCH_10:
1445 info->fix.accel = FB_ACCEL_NV_10;
1446 break;
1447 case NV_ARCH_20:
1448 info->fix.accel = FB_ACCEL_NV_20;
1449 break;
1450 case NV_ARCH_30:
1451 info->fix.accel = FB_ACCEL_NV_30;
1452 break;
1453 case NV_ARCH_40:
1454 info->fix.accel = FB_ACCEL_NV_40;
1455 break;
1456 }
1457
1458 NVTRACE_LEAVE();
1459
1460 return nvidiafb_check_var(&info->var, info);
1461}
1462
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001463static u32 __devinit nvidia_get_chipset(struct fb_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001465 struct nvidia_par *par = info->par;
1466 u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
1467
1468 printk("nvidiafb: PCI id - %x\n", id);
1469 if ((id & 0xfff0) == 0x00f0) {
1470 /* pci-e */
1471 printk("nvidiafb: PCI-E card\n");
1472 id = NV_RD32(par->REGS, 0x1800);
1473
1474 if ((id & 0x0000ffff) == 0x000010DE)
1475 id = 0x10DE0000 | (id >> 16);
1476 else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
1477 id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
1478 ((id >> 8) & 0x000000ff);
1479 }
1480
1481 printk("nvidiafb: Actual id - %x\n", id);
1482 return id;
1483}
1484
1485static u32 __devinit nvidia_get_arch(struct fb_info *info)
1486{
1487 struct nvidia_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 u32 arch = 0;
1489
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001490 switch (par->Chipset & 0x0ff0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 case 0x0100: /* GeForce 256 */
1492 case 0x0110: /* GeForce2 MX */
1493 case 0x0150: /* GeForce2 */
1494 case 0x0170: /* GeForce4 MX */
1495 case 0x0180: /* GeForce4 MX (8x AGP) */
1496 case 0x01A0: /* nForce */
1497 case 0x01F0: /* nForce2 */
1498 arch = NV_ARCH_10;
1499 break;
1500 case 0x0200: /* GeForce3 */
1501 case 0x0250: /* GeForce4 Ti */
1502 case 0x0280: /* GeForce4 Ti (8x AGP) */
1503 arch = NV_ARCH_20;
1504 break;
1505 case 0x0300: /* GeForceFX 5800 */
1506 case 0x0310: /* GeForceFX 5600 */
1507 case 0x0320: /* GeForceFX 5200 */
1508 case 0x0330: /* GeForceFX 5900 */
1509 case 0x0340: /* GeForceFX 5700 */
1510 arch = NV_ARCH_30;
1511 break;
1512 case 0x0040:
1513 case 0x00C0:
1514 case 0x0120:
1515 case 0x0130:
1516 case 0x0140:
1517 case 0x0160:
1518 case 0x01D0:
1519 case 0x0090:
1520 case 0x0210:
1521 case 0x0220:
1522 case 0x0230:
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001523 case 0x0290:
1524 case 0x0390:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 arch = NV_ARCH_40;
1526 break;
1527 case 0x0020: /* TNT, TNT2 */
1528 arch = NV_ARCH_04;
1529 break;
1530 default: /* unknown architecture */
1531 break;
1532 }
1533
1534 return arch;
1535}
1536
1537static int __devinit nvidiafb_probe(struct pci_dev *pd,
1538 const struct pci_device_id *ent)
1539{
1540 struct nvidia_par *par;
1541 struct fb_info *info;
1542 unsigned short cmd;
1543
1544
1545 NVTRACE_ENTER();
1546 assert(pd != NULL);
1547
1548 info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
1549
1550 if (!info)
1551 goto err_out;
1552
Antonino A. Daplasc439e342006-01-09 20:53:02 -08001553 par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 par->pci_dev = pd;
1555
1556 info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
1557
1558 if (info->pixmap.addr == NULL)
1559 goto err_out_kfree;
1560
1561 memset(info->pixmap.addr, 0, 8 * 1024);
1562
1563 if (pci_enable_device(pd)) {
1564 printk(KERN_ERR PFX "cannot enable PCI device\n");
1565 goto err_out_enable;
1566 }
1567
1568 if (pci_request_regions(pd, "nvidiafb")) {
1569 printk(KERN_ERR PFX "cannot request PCI regions\n");
1570 goto err_out_request;
1571 }
1572
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 par->FlatPanel = flatpanel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 if (flatpanel == 1)
1575 printk(KERN_INFO PFX "flatpanel support enabled\n");
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001576 par->FPDither = fpdither;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
1578 par->CRTCnumber = forceCRTC;
1579 par->FpScale = (!noscale);
1580 par->paneltweak = paneltweak;
1581
1582 /* enable IO and mem if not already done */
1583 pci_read_config_word(pd, PCI_COMMAND, &cmd);
1584 cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
1585 pci_write_config_word(pd, PCI_COMMAND, cmd);
1586
1587 nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
1588 nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
1589 nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
1590
1591 par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
1592
1593 if (!par->REGS) {
1594 printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
1595 goto err_out_free_base0;
1596 }
1597
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001598 par->Chipset = nvidia_get_chipset(info);
1599 printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
1600 par->Architecture = nvidia_get_arch(info);
1601
1602 if (par->Architecture == 0) {
1603 printk(KERN_ERR PFX "unknown NV_ARCH\n");
1604 goto err_out_arch;
1605 }
1606
1607 sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
1608
Antonino A. Daplas918799a2006-01-09 20:53:40 -08001609 if (NVCommonSetup(info))
1610 goto err_out_arch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 par->FbAddress = nvidiafb_fix.smem_start;
1613 par->FbMapSize = par->RamAmountKBytes * 1024;
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001614 if (vram && vram * 1024 * 1024 < par->FbMapSize)
1615 par->FbMapSize = vram * 1024 * 1024;
1616
1617 /* Limit amount of vram to 64 MB */
1618 if (par->FbMapSize > 64 * 1024 * 1024)
1619 par->FbMapSize = 64 * 1024 * 1024;
1620
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001621 if(par->Architecture >= NV_ARCH_40)
1622 par->FbUsableSize = par->FbMapSize - (560 * 1024);
1623 else
1624 par->FbUsableSize = par->FbMapSize - (128 * 1024);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
1626 16 * 1024;
1627 par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001628 par->CursorStart = par->FbUsableSize + (32 * 1024);
1629
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001631 info->screen_size = par->FbUsableSize;
1632 nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 if (!info->screen_base) {
1635 printk(KERN_ERR PFX "cannot ioremap FB base\n");
1636 goto err_out_free_base1;
1637 }
1638
1639 par->FbStart = info->screen_base;
1640
1641#ifdef CONFIG_MTRR
1642 if (!nomtrr) {
1643 par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001644 par->RamAmountKBytes * 1024,
1645 MTRR_TYPE_WRCOMB, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 if (par->mtrr.vram < 0) {
1647 printk(KERN_ERR PFX "unable to setup MTRR\n");
1648 } else {
1649 par->mtrr.vram_valid = 1;
1650 /* let there be speed */
1651 printk(KERN_INFO PFX "MTRR set to ON\n");
1652 }
1653 }
1654#endif /* CONFIG_MTRR */
1655
1656 info->fbops = &nvidia_fb_ops;
1657 info->fix = nvidiafb_fix;
1658
1659 if (nvidia_set_fbinfo(info) < 0) {
1660 printk(KERN_ERR PFX "error setting initial video mode\n");
1661 goto err_out_iounmap_fb;
1662 }
1663
1664 nvidia_save_vga(par, &par->SavedReg);
1665
1666 if (register_framebuffer(info) < 0) {
1667 printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
1668 goto err_out_iounmap_fb;
1669 }
1670
1671 pci_set_drvdata(pd, info);
1672
1673 printk(KERN_INFO PFX
1674 "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
1675 info->fix.id,
1676 par->FbMapSize / (1024 * 1024), info->fix.smem_start);
Michael Hanselmann5474c122006-06-25 05:47:08 -07001677
1678 nvidia_bl_init(par);
1679
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 NVTRACE_LEAVE();
1681 return 0;
1682
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001683err_out_iounmap_fb:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 iounmap(info->screen_base);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001685err_out_free_base1:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 fb_destroy_modedb(info->monspecs.modedb);
1687 nvidia_delete_i2c_busses(par);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001688err_out_arch:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 iounmap(par->REGS);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001690err_out_free_base0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 pci_release_regions(pd);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001692err_out_request:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 pci_disable_device(pd);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001694err_out_enable:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695 kfree(info->pixmap.addr);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001696err_out_kfree:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 framebuffer_release(info);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001698err_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 return -ENODEV;
1700}
1701
1702static void __exit nvidiafb_remove(struct pci_dev *pd)
1703{
1704 struct fb_info *info = pci_get_drvdata(pd);
1705 struct nvidia_par *par = info->par;
1706
1707 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Michael Hanselmann5474c122006-06-25 05:47:08 -07001709 nvidia_bl_exit(par);
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 unregister_framebuffer(info);
1712#ifdef CONFIG_MTRR
1713 if (par->mtrr.vram_valid)
1714 mtrr_del(par->mtrr.vram, info->fix.smem_start,
1715 info->fix.smem_len);
1716#endif /* CONFIG_MTRR */
1717
1718 iounmap(info->screen_base);
1719 fb_destroy_modedb(info->monspecs.modedb);
1720 nvidia_delete_i2c_busses(par);
1721 iounmap(par->REGS);
1722 pci_release_regions(pd);
1723 pci_disable_device(pd);
1724 kfree(info->pixmap.addr);
1725 framebuffer_release(info);
1726 pci_set_drvdata(pd, NULL);
1727 NVTRACE_LEAVE();
1728}
1729
1730/* ------------------------------------------------------------------------- *
1731 *
1732 * initialization
1733 *
1734 * ------------------------------------------------------------------------- */
1735
1736#ifndef MODULE
1737static int __devinit nvidiafb_setup(char *options)
1738{
1739 char *this_opt;
1740
1741 NVTRACE_ENTER();
1742 if (!options || !*options)
1743 return 0;
1744
1745 while ((this_opt = strsep(&options, ",")) != NULL) {
1746 if (!strncmp(this_opt, "forceCRTC", 9)) {
1747 char *p;
1748
1749 p = this_opt + 9;
1750 if (!*p || !*(++p))
1751 continue;
1752 forceCRTC = *p - '0';
1753 if (forceCRTC < 0 || forceCRTC > 1)
1754 forceCRTC = -1;
1755 } else if (!strncmp(this_opt, "flatpanel", 9)) {
1756 flatpanel = 1;
1757 } else if (!strncmp(this_opt, "hwcur", 5)) {
1758 hwcur = 1;
1759 } else if (!strncmp(this_opt, "noaccel", 6)) {
1760 noaccel = 1;
1761 } else if (!strncmp(this_opt, "noscale", 7)) {
1762 noscale = 1;
1763 } else if (!strncmp(this_opt, "paneltweak:", 11)) {
1764 paneltweak = simple_strtoul(this_opt+11, NULL, 0);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001765 } else if (!strncmp(this_opt, "vram:", 5)) {
1766 vram = simple_strtoul(this_opt+5, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767#ifdef CONFIG_MTRR
1768 } else if (!strncmp(this_opt, "nomtrr", 6)) {
1769 nomtrr = 1;
1770#endif
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001771 } else if (!strncmp(this_opt, "fpdither:", 9)) {
1772 fpdither = simple_strtol(this_opt+9, NULL, 0);
Antonino A. Daplasade91852006-01-09 20:53:39 -08001773 } else if (!strncmp(this_opt, "bpp:", 4)) {
1774 bpp = simple_strtoul(this_opt+4, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775 } else
1776 mode_option = this_opt;
1777 }
1778 NVTRACE_LEAVE();
1779 return 0;
1780}
1781#endif /* !MODULE */
1782
1783static struct pci_driver nvidiafb_driver = {
1784 .name = "nvidiafb",
1785 .id_table = nvidiafb_pci_tbl,
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001786 .probe = nvidiafb_probe,
1787 .suspend = nvidiafb_suspend,
1788 .resume = nvidiafb_resume,
1789 .remove = __exit_p(nvidiafb_remove),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790};
1791
1792/* ------------------------------------------------------------------------- *
1793 *
1794 * modularization
1795 *
1796 * ------------------------------------------------------------------------- */
1797
1798static int __devinit nvidiafb_init(void)
1799{
1800#ifndef MODULE
1801 char *option = NULL;
1802
1803 if (fb_get_options("nvidiafb", &option))
1804 return -ENODEV;
1805 nvidiafb_setup(option);
1806#endif
1807 return pci_register_driver(&nvidiafb_driver);
1808}
1809
1810module_init(nvidiafb_init);
1811
1812#ifdef MODULE
1813static void __exit nvidiafb_exit(void)
1814{
1815 pci_unregister_driver(&nvidiafb_driver);
1816}
1817
1818module_exit(nvidiafb_exit);
1819
1820module_param(flatpanel, int, 0);
1821MODULE_PARM_DESC(flatpanel,
1822 "Enables experimental flat panel support for some chipsets. "
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001823 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
1824module_param(fpdither, int, 0);
1825MODULE_PARM_DESC(fpdither,
1826 "Enables dithering of flat panel for 6 bits panels. "
1827 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828module_param(hwcur, int, 0);
1829MODULE_PARM_DESC(hwcur,
1830 "Enables hardware cursor implementation. (0 or 1=enabled) "
1831 "(default=0)");
1832module_param(noaccel, int, 0);
1833MODULE_PARM_DESC(noaccel,
1834 "Disables hardware acceleration. (0 or 1=disable) "
1835 "(default=0)");
1836module_param(noscale, int, 0);
1837MODULE_PARM_DESC(noscale,
1838 "Disables screen scaleing. (0 or 1=disable) "
1839 "(default=0, do scaling)");
1840module_param(paneltweak, int, 0);
1841MODULE_PARM_DESC(paneltweak,
1842 "Tweak display settings for flatpanels. "
1843 "(default=0, no tweaks)");
1844module_param(forceCRTC, int, 0);
1845MODULE_PARM_DESC(forceCRTC,
1846 "Forces usage of a particular CRTC in case autodetection "
1847 "fails. (0 or 1) (default=autodetect)");
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001848module_param(vram, int, 0);
1849MODULE_PARM_DESC(vram,
1850 "amount of framebuffer memory to remap in MiB"
1851 "(default=0 - remap entire memory)");
Antonino A. Daplasc439e342006-01-09 20:53:02 -08001852module_param(mode_option, charp, 0);
1853MODULE_PARM_DESC(mode_option, "Specify initial video mode");
Antonino A. Daplasade91852006-01-09 20:53:39 -08001854module_param(bpp, int, 0);
1855MODULE_PARM_DESC(bpp, "pixel width in bits"
1856 "(default=8)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857#ifdef CONFIG_MTRR
1858module_param(nomtrr, bool, 0);
1859MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
1860 "(default=0)");
1861#endif
1862
1863MODULE_AUTHOR("Antonino Daplas");
1864MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
1865MODULE_LICENSE("GPL");
1866#endif /* MODULE */
1867