blob: 6d3e4890cb43c563c4f9b070806f3c945bee98f1 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#ifdef CONFIG_MTRR
26#include <asm/mtrr.h>
27#endif
28#ifdef CONFIG_PPC_OF
29#include <asm/prom.h>
30#include <asm/pci-bridge.h>
31#endif
32#ifdef CONFIG_PMAC_BACKLIGHT
33#include <asm/backlight.h>
34#endif
35
36#include "nv_local.h"
37#include "nv_type.h"
38#include "nv_proto.h"
39#include "nv_dma.h"
40
41#ifndef CONFIG_PCI /* sanity check */
42#error This driver requires PCI support.
43#endif
44
45#undef CONFIG_FB_NVIDIA_DEBUG
46#ifdef CONFIG_FB_NVIDIA_DEBUG
47#define NVTRACE printk
48#else
49#define NVTRACE if (0) printk
50#endif
51
52#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
53#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
54
55#ifdef CONFIG_FB_NVIDIA_DEBUG
56#define assert(expr) \
57 if (!(expr)) { \
58 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
59 #expr,__FILE__,__FUNCTION__,__LINE__); \
60 BUG(); \
61 }
62#else
63#define assert(expr)
64#endif
65
66#define PFX "nvidiafb: "
67
68/* HW cursor parameters */
69#define MAX_CURS 32
70
71static struct pci_device_id nvidiafb_pci_tbl[] = {
72 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
73 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
74 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
75 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
76 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
77 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
78 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
79 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
80 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
81 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
82 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
83 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
84 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
85 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
86 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
87 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
88 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
89 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
90 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
91 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
92 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
93 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
94 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
95 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
96 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
97 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
98 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
99 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
100 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
101 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
102 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
103 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
104 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
105 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
106 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
107 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
108 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
109 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
110 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
111 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
112 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
113 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
114 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
115 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
116 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
117 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
118 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
119 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
120 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
121 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
122 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
123 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
124 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
126 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
127 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
128 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
129 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
130 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
131 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
132 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
133 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
134 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
135 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
136 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
137 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
138 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
139 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
140 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
141 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Antonino A. Daplasbc7fc062006-02-11 17:56:07 -0800142 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
143 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
145 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
146 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
147 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
148 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
149 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
150 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
151 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
152 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
153 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
154 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
155 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
156 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
157 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
158 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
159 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
160 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
161 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
162 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
163 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
164 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
165 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
166 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
167 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
168 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
169 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
170 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
171 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
172 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
173 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
174 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
175 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
176 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
177 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
178 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
179 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
180 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
181 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
182 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
183 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
184 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
185 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
186 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
187 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
188 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
189 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
190 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
191 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
192 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
193 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
194 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
195 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
196 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
197 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
198 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
199 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
200 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
201 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
202 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
203 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
204 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
205 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
206 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
207 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
208 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
209 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
210 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
211 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
212 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
213 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
214 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
215 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
216 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
217 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
218 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
219 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
220 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
221 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
222 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
223 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
224 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
225 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
226 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
227 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
228 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
229 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
230 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
231 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
232 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
233 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
234 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
235 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
236 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
237 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
238 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
239 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
240 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
241 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
242 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
243 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
244 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
245 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
246 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
247 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
248 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
249 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
250 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
251 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
252 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
253 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
254 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
255 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
256 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
257 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
258 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
259 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
260 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
261 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
262 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
263 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
264 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
265 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
266 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
267 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
268 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
269 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
270 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
271 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
272 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
273 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
274 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
275 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
276 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
277 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
278 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
279 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
280 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
281 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
282 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
283 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
284 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
285 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
286 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
287 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
288 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
289 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Antonino A. Daplasc549dc62006-01-09 20:53:33 -0800290 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
291 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
292 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
293 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
294 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
295 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
296 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
297 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
298 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
299 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Pavel Roskined498432006-03-27 01:17:36 -0800300 {PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280,
301 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 {PCI_VENDOR_ID_NVIDIA, 0x0252,
303 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
304 {PCI_VENDOR_ID_NVIDIA, 0x0313,
305 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
306 {PCI_VENDOR_ID_NVIDIA, 0x0316,
307 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
308 {PCI_VENDOR_ID_NVIDIA, 0x0317,
309 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
310 {PCI_VENDOR_ID_NVIDIA, 0x031D,
311 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
312 {PCI_VENDOR_ID_NVIDIA, 0x031E,
313 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
314 {PCI_VENDOR_ID_NVIDIA, 0x031F,
315 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
316 {PCI_VENDOR_ID_NVIDIA, 0x0329,
317 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
318 {PCI_VENDOR_ID_NVIDIA, 0x032F,
319 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
320 {PCI_VENDOR_ID_NVIDIA, 0x0345,
321 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
322 {PCI_VENDOR_ID_NVIDIA, 0x0349,
323 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
324 {PCI_VENDOR_ID_NVIDIA, 0x034B,
325 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
326 {PCI_VENDOR_ID_NVIDIA, 0x034F,
327 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
328 {PCI_VENDOR_ID_NVIDIA, 0x00c0,
329 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
330 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
331 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
332 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
333 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
334 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
335 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
336 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
337 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
338 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
339 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
340 {PCI_VENDOR_ID_NVIDIA, 0x00cd,
341 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
342 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
343 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
344 {PCI_VENDOR_ID_NVIDIA, 0x0142,
345 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
346 {PCI_VENDOR_ID_NVIDIA, 0x0143,
347 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
348 {PCI_VENDOR_ID_NVIDIA, 0x0144,
349 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
350 {PCI_VENDOR_ID_NVIDIA, 0x0145,
351 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
352 {PCI_VENDOR_ID_NVIDIA, 0x0146,
353 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
354 {PCI_VENDOR_ID_NVIDIA, 0x0147,
355 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
356 {PCI_VENDOR_ID_NVIDIA, 0x0148,
357 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
358 {PCI_VENDOR_ID_NVIDIA, 0x0149,
359 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
360 {PCI_VENDOR_ID_NVIDIA, 0x014b,
361 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
362 {PCI_VENDOR_ID_NVIDIA, 0x14c,
363 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
364 {PCI_VENDOR_ID_NVIDIA, 0x014d,
365 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
366 {PCI_VENDOR_ID_NVIDIA, 0x0160,
367 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
368 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
369 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
370 {PCI_VENDOR_ID_NVIDIA, 0x0162,
371 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
372 {PCI_VENDOR_ID_NVIDIA, 0x0163,
373 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
374 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
375 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
376 {PCI_VENDOR_ID_NVIDIA, 0x0165,
377 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
378 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
379 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
380 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
381 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
382 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
383 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
384 {PCI_VENDOR_ID_NVIDIA, 0x0169,
385 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
386 {PCI_VENDOR_ID_NVIDIA, 0x016b,
387 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
388 {PCI_VENDOR_ID_NVIDIA, 0x016c,
389 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
390 {PCI_VENDOR_ID_NVIDIA, 0x016d,
391 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
392 {PCI_VENDOR_ID_NVIDIA, 0x016e,
393 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
394 {PCI_VENDOR_ID_NVIDIA, 0x0210,
395 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
396 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
397 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
398 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
399 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
400 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
401 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Calin A. Culianu7015faa2005-11-04 20:38:04 -0500402 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT,
403 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
404 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX,
405 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
406 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800,
407 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
408 {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX,
409 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 {PCI_VENDOR_ID_NVIDIA, 0x021d,
411 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
412 {PCI_VENDOR_ID_NVIDIA, 0x021e,
413 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
414 {PCI_VENDOR_ID_NVIDIA, 0x0220,
415 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
416 {PCI_VENDOR_ID_NVIDIA, 0x0221,
417 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
418 {PCI_VENDOR_ID_NVIDIA, 0x0222,
419 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
420 {PCI_VENDOR_ID_NVIDIA, 0x0228,
421 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
422 {0,} /* terminate list */
423};
424
425MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
426
427/* command line data, set in nvidiafb_setup() */
428static int flatpanel __devinitdata = -1; /* Autodetect later */
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -0800429static int fpdither __devinitdata = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430static int forceCRTC __devinitdata = -1;
431static int hwcur __devinitdata = 0;
432static int noaccel __devinitdata = 0;
433static int noscale __devinitdata = 0;
434static int paneltweak __devinitdata = 0;
Antonino A. Daplas917bb072005-05-01 08:59:22 -0700435static int vram __devinitdata = 0;
Antonino A. Daplasade91852006-01-09 20:53:39 -0800436static int bpp __devinitdata = 8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437#ifdef CONFIG_MTRR
438static int nomtrr __devinitdata = 0;
439#endif
440
441static char *mode_option __devinitdata = NULL;
442
443static struct fb_fix_screeninfo __devinitdata nvidiafb_fix = {
444 .type = FB_TYPE_PACKED_PIXELS,
445 .xpanstep = 8,
446 .ypanstep = 1,
447};
448
449static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
450 .xres = 640,
451 .yres = 480,
452 .xres_virtual = 640,
453 .yres_virtual = 480,
454 .bits_per_pixel = 8,
455 .red = {0, 8, 0},
456 .green = {0, 8, 0},
457 .blue = {0, 8, 0},
458 .transp = {0, 0, 0},
459 .activate = FB_ACTIVATE_NOW,
460 .height = -1,
461 .width = -1,
462 .pixclock = 39721,
463 .left_margin = 40,
464 .right_margin = 24,
465 .upper_margin = 32,
466 .lower_margin = 11,
467 .hsync_len = 96,
468 .vsync_len = 2,
469 .vmode = FB_VMODE_NONINTERLACED
470};
471
472/*
473 * Backlight control
474 */
475#ifdef CONFIG_PMAC_BACKLIGHT
476
477static int nvidia_backlight_levels[] = {
478 0x158,
479 0x192,
480 0x1c6,
481 0x200,
482 0x234,
483 0x268,
484 0x2a2,
485 0x2d6,
486 0x310,
487 0x344,
488 0x378,
489 0x3b2,
490 0x3e6,
491 0x41a,
492 0x454,
493 0x534,
494};
495
496/* ------------------------------------------------------------------------- *
497 *
498 * Backlight operations
499 *
500 * ------------------------------------------------------------------------- */
501
502static int nvidia_set_backlight_enable(int on, int level, void *data)
503{
Antonino A. Daplasc439e342006-01-09 20:53:02 -0800504 struct nvidia_par *par = data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 u32 tmp_pcrt, tmp_pmc, fpcontrol;
506
507 tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
508 tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
509 fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
510
511 if (on && (level > BACKLIGHT_OFF)) {
512 tmp_pcrt |= 0x1;
513 tmp_pmc |= (1 << 31); // backlight bit
514 tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
515 }
516
517 if (on)
518 fpcontrol |= par->fpSyncs;
519 else
520 fpcontrol |= 0x20000022;
521
522 NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
523 NV_WR32(par->PMC, 0x10F0, tmp_pmc);
524 NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
525
526 return 0;
527}
528
529static int nvidia_set_backlight_level(int level, void *data)
530{
531 return nvidia_set_backlight_enable(1, level, data);
532}
533
534static struct backlight_controller nvidia_backlight_controller = {
535 nvidia_set_backlight_enable,
536 nvidia_set_backlight_level
537};
538
539#endif /* CONFIG_PMAC_BACKLIGHT */
540
541static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
542 u16 bg, u16 fg, u32 w, u32 h)
543{
James Simmonsf1ab5da2005-06-21 17:17:07 -0700544 u32 *data = (u32 *) data8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 int i, j, k = 0;
546 u32 b, tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 w = (w + 1) & ~1;
549
550 for (i = 0; i < h; i++) {
551 b = *data++;
552 reverse_order(&b);
553
554 for (j = 0; j < w / 2; j++) {
555 tmp = 0;
556#if defined (__BIG_ENDIAN)
557 tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
558 b <<= 1;
559 tmp |= (b & (1 << 31)) ? fg : bg;
560 b <<= 1;
561#else
562 tmp = (b & 1) ? fg : bg;
563 b >>= 1;
564 tmp |= (b & 1) ? fg << 16 : bg << 16;
565 b >>= 1;
566#endif
567 NV_WR32(&par->CURSOR[k++], 0, tmp);
568 }
569 k += (MAX_CURS - w) / 2;
570 }
571}
572
573static void nvidia_write_clut(struct nvidia_par *par,
574 u8 regnum, u8 red, u8 green, u8 blue)
575{
576 NVWriteDacMask(par, 0xff);
577 NVWriteDacWriteAddr(par, regnum);
578 NVWriteDacData(par, red);
579 NVWriteDacData(par, green);
580 NVWriteDacData(par, blue);
581}
582
583static void nvidia_read_clut(struct nvidia_par *par,
584 u8 regnum, u8 * red, u8 * green, u8 * blue)
585{
586 NVWriteDacMask(par, 0xff);
587 NVWriteDacReadAddr(par, regnum);
588 *red = NVReadDacData(par);
589 *green = NVReadDacData(par);
590 *blue = NVReadDacData(par);
591}
592
593static int nvidia_panel_tweak(struct nvidia_par *par,
594 struct _riva_hw_state *state)
595{
596 int tweak = 0;
597
598 if (par->paneltweak) {
599 tweak = par->paneltweak;
600 } else {
601 /* begin flat panel hacks */
602 /* This is unfortunate, but some chips need this register
603 tweaked or else you get artifacts where adjacent pixels are
604 swapped. There are no hard rules for what to set here so all
605 we can do is experiment and apply hacks. */
606
607 if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
608 /* At least one NV34 laptop needs this workaround. */
609 tweak = -1;
610 }
611
612 if((par->Chipset & 0xfff0) == 0x0310) {
613 tweak = 1;
614 }
615 /* end flat panel hacks */
616 }
617
618 return tweak;
619}
620
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -0800621static void nvidia_vga_protect(struct nvidia_par *par, int on)
622{
623 unsigned char tmp;
624
625 if (on) {
626 /*
627 * Turn off screen and disable sequencer.
628 */
629 tmp = NVReadSeq(par, 0x01);
630
631 NVWriteSeq(par, 0x00, 0x01); /* Synchronous Reset */
632 NVWriteSeq(par, 0x01, tmp | 0x20); /* disable the display */
633 } else {
634 /*
635 * Reenable sequencer, then turn on screen.
636 */
637
638 tmp = NVReadSeq(par, 0x01);
639
640 NVWriteSeq(par, 0x01, tmp & ~0x20); /* reenable display */
641 NVWriteSeq(par, 0x00, 0x03); /* End Reset */
642 }
643}
644
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645static void nvidia_save_vga(struct nvidia_par *par,
646 struct _riva_hw_state *state)
647{
648 int i;
649
650 NVTRACE_ENTER();
651 NVLockUnlock(par, 0);
652
653 NVUnloadStateExt(par, state);
654
655 state->misc_output = NVReadMiscOut(par);
656
657 for (i = 0; i < NUM_CRT_REGS; i++)
658 state->crtc[i] = NVReadCrtc(par, i);
659
660 for (i = 0; i < NUM_ATC_REGS; i++)
661 state->attr[i] = NVReadAttr(par, i);
662
663 for (i = 0; i < NUM_GRC_REGS; i++)
664 state->gra[i] = NVReadGr(par, i);
665
666 for (i = 0; i < NUM_SEQ_REGS; i++)
667 state->seq[i] = NVReadSeq(par, i);
668 NVTRACE_LEAVE();
669}
670
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800671#undef DUMP_REG
672
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -0800673static void nvidia_write_regs(struct nvidia_par *par,
674 struct _riva_hw_state *state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 int i;
677
678 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680 NVLoadStateExt(par, state);
681
682 NVWriteMiscOut(par, state->misc_output);
683
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800684 for (i = 1; i < NUM_SEQ_REGS; i++) {
685#ifdef DUMP_REG
686 printk(" SEQ[%02x] = %08x\n", i, state->seq[i]);
687#endif
688 NVWriteSeq(par, i, state->seq[i]);
689 }
690
691 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17] */
692 NVWriteCrtc(par, 0x11, state->crtc[0x11] & ~0x80);
693
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 for (i = 0; i < NUM_CRT_REGS; i++) {
695 switch (i) {
696 case 0x19:
697 case 0x20 ... 0x40:
698 break;
699 default:
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800700#ifdef DUMP_REG
701 printk("CRTC[%02x] = %08x\n", i, state->crtc[i]);
702#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 NVWriteCrtc(par, i, state->crtc[i]);
704 }
705 }
706
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800707 for (i = 0; i < NUM_GRC_REGS; i++) {
708#ifdef DUMP_REG
709 printk(" GRA[%02x] = %08x\n", i, state->gra[i]);
710#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 NVWriteGr(par, i, state->gra[i]);
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800714 for (i = 0; i < NUM_ATC_REGS; i++) {
715#ifdef DUMP_REG
716 printk("ATTR[%02x] = %08x\n", i, state->attr[i]);
717#endif
718 NVWriteAttr(par, i, state->attr[i]);
719 }
720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 NVTRACE_LEAVE();
722}
723
724static int nvidia_calc_regs(struct fb_info *info)
725{
726 struct nvidia_par *par = info->par;
727 struct _riva_hw_state *state = &par->ModeReg;
Antonino A. Daplasb8c90942005-09-09 13:04:37 -0700728 int i, depth = fb_get_color_depth(&info->var, &info->fix);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 int h_display = info->var.xres / 8 - 1;
730 int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
731 int h_end = (info->var.xres + info->var.right_margin +
732 info->var.hsync_len) / 8 - 1;
733 int h_total = (info->var.xres + info->var.right_margin +
734 info->var.hsync_len + info->var.left_margin) / 8 - 5;
735 int h_blank_s = h_display;
736 int h_blank_e = h_total + 4;
737 int v_display = info->var.yres - 1;
738 int v_start = info->var.yres + info->var.lower_margin - 1;
739 int v_end = (info->var.yres + info->var.lower_margin +
740 info->var.vsync_len) - 1;
741 int v_total = (info->var.yres + info->var.lower_margin +
742 info->var.vsync_len + info->var.upper_margin) - 2;
743 int v_blank_s = v_display;
744 int v_blank_e = v_total + 1;
745
746 /*
747 * Set all CRTC values.
748 */
749
750 if (info->var.vmode & FB_VMODE_INTERLACED)
751 v_total |= 1;
752
753 if (par->FlatPanel == 1) {
754 v_start = v_total - 3;
755 v_end = v_total - 2;
756 v_blank_s = v_start;
757 h_start = h_total - 5;
758 h_end = h_total - 2;
759 h_blank_e = h_total + 4;
760 }
761
762 state->crtc[0x0] = Set8Bits(h_total);
763 state->crtc[0x1] = Set8Bits(h_display);
764 state->crtc[0x2] = Set8Bits(h_blank_s);
765 state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
766 | SetBit(7);
767 state->crtc[0x4] = Set8Bits(h_start);
768 state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
769 | SetBitField(h_end, 4: 0, 4:0);
770 state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
771 state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
772 | SetBitField(v_display, 8: 8, 1:1)
773 | SetBitField(v_start, 8: 8, 2:2)
774 | SetBitField(v_blank_s, 8: 8, 3:3)
775 | SetBit(4)
776 | SetBitField(v_total, 9: 9, 5:5)
777 | SetBitField(v_display, 9: 9, 6:6)
778 | SetBitField(v_start, 9: 9, 7:7);
779 state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
780 | SetBit(6)
781 | ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
782 state->crtc[0x10] = Set8Bits(v_start);
783 state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
784 state->crtc[0x12] = Set8Bits(v_display);
785 state->crtc[0x13] = ((info->var.xres_virtual / 8) *
786 (info->var.bits_per_pixel / 8));
787 state->crtc[0x15] = Set8Bits(v_blank_s);
788 state->crtc[0x16] = Set8Bits(v_blank_e);
789
790 state->attr[0x10] = 0x01;
791
792 if (par->Television)
793 state->attr[0x11] = 0x00;
794
795 state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
796 | SetBitField(v_blank_s, 10: 10, 3:3)
797 | SetBitField(v_start, 10: 10, 2:2)
798 | SetBitField(v_display, 10: 10, 1:1)
799 | SetBitField(v_total, 10: 10, 0:0);
800
801 state->horiz = SetBitField(h_total, 8: 8, 0:0)
802 | SetBitField(h_display, 8: 8, 1:1)
803 | SetBitField(h_blank_s, 8: 8, 2:2)
804 | SetBitField(h_start, 8: 8, 3:3);
805
806 state->extra = SetBitField(v_total, 11: 11, 0:0)
807 | SetBitField(v_display, 11: 11, 2:2)
808 | SetBitField(v_start, 11: 11, 4:4)
809 | SetBitField(v_blank_s, 11: 11, 6:6);
810
811 if (info->var.vmode & FB_VMODE_INTERLACED) {
812 h_total = (h_total >> 1) & ~1;
813 state->interlace = Set8Bits(h_total);
814 state->horiz |= SetBitField(h_total, 8: 8, 4:4);
815 } else {
816 state->interlace = 0xff; /* interlace off */
817 }
818
819 /*
820 * Calculate the extended registers.
821 */
822
823 if (depth < 24)
824 i = depth;
825 else
826 i = 32;
827
828 if (par->Architecture >= NV_ARCH_10)
829 par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
830 par->CursorStart);
831
832 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
833 state->misc_output &= ~0x40;
834 else
835 state->misc_output |= 0x40;
836 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
837 state->misc_output &= ~0x80;
838 else
839 state->misc_output |= 0x80;
840
841 NVCalcStateExt(par, state, i, info->var.xres_virtual,
842 info->var.xres, info->var.yres_virtual,
843 1000000000 / info->var.pixclock, info->var.vmode);
844
845 state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
846 if (par->FlatPanel == 1) {
847 state->pixel |= (1 << 7);
848
849 if (!par->fpScaler || (par->fpWidth <= info->var.xres)
850 || (par->fpHeight <= info->var.yres)) {
851 state->scale |= (1 << 8);
852 }
853
854 if (!par->crtcSync_read) {
855 state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
856 par->crtcSync_read = 1;
857 }
858
859 par->PanelTweak = nvidia_panel_tweak(par, state);
860 }
861
862 state->vpll = state->pll;
863 state->vpll2 = state->pll;
864 state->vpllB = state->pllB;
865 state->vpll2B = state->pllB;
866
867 VGA_WR08(par->PCIO, 0x03D4, 0x1C);
868 state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
869
870 if (par->CRTCnumber) {
871 state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
872 state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
873 state->crtcOwner = 3;
874 state->pllsel |= 0x20000800;
875 state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
876 if (par->twoStagePLL)
877 state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
878 } else if (par->twoHeads) {
879 state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
880 state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
881 state->crtcOwner = 0;
882 state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
883 if (par->twoStagePLL)
884 state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
885 }
886
887 state->cursorConfig = 0x00000100;
888
889 if (info->var.vmode & FB_VMODE_DOUBLE)
890 state->cursorConfig |= (1 << 4);
891
892 if (par->alphaCursor) {
893 if ((par->Chipset & 0x0ff0) != 0x0110)
894 state->cursorConfig |= 0x04011000;
895 else
896 state->cursorConfig |= 0x14011000;
897 state->general |= (1 << 29);
898 } else
899 state->cursorConfig |= 0x02000000;
900
901 if (par->twoHeads) {
902 if ((par->Chipset & 0x0ff0) == 0x0110) {
903 state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
904 ~0x00010000;
905 if (par->FPDither)
906 state->dither |= 0x00010000;
907 } else {
908 state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
909 if (par->FPDither)
910 state->dither |= 1;
911 }
912 }
913
914 state->timingH = 0;
915 state->timingV = 0;
916 state->displayV = info->var.xres;
917
918 return 0;
919}
920
921static void nvidia_init_vga(struct fb_info *info)
922{
923 struct nvidia_par *par = info->par;
924 struct _riva_hw_state *state = &par->ModeReg;
925 int i;
926
927 for (i = 0; i < 0x10; i++)
928 state->attr[i] = i;
929 state->attr[0x10] = 0x41;
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -0800930 state->attr[0x11] = 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 state->attr[0x12] = 0x0f;
932 state->attr[0x13] = 0x00;
933 state->attr[0x14] = 0x00;
934
935 memset(state->crtc, 0x00, NUM_CRT_REGS);
936 state->crtc[0x0a] = 0x20;
937 state->crtc[0x17] = 0xe3;
938 state->crtc[0x18] = 0xff;
939 state->crtc[0x28] = 0x40;
940
941 memset(state->gra, 0x00, NUM_GRC_REGS);
942 state->gra[0x05] = 0x40;
943 state->gra[0x06] = 0x05;
944 state->gra[0x07] = 0x0f;
945 state->gra[0x08] = 0xff;
946
947 state->seq[0x00] = 0x03;
948 state->seq[0x01] = 0x01;
949 state->seq[0x02] = 0x0f;
950 state->seq[0x03] = 0x00;
951 state->seq[0x04] = 0x0e;
952
953 state->misc_output = 0xeb;
954}
955
956static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
957{
958 struct nvidia_par *par = info->par;
959 u8 data[MAX_CURS * MAX_CURS / 8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 int i, set = cursor->set;
James Simmonsf1ab5da2005-06-21 17:17:07 -0700961 u16 fg, bg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Antonino A. Daplas7a482422005-09-21 07:30:21 +0800963 if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
James Simmonsf1ab5da2005-06-21 17:17:07 -0700964 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965
966 NVShowHideCursor(par, 0);
967
968 if (par->cursor_reset) {
969 set = FB_CUR_SETALL;
970 par->cursor_reset = 0;
971 }
972
973 if (set & FB_CUR_SETSIZE)
974 memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
975
976 if (set & FB_CUR_SETPOS) {
977 u32 xx, yy, temp;
978
979 yy = cursor->image.dy - info->var.yoffset;
980 xx = cursor->image.dx - info->var.xoffset;
981 temp = xx & 0xFFFF;
982 temp |= yy << 16;
983
984 NV_WR32(par->PRAMDAC, 0x0000300, temp);
985 }
986
987 if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
988 u32 bg_idx = cursor->image.bg_color;
989 u32 fg_idx = cursor->image.fg_color;
990 u32 s_pitch = (cursor->image.width + 7) >> 3;
991 u32 d_pitch = MAX_CURS / 8;
992 u8 *dat = (u8 *) cursor->image.data;
993 u8 *msk = (u8 *) cursor->mask;
994 u8 *src;
995
996 src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
997
998 if (src) {
999 switch (cursor->rop) {
1000 case ROP_XOR:
James Simmonsf1ab5da2005-06-21 17:17:07 -07001001 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 src[i] = dat[i] ^ msk[i];
1003 break;
1004 case ROP_COPY:
1005 default:
James Simmonsf1ab5da2005-06-21 17:17:07 -07001006 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 src[i] = dat[i] & msk[i];
1008 break;
1009 }
1010
James Simmonsf1ab5da2005-06-21 17:17:07 -07001011 fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
1012 cursor->image.height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014 bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
1015 ((info->cmap.green[bg_idx] & 0xf8) << 2) |
1016 ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
1017
1018 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
1019 ((info->cmap.green[fg_idx] & 0xf8) << 2) |
1020 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
1021
1022 NVLockUnlock(par, 0);
1023
1024 nvidiafb_load_cursor_image(par, data, bg, fg,
1025 cursor->image.width,
1026 cursor->image.height);
1027 kfree(src);
1028 }
1029 }
1030
1031 if (cursor->enable)
1032 NVShowHideCursor(par, 1);
1033
1034 return 0;
1035}
1036
1037static int nvidiafb_set_par(struct fb_info *info)
1038{
1039 struct nvidia_par *par = info->par;
1040
1041 NVTRACE_ENTER();
1042
1043 NVLockUnlock(par, 1);
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001044 if (!par->FlatPanel || !par->twoHeads)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 par->FPDither = 0;
1046
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001047 if (par->FPDither < 0) {
1048 if ((par->Chipset & 0x0ff0) == 0x0110)
1049 par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x0528)
1050 & 0x00010000);
1051 else
1052 par->FPDither = !!(NV_RD32(par->PRAMDAC, 0x083C) & 1);
1053 printk(KERN_INFO PFX "Flat panel dithering %s\n",
1054 par->FPDither ? "enabled" : "disabled");
1055 }
1056
Antonino A. Daplasb8c90942005-09-09 13:04:37 -07001057 info->fix.visual = (info->var.bits_per_pixel == 8) ?
1058 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1059
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 nvidia_init_vga(info);
1061 nvidia_calc_regs(info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 NVLockUnlock(par, 0);
1064 if (par->twoHeads) {
1065 VGA_WR08(par->PCIO, 0x03D4, 0x44);
1066 VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
1067 NVLockUnlock(par, 0);
1068 }
1069
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -08001070 nvidia_vga_protect(par, 1);
1071
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001072 nvidia_write_regs(par, &par->ModeReg);
1073 NVSetStartAddress(par, 0);
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -08001074
1075#if defined (__BIG_ENDIAN)
1076 /* turn on LFB swapping */
1077 {
1078 unsigned char tmp;
1079
1080 VGA_WR08(par->PCIO, 0x3d4, 0x46);
1081 tmp = VGA_RD08(par->PCIO, 0x3d5);
1082 tmp |= (1 << 7);
1083 VGA_WR08(par->PCIO, 0x3d5, tmp);
1084 }
1085#endif
1086
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 info->fix.line_length = (info->var.xres_virtual *
1088 info->var.bits_per_pixel) >> 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 if (info->var.accel_flags) {
1090 info->fbops->fb_imageblit = nvidiafb_imageblit;
1091 info->fbops->fb_fillrect = nvidiafb_fillrect;
1092 info->fbops->fb_copyarea = nvidiafb_copyarea;
1093 info->fbops->fb_sync = nvidiafb_sync;
1094 info->pixmap.scan_align = 4;
1095 info->flags &= ~FBINFO_HWACCEL_DISABLED;
1096 NVResetGraphics(info);
1097 } else {
1098 info->fbops->fb_imageblit = cfb_imageblit;
1099 info->fbops->fb_fillrect = cfb_fillrect;
1100 info->fbops->fb_copyarea = cfb_copyarea;
1101 info->fbops->fb_sync = NULL;
1102 info->pixmap.scan_align = 1;
1103 info->flags |= FBINFO_HWACCEL_DISABLED;
1104 }
1105
1106 par->cursor_reset = 1;
1107
Benjamin Herrenschmidt85f15032005-11-07 01:00:30 -08001108 nvidia_vga_protect(par, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109
1110 NVTRACE_LEAVE();
1111 return 0;
1112}
1113
1114static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1115 unsigned blue, unsigned transp,
1116 struct fb_info *info)
1117{
1118 struct nvidia_par *par = info->par;
1119 int i;
1120
1121 NVTRACE_ENTER();
1122 if (regno >= (1 << info->var.green.length))
1123 return -EINVAL;
1124
1125 if (info->var.grayscale) {
1126 /* gray = 0.30*R + 0.59*G + 0.11*B */
1127 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
1128 }
1129
1130 if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1131 ((u32 *) info->pseudo_palette)[regno] =
1132 (regno << info->var.red.offset) |
1133 (regno << info->var.green.offset) |
1134 (regno << info->var.blue.offset);
1135 }
1136
1137 switch (info->var.bits_per_pixel) {
1138 case 8:
1139 /* "transparent" stuff is completely ignored. */
1140 nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
1141 break;
1142 case 16:
1143 if (info->var.green.length == 5) {
1144 for (i = 0; i < 8; i++) {
1145 nvidia_write_clut(par, regno * 8 + i, red >> 8,
1146 green >> 8, blue >> 8);
1147 }
1148 } else {
1149 u8 r, g, b;
1150
1151 if (regno < 32) {
1152 for (i = 0; i < 8; i++) {
1153 nvidia_write_clut(par, regno * 8 + i,
1154 red >> 8, green >> 8,
1155 blue >> 8);
1156 }
1157 }
1158
1159 nvidia_read_clut(par, regno * 4, &r, &g, &b);
1160
1161 for (i = 0; i < 4; i++)
1162 nvidia_write_clut(par, regno * 4 + i, r,
1163 green >> 8, b);
1164 }
1165 break;
1166 case 32:
1167 nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
1168 break;
1169 default:
1170 /* do nothing */
1171 break;
1172 }
1173
1174 NVTRACE_LEAVE();
1175 return 0;
1176}
1177
1178static int nvidiafb_check_var(struct fb_var_screeninfo *var,
1179 struct fb_info *info)
1180{
1181 struct nvidia_par *par = info->par;
1182 int memlen, vramlen, mode_valid = 0;
1183 int pitch, err = 0;
1184
1185 NVTRACE_ENTER();
1186
1187 var->transp.offset = 0;
1188 var->transp.length = 0;
1189
1190 var->xres &= ~7;
1191
1192 if (var->bits_per_pixel <= 8)
1193 var->bits_per_pixel = 8;
1194 else if (var->bits_per_pixel <= 16)
1195 var->bits_per_pixel = 16;
1196 else
1197 var->bits_per_pixel = 32;
1198
1199 switch (var->bits_per_pixel) {
1200 case 8:
1201 var->red.offset = 0;
1202 var->red.length = 8;
1203 var->green.offset = 0;
1204 var->green.length = 8;
1205 var->blue.offset = 0;
1206 var->blue.length = 8;
1207 var->transp.offset = 0;
1208 var->transp.length = 0;
1209 break;
1210 case 16:
1211 var->green.length = (var->green.length < 6) ? 5 : 6;
1212 var->red.length = 5;
1213 var->blue.length = 5;
1214 var->transp.length = 6 - var->green.length;
1215 var->blue.offset = 0;
1216 var->green.offset = 5;
1217 var->red.offset = 5 + var->green.length;
1218 var->transp.offset = (5 + var->red.offset) & 15;
1219 break;
1220 case 32: /* RGBA 8888 */
1221 var->red.offset = 16;
1222 var->red.length = 8;
1223 var->green.offset = 8;
1224 var->green.length = 8;
1225 var->blue.offset = 0;
1226 var->blue.length = 8;
1227 var->transp.length = 8;
1228 var->transp.offset = 24;
1229 break;
1230 }
1231
1232 var->red.msb_right = 0;
1233 var->green.msb_right = 0;
1234 var->blue.msb_right = 0;
1235 var->transp.msb_right = 0;
1236
1237 if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
1238 !info->monspecs.dclkmax || !fb_validate_mode(var, info))
1239 mode_valid = 1;
1240
1241 /* calculate modeline if supported by monitor */
1242 if (!mode_valid && info->monspecs.gtf) {
1243 if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1244 mode_valid = 1;
1245 }
1246
1247 if (!mode_valid) {
1248 struct fb_videomode *mode;
1249
1250 mode = fb_find_best_mode(var, &info->modelist);
1251 if (mode) {
1252 fb_videomode_to_var(var, mode);
1253 mode_valid = 1;
1254 }
1255 }
1256
1257 if (!mode_valid && info->monspecs.modedb_len)
1258 return -EINVAL;
1259
1260 if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
1261 par->fpHeight < var->yres))
1262 return -EINVAL;
1263
1264 if (var->yres_virtual < var->yres)
1265 var->yres_virtual = var->yres;
1266
1267 if (var->xres_virtual < var->xres)
1268 var->xres_virtual = var->xres;
1269
1270 var->xres_virtual = (var->xres_virtual + 63) & ~63;
1271
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001272 vramlen = info->screen_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
1274 memlen = pitch * var->yres_virtual;
1275
1276 if (memlen > vramlen) {
1277 var->yres_virtual = vramlen / pitch;
1278
1279 if (var->yres_virtual < var->yres) {
1280 var->yres_virtual = var->yres;
1281 var->xres_virtual = vramlen / var->yres_virtual;
1282 var->xres_virtual /= var->bits_per_pixel / 8;
1283 var->xres_virtual &= ~63;
1284 pitch = (var->xres_virtual *
1285 var->bits_per_pixel + 7) / 8;
1286 memlen = pitch * var->yres;
1287
1288 if (var->xres_virtual < var->xres) {
1289 printk("nvidiafb: required video memory, "
1290 "%d bytes, for %dx%d-%d (virtual) "
1291 "is out of range\n",
1292 memlen, var->xres_virtual,
1293 var->yres_virtual, var->bits_per_pixel);
1294 err = -ENOMEM;
1295 }
1296 }
1297 }
1298
1299 if (var->accel_flags) {
1300 if (var->yres_virtual > 0x7fff)
1301 var->yres_virtual = 0x7fff;
1302 if (var->xres_virtual > 0x7fff)
1303 var->xres_virtual = 0x7fff;
1304 }
1305
1306 var->xres_virtual &= ~63;
1307
1308 NVTRACE_LEAVE();
1309
1310 return err;
1311}
1312
1313static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
1314 struct fb_info *info)
1315{
1316 struct nvidia_par *par = info->par;
1317 u32 total;
1318
Antonino A. Daplas3c8d61b2005-11-13 16:06:34 -08001319 total = var->yoffset * info->fix.line_length + var->xoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 NVSetStartAddress(par, total);
1322
1323 return 0;
1324}
1325
1326static int nvidiafb_blank(int blank, struct fb_info *info)
1327{
1328 struct nvidia_par *par = info->par;
1329 unsigned char tmp, vesa;
1330
1331 tmp = NVReadSeq(par, 0x01) & ~0x20; /* screen on/off */
1332 vesa = NVReadCrtc(par, 0x1a) & ~0xc0; /* sync on/off */
1333
1334 NVTRACE_ENTER();
1335
1336 if (blank)
1337 tmp |= 0x20;
1338
1339 switch (blank) {
1340 case FB_BLANK_UNBLANK:
1341 case FB_BLANK_NORMAL:
1342 break;
1343 case FB_BLANK_VSYNC_SUSPEND:
1344 vesa |= 0x80;
1345 break;
1346 case FB_BLANK_HSYNC_SUSPEND:
1347 vesa |= 0x40;
1348 break;
1349 case FB_BLANK_POWERDOWN:
1350 vesa |= 0xc0;
1351 break;
1352 }
1353
1354 NVWriteSeq(par, 0x01, tmp);
1355 NVWriteCrtc(par, 0x1a, vesa);
1356
1357#ifdef CONFIG_PMAC_BACKLIGHT
1358 if (par->FlatPanel && _machine == _MACH_Pmac) {
1359 set_backlight_enable(!blank);
1360 }
1361#endif
1362
1363 NVTRACE_LEAVE();
1364
1365 return 0;
1366}
1367
1368static struct fb_ops nvidia_fb_ops = {
1369 .owner = THIS_MODULE,
1370 .fb_check_var = nvidiafb_check_var,
1371 .fb_set_par = nvidiafb_set_par,
1372 .fb_setcolreg = nvidiafb_setcolreg,
1373 .fb_pan_display = nvidiafb_pan_display,
1374 .fb_blank = nvidiafb_blank,
1375 .fb_fillrect = nvidiafb_fillrect,
1376 .fb_copyarea = nvidiafb_copyarea,
1377 .fb_imageblit = nvidiafb_imageblit,
1378 .fb_cursor = nvidiafb_cursor,
1379 .fb_sync = nvidiafb_sync,
1380};
1381
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001382#ifdef CONFIG_PM
1383static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
1384{
1385 struct fb_info *info = pci_get_drvdata(dev);
1386 struct nvidia_par *par = info->par;
1387
1388 acquire_console_sem();
1389 par->pm_state = state.event;
1390
1391 if (state.event == PM_EVENT_FREEZE) {
1392 dev->dev.power.power_state = state;
1393 } else {
1394 fb_set_suspend(info, 1);
1395 nvidiafb_blank(FB_BLANK_POWERDOWN, info);
1396 nvidia_write_regs(par, &par->SavedReg);
1397 pci_save_state(dev);
1398 pci_disable_device(dev);
1399 pci_set_power_state(dev, pci_choose_state(dev, state));
1400 }
1401
1402 release_console_sem();
1403 return 0;
1404}
1405
1406static int nvidiafb_resume(struct pci_dev *dev)
1407{
1408 struct fb_info *info = pci_get_drvdata(dev);
1409 struct nvidia_par *par = info->par;
1410
1411 acquire_console_sem();
1412 pci_set_power_state(dev, PCI_D0);
1413
1414 if (par->pm_state != PM_EVENT_FREEZE) {
1415 pci_restore_state(dev);
1416 pci_enable_device(dev);
1417 pci_set_master(dev);
1418 }
1419
1420 par->pm_state = PM_EVENT_ON;
1421 nvidiafb_set_par(info);
1422 fb_set_suspend (info, 0);
1423 nvidiafb_blank(FB_BLANK_UNBLANK, info);
1424
1425 release_console_sem();
1426 return 0;
1427}
1428#else
1429#define nvidiafb_suspend NULL
1430#define nvidiafb_resume NULL
1431#endif
1432
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433static int __devinit nvidia_set_fbinfo(struct fb_info *info)
1434{
1435 struct fb_monspecs *specs = &info->monspecs;
1436 struct fb_videomode modedb;
1437 struct nvidia_par *par = info->par;
1438 int lpitch;
1439
1440 NVTRACE_ENTER();
1441 info->flags = FBINFO_DEFAULT
1442 | FBINFO_HWACCEL_IMAGEBLIT
1443 | FBINFO_HWACCEL_FILLRECT
1444 | FBINFO_HWACCEL_COPYAREA
1445 | FBINFO_HWACCEL_YPAN;
1446
1447 fb_videomode_to_modelist(info->monspecs.modedb,
1448 info->monspecs.modedb_len, &info->modelist);
1449 fb_var_to_videomode(&modedb, &nvidiafb_default_var);
1450
Antonino A. Daplasade91852006-01-09 20:53:39 -08001451 switch (bpp) {
1452 case 0 ... 8:
1453 bpp = 8;
1454 break;
1455 case 9 ... 16:
1456 bpp = 16;
1457 break;
1458 default:
1459 bpp = 32;
1460 break;
1461 }
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 if (specs->modedb != NULL) {
Antonino A. Daplas5ee1ef92005-11-07 01:00:55 -08001464 struct fb_videomode *modedb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
Antonino A. Daplas5ee1ef92005-11-07 01:00:55 -08001466 modedb = fb_find_best_display(specs, &info->modelist);
1467 fb_videomode_to_var(&nvidiafb_default_var, modedb);
Antonino A. Daplasade91852006-01-09 20:53:39 -08001468 nvidiafb_default_var.bits_per_pixel = bpp;
Antonino Daplasdb6778d2005-08-08 14:22:43 +08001469 } else if (par->fpWidth && par->fpHeight) {
1470 char buf[16];
1471
1472 memset(buf, 0, 16);
Antonino A. Daplas948a95f2005-09-09 13:09:59 -07001473 snprintf(buf, 15, "%dx%dMR", par->fpWidth, par->fpHeight);
Antonino Daplasdb6778d2005-08-08 14:22:43 +08001474 fb_find_mode(&nvidiafb_default_var, info, buf, specs->modedb,
Antonino A. Daplasade91852006-01-09 20:53:39 -08001475 specs->modedb_len, &modedb, bpp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 }
1477
1478 if (mode_option)
1479 fb_find_mode(&nvidiafb_default_var, info, mode_option,
Antonino A. Daplasade91852006-01-09 20:53:39 -08001480 specs->modedb, specs->modedb_len, &modedb, bpp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482 info->var = nvidiafb_default_var;
1483 info->fix.visual = (info->var.bits_per_pixel == 8) ?
1484 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1485 info->pseudo_palette = par->pseudo_palette;
1486 fb_alloc_cmap(&info->cmap, 256, 0);
1487 fb_destroy_modedb(info->monspecs.modedb);
1488 info->monspecs.modedb = NULL;
1489
1490 /* maximize virtual vertical length */
1491 lpitch = info->var.xres_virtual *
1492 ((info->var.bits_per_pixel + 7) >> 3);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001493 info->var.yres_virtual = info->screen_size / lpitch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
1495 info->pixmap.scan_align = 4;
1496 info->pixmap.buf_align = 4;
James Simmons58a60642005-06-21 17:17:08 -07001497 info->pixmap.access_align = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 info->pixmap.size = 8 * 1024;
1499 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1500
Antonino A. Daplas7a482422005-09-21 07:30:21 +08001501 if (!hwcur)
Antonino A. Daplasc465e052005-11-07 01:00:35 -08001502 info->fbops->fb_cursor = NULL;
Antonino A. Daplas7a482422005-09-21 07:30:21 +08001503
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 info->var.accel_flags = (!noaccel);
1505
1506 switch (par->Architecture) {
1507 case NV_ARCH_04:
1508 info->fix.accel = FB_ACCEL_NV4;
1509 break;
1510 case NV_ARCH_10:
1511 info->fix.accel = FB_ACCEL_NV_10;
1512 break;
1513 case NV_ARCH_20:
1514 info->fix.accel = FB_ACCEL_NV_20;
1515 break;
1516 case NV_ARCH_30:
1517 info->fix.accel = FB_ACCEL_NV_30;
1518 break;
1519 case NV_ARCH_40:
1520 info->fix.accel = FB_ACCEL_NV_40;
1521 break;
1522 }
1523
1524 NVTRACE_LEAVE();
1525
1526 return nvidiafb_check_var(&info->var, info);
1527}
1528
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001529static u32 __devinit nvidia_get_chipset(struct fb_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530{
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001531 struct nvidia_par *par = info->par;
1532 u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
1533
1534 printk("nvidiafb: PCI id - %x\n", id);
1535 if ((id & 0xfff0) == 0x00f0) {
1536 /* pci-e */
1537 printk("nvidiafb: PCI-E card\n");
1538 id = NV_RD32(par->REGS, 0x1800);
1539
1540 if ((id & 0x0000ffff) == 0x000010DE)
1541 id = 0x10DE0000 | (id >> 16);
1542 else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
1543 id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
1544 ((id >> 8) & 0x000000ff);
1545 }
1546
1547 printk("nvidiafb: Actual id - %x\n", id);
1548 return id;
1549}
1550
1551static u32 __devinit nvidia_get_arch(struct fb_info *info)
1552{
1553 struct nvidia_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 u32 arch = 0;
1555
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001556 switch (par->Chipset & 0x0ff0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 case 0x0100: /* GeForce 256 */
1558 case 0x0110: /* GeForce2 MX */
1559 case 0x0150: /* GeForce2 */
1560 case 0x0170: /* GeForce4 MX */
1561 case 0x0180: /* GeForce4 MX (8x AGP) */
1562 case 0x01A0: /* nForce */
1563 case 0x01F0: /* nForce2 */
1564 arch = NV_ARCH_10;
1565 break;
1566 case 0x0200: /* GeForce3 */
1567 case 0x0250: /* GeForce4 Ti */
1568 case 0x0280: /* GeForce4 Ti (8x AGP) */
1569 arch = NV_ARCH_20;
1570 break;
1571 case 0x0300: /* GeForceFX 5800 */
1572 case 0x0310: /* GeForceFX 5600 */
1573 case 0x0320: /* GeForceFX 5200 */
1574 case 0x0330: /* GeForceFX 5900 */
1575 case 0x0340: /* GeForceFX 5700 */
1576 arch = NV_ARCH_30;
1577 break;
1578 case 0x0040:
1579 case 0x00C0:
1580 case 0x0120:
1581 case 0x0130:
1582 case 0x0140:
1583 case 0x0160:
1584 case 0x01D0:
1585 case 0x0090:
1586 case 0x0210:
1587 case 0x0220:
1588 case 0x0230:
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001589 case 0x0290:
1590 case 0x0390:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 arch = NV_ARCH_40;
1592 break;
1593 case 0x0020: /* TNT, TNT2 */
1594 arch = NV_ARCH_04;
1595 break;
1596 default: /* unknown architecture */
1597 break;
1598 }
1599
1600 return arch;
1601}
1602
1603static int __devinit nvidiafb_probe(struct pci_dev *pd,
1604 const struct pci_device_id *ent)
1605{
1606 struct nvidia_par *par;
1607 struct fb_info *info;
1608 unsigned short cmd;
1609
1610
1611 NVTRACE_ENTER();
1612 assert(pd != NULL);
1613
1614 info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
1615
1616 if (!info)
1617 goto err_out;
1618
Antonino A. Daplasc439e342006-01-09 20:53:02 -08001619 par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 par->pci_dev = pd;
1621
1622 info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
1623
1624 if (info->pixmap.addr == NULL)
1625 goto err_out_kfree;
1626
1627 memset(info->pixmap.addr, 0, 8 * 1024);
1628
1629 if (pci_enable_device(pd)) {
1630 printk(KERN_ERR PFX "cannot enable PCI device\n");
1631 goto err_out_enable;
1632 }
1633
1634 if (pci_request_regions(pd, "nvidiafb")) {
1635 printk(KERN_ERR PFX "cannot request PCI regions\n");
1636 goto err_out_request;
1637 }
1638
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 par->FlatPanel = flatpanel;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 if (flatpanel == 1)
1641 printk(KERN_INFO PFX "flatpanel support enabled\n");
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001642 par->FPDither = fpdither;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 par->CRTCnumber = forceCRTC;
1645 par->FpScale = (!noscale);
1646 par->paneltweak = paneltweak;
1647
1648 /* enable IO and mem if not already done */
1649 pci_read_config_word(pd, PCI_COMMAND, &cmd);
1650 cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
1651 pci_write_config_word(pd, PCI_COMMAND, cmd);
1652
1653 nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
1654 nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
1655 nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
1656
1657 par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
1658
1659 if (!par->REGS) {
1660 printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
1661 goto err_out_free_base0;
1662 }
1663
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001664 par->Chipset = nvidia_get_chipset(info);
1665 printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
1666 par->Architecture = nvidia_get_arch(info);
1667
1668 if (par->Architecture == 0) {
1669 printk(KERN_ERR PFX "unknown NV_ARCH\n");
1670 goto err_out_arch;
1671 }
1672
1673 sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
1674
Antonino A. Daplas918799a2006-01-09 20:53:40 -08001675 if (NVCommonSetup(info))
1676 goto err_out_arch;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
1678 par->FbAddress = nvidiafb_fix.smem_start;
1679 par->FbMapSize = par->RamAmountKBytes * 1024;
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001680 if (vram && vram * 1024 * 1024 < par->FbMapSize)
1681 par->FbMapSize = vram * 1024 * 1024;
1682
1683 /* Limit amount of vram to 64 MB */
1684 if (par->FbMapSize > 64 * 1024 * 1024)
1685 par->FbMapSize = 64 * 1024 * 1024;
1686
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001687 if(par->Architecture >= NV_ARCH_40)
1688 par->FbUsableSize = par->FbMapSize - (560 * 1024);
1689 else
1690 par->FbUsableSize = par->FbMapSize - (128 * 1024);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
1692 16 * 1024;
1693 par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
Benjamin Herrenschmidt0137ecf2006-01-09 20:51:27 -08001694 par->CursorStart = par->FbUsableSize + (32 * 1024);
1695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001697 info->screen_size = par->FbUsableSize;
1698 nvidiafb_fix.smem_len = par->RamAmountKBytes * 1024;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
1700 if (!info->screen_base) {
1701 printk(KERN_ERR PFX "cannot ioremap FB base\n");
1702 goto err_out_free_base1;
1703 }
1704
1705 par->FbStart = info->screen_base;
1706
1707#ifdef CONFIG_MTRR
1708 if (!nomtrr) {
1709 par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001710 par->RamAmountKBytes * 1024,
1711 MTRR_TYPE_WRCOMB, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 if (par->mtrr.vram < 0) {
1713 printk(KERN_ERR PFX "unable to setup MTRR\n");
1714 } else {
1715 par->mtrr.vram_valid = 1;
1716 /* let there be speed */
1717 printk(KERN_INFO PFX "MTRR set to ON\n");
1718 }
1719 }
1720#endif /* CONFIG_MTRR */
1721
1722 info->fbops = &nvidia_fb_ops;
1723 info->fix = nvidiafb_fix;
1724
1725 if (nvidia_set_fbinfo(info) < 0) {
1726 printk(KERN_ERR PFX "error setting initial video mode\n");
1727 goto err_out_iounmap_fb;
1728 }
1729
1730 nvidia_save_vga(par, &par->SavedReg);
1731
1732 if (register_framebuffer(info) < 0) {
1733 printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
1734 goto err_out_iounmap_fb;
1735 }
1736
1737 pci_set_drvdata(pd, info);
1738
1739 printk(KERN_INFO PFX
1740 "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
1741 info->fix.id,
1742 par->FbMapSize / (1024 * 1024), info->fix.smem_start);
1743#ifdef CONFIG_PMAC_BACKLIGHT
1744 if (par->FlatPanel && _machine == _MACH_Pmac)
1745 register_backlight_controller(&nvidia_backlight_controller,
1746 par, "mnca");
1747#endif
1748 NVTRACE_LEAVE();
1749 return 0;
1750
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001751err_out_iounmap_fb:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 iounmap(info->screen_base);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001753err_out_free_base1:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 fb_destroy_modedb(info->monspecs.modedb);
1755 nvidia_delete_i2c_busses(par);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001756err_out_arch:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 iounmap(par->REGS);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001758err_out_free_base0:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 pci_release_regions(pd);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001760err_out_request:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 pci_disable_device(pd);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001762err_out_enable:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 kfree(info->pixmap.addr);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001764err_out_kfree:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 framebuffer_release(info);
Antonino A. Daplasc549dc62006-01-09 20:53:33 -08001766err_out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767 return -ENODEV;
1768}
1769
1770static void __exit nvidiafb_remove(struct pci_dev *pd)
1771{
1772 struct fb_info *info = pci_get_drvdata(pd);
1773 struct nvidia_par *par = info->par;
1774
1775 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
1777 unregister_framebuffer(info);
1778#ifdef CONFIG_MTRR
1779 if (par->mtrr.vram_valid)
1780 mtrr_del(par->mtrr.vram, info->fix.smem_start,
1781 info->fix.smem_len);
1782#endif /* CONFIG_MTRR */
1783
1784 iounmap(info->screen_base);
1785 fb_destroy_modedb(info->monspecs.modedb);
1786 nvidia_delete_i2c_busses(par);
1787 iounmap(par->REGS);
1788 pci_release_regions(pd);
1789 pci_disable_device(pd);
1790 kfree(info->pixmap.addr);
1791 framebuffer_release(info);
1792 pci_set_drvdata(pd, NULL);
1793 NVTRACE_LEAVE();
1794}
1795
1796/* ------------------------------------------------------------------------- *
1797 *
1798 * initialization
1799 *
1800 * ------------------------------------------------------------------------- */
1801
1802#ifndef MODULE
1803static int __devinit nvidiafb_setup(char *options)
1804{
1805 char *this_opt;
1806
1807 NVTRACE_ENTER();
1808 if (!options || !*options)
1809 return 0;
1810
1811 while ((this_opt = strsep(&options, ",")) != NULL) {
1812 if (!strncmp(this_opt, "forceCRTC", 9)) {
1813 char *p;
1814
1815 p = this_opt + 9;
1816 if (!*p || !*(++p))
1817 continue;
1818 forceCRTC = *p - '0';
1819 if (forceCRTC < 0 || forceCRTC > 1)
1820 forceCRTC = -1;
1821 } else if (!strncmp(this_opt, "flatpanel", 9)) {
1822 flatpanel = 1;
1823 } else if (!strncmp(this_opt, "hwcur", 5)) {
1824 hwcur = 1;
1825 } else if (!strncmp(this_opt, "noaccel", 6)) {
1826 noaccel = 1;
1827 } else if (!strncmp(this_opt, "noscale", 7)) {
1828 noscale = 1;
1829 } else if (!strncmp(this_opt, "paneltweak:", 11)) {
1830 paneltweak = simple_strtoul(this_opt+11, NULL, 0);
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001831 } else if (!strncmp(this_opt, "vram:", 5)) {
1832 vram = simple_strtoul(this_opt+5, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833#ifdef CONFIG_MTRR
1834 } else if (!strncmp(this_opt, "nomtrr", 6)) {
1835 nomtrr = 1;
1836#endif
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001837 } else if (!strncmp(this_opt, "fpdither:", 9)) {
1838 fpdither = simple_strtol(this_opt+9, NULL, 0);
Antonino A. Daplasade91852006-01-09 20:53:39 -08001839 } else if (!strncmp(this_opt, "bpp:", 4)) {
1840 bpp = simple_strtoul(this_opt+4, NULL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 } else
1842 mode_option = this_opt;
1843 }
1844 NVTRACE_LEAVE();
1845 return 0;
1846}
1847#endif /* !MODULE */
1848
1849static struct pci_driver nvidiafb_driver = {
1850 .name = "nvidiafb",
1851 .id_table = nvidiafb_pci_tbl,
Antonino A. Daplas7a07cd72006-03-27 01:17:22 -08001852 .probe = nvidiafb_probe,
1853 .suspend = nvidiafb_suspend,
1854 .resume = nvidiafb_resume,
1855 .remove = __exit_p(nvidiafb_remove),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856};
1857
1858/* ------------------------------------------------------------------------- *
1859 *
1860 * modularization
1861 *
1862 * ------------------------------------------------------------------------- */
1863
1864static int __devinit nvidiafb_init(void)
1865{
1866#ifndef MODULE
1867 char *option = NULL;
1868
1869 if (fb_get_options("nvidiafb", &option))
1870 return -ENODEV;
1871 nvidiafb_setup(option);
1872#endif
1873 return pci_register_driver(&nvidiafb_driver);
1874}
1875
1876module_init(nvidiafb_init);
1877
1878#ifdef MODULE
1879static void __exit nvidiafb_exit(void)
1880{
1881 pci_unregister_driver(&nvidiafb_driver);
1882}
1883
1884module_exit(nvidiafb_exit);
1885
1886module_param(flatpanel, int, 0);
1887MODULE_PARM_DESC(flatpanel,
1888 "Enables experimental flat panel support for some chipsets. "
Benjamin Herrenschmidtb8c49ef2005-11-07 01:00:32 -08001889 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
1890module_param(fpdither, int, 0);
1891MODULE_PARM_DESC(fpdither,
1892 "Enables dithering of flat panel for 6 bits panels. "
1893 "(0=disabled, 1=enabled, -1=autodetect) (default=-1)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894module_param(hwcur, int, 0);
1895MODULE_PARM_DESC(hwcur,
1896 "Enables hardware cursor implementation. (0 or 1=enabled) "
1897 "(default=0)");
1898module_param(noaccel, int, 0);
1899MODULE_PARM_DESC(noaccel,
1900 "Disables hardware acceleration. (0 or 1=disable) "
1901 "(default=0)");
1902module_param(noscale, int, 0);
1903MODULE_PARM_DESC(noscale,
1904 "Disables screen scaleing. (0 or 1=disable) "
1905 "(default=0, do scaling)");
1906module_param(paneltweak, int, 0);
1907MODULE_PARM_DESC(paneltweak,
1908 "Tweak display settings for flatpanels. "
1909 "(default=0, no tweaks)");
1910module_param(forceCRTC, int, 0);
1911MODULE_PARM_DESC(forceCRTC,
1912 "Forces usage of a particular CRTC in case autodetection "
1913 "fails. (0 or 1) (default=autodetect)");
Antonino A. Daplas917bb072005-05-01 08:59:22 -07001914module_param(vram, int, 0);
1915MODULE_PARM_DESC(vram,
1916 "amount of framebuffer memory to remap in MiB"
1917 "(default=0 - remap entire memory)");
Antonino A. Daplasc439e342006-01-09 20:53:02 -08001918module_param(mode_option, charp, 0);
1919MODULE_PARM_DESC(mode_option, "Specify initial video mode");
Antonino A. Daplasade91852006-01-09 20:53:39 -08001920module_param(bpp, int, 0);
1921MODULE_PARM_DESC(bpp, "pixel width in bits"
1922 "(default=8)");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001923#ifdef CONFIG_MTRR
1924module_param(nomtrr, bool, 0);
1925MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
1926 "(default=0)");
1927#endif
1928
1929MODULE_AUTHOR("Antonino Daplas");
1930MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
1931MODULE_LICENSE("GPL");
1932#endif /* MODULE */
1933