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