blob: d4384ab1df653c2ff57bd4942712bdbf19129299 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
3 *
4 * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
5 *
6 * Copyright 1999-2000 Jeff Garzik
7 *
8 * Contributors:
9 *
10 * Ani Joshi: Lots of debugging and cleanup work, really helped
11 * get the driver going
12 *
13 * Ferenc Bakonyi: Bug fixes, cleanup, modularization
14 *
15 * Jindrich Makovicka: Accel code help, hw cursor, mtrr
16 *
17 * Paul Richards: Bug fixes, updates
18 *
19 * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
20 * Includes riva_hw.c from nVidia, see copyright below.
21 * KGI code provided the basis for state storage, init, and mode switching.
22 *
23 * This file is subject to the terms and conditions of the GNU General Public
24 * License. See the file COPYING in the main directory of this archive
25 * for more details.
26 *
27 * Known bugs and issues:
28 * restoring text mode fails
29 * doublescan modes are broken
30 */
31
32#include <linux/config.h>
33#include <linux/module.h>
34#include <linux/kernel.h>
35#include <linux/errno.h>
36#include <linux/string.h>
37#include <linux/mm.h>
38#include <linux/tty.h>
39#include <linux/slab.h>
40#include <linux/delay.h>
41#include <linux/fb.h>
42#include <linux/init.h>
43#include <linux/pci.h>
Michael Hanselmann5474c122006-06-25 05:47:08 -070044#include <linux/backlight.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#ifdef CONFIG_MTRR
46#include <asm/mtrr.h>
47#endif
48#ifdef CONFIG_PPC_OF
49#include <asm/prom.h>
50#include <asm/pci-bridge.h>
51#endif
52#ifdef CONFIG_PMAC_BACKLIGHT
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +110053#include <asm/machdep.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070054#include <asm/backlight.h>
55#endif
56
57#include "rivafb.h"
58#include "nvreg.h"
59
60#ifndef CONFIG_PCI /* sanity check */
61#error This driver requires PCI support.
62#endif
63
64/* version number of this driver */
65#define RIVAFB_VERSION "0.9.5b"
66
67/* ------------------------------------------------------------------------- *
68 *
69 * various helpful macros and constants
70 *
71 * ------------------------------------------------------------------------- */
72#ifdef CONFIG_FB_RIVA_DEBUG
73#define NVTRACE printk
74#else
75#define NVTRACE if(0) printk
76#endif
77
78#define NVTRACE_ENTER(...) NVTRACE("%s START\n", __FUNCTION__)
79#define NVTRACE_LEAVE(...) NVTRACE("%s END\n", __FUNCTION__)
80
81#ifdef CONFIG_FB_RIVA_DEBUG
82#define assert(expr) \
83 if(!(expr)) { \
84 printk( "Assertion failed! %s,%s,%s,line=%d\n",\
85 #expr,__FILE__,__FUNCTION__,__LINE__); \
86 BUG(); \
87 }
88#else
89#define assert(expr)
90#endif
91
92#define PFX "rivafb: "
93
94/* macro that allows you to set overflow bits */
95#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
96#define SetBit(n) (1<<(n))
97#define Set8Bits(value) ((value)&0xff)
98
99/* HW cursor parameters */
100#define MAX_CURS 32
101
102/* ------------------------------------------------------------------------- *
103 *
104 * prototypes
105 *
106 * ------------------------------------------------------------------------- */
107
108static int rivafb_blank(int blank, struct fb_info *info);
109
110/* ------------------------------------------------------------------------- *
111 *
112 * card identification
113 *
114 * ------------------------------------------------------------------------- */
115
116static struct pci_device_id rivafb_pci_tbl[] = {
117 { PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
118 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
119 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
120 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
121 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
122 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
123 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
124 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
125 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
126 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
127 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
128 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
129 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
130 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
131 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
132 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
133 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
134 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
135 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
136 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
137 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
138 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
139 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
140 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
141 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
142 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
143 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
144 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
145 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
146 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
147 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
148 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
149 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
150 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
151 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
152 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
153 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
154 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
155 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
156 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
157 // NF2/IGP version, GeForce 4 MX, NV18
158 { PCI_VENDOR_ID_NVIDIA, 0x01f0,
159 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
160 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
161 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
162 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
163 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
164 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
165 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
166 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
167 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
168 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
169 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
170 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
171 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
172 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
173 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
174 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
175 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
176 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
177 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
178 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
179 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
180 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
181 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
182 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
183 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
184 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
185 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
186 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
187 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
188 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
189 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
190 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
191 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
192 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
193 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
194 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
195 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
196 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
197 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
198 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
199 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
200 { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
201 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
202 { 0, } /* terminate list */
203};
204MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
205
206/* ------------------------------------------------------------------------- *
207 *
208 * global variables
209 *
210 * ------------------------------------------------------------------------- */
211
212/* command line data, set in rivafb_setup() */
213static int flatpanel __devinitdata = -1; /* Autodetect later */
214static int forceCRTC __devinitdata = -1;
215static int noaccel __devinitdata = 0;
216#ifdef CONFIG_MTRR
217static int nomtrr __devinitdata = 0;
218#endif
219
220static char *mode_option __devinitdata = NULL;
221static int strictmode = 0;
222
223static struct fb_fix_screeninfo __devinitdata rivafb_fix = {
224 .type = FB_TYPE_PACKED_PIXELS,
225 .xpanstep = 1,
226 .ypanstep = 1,
227};
228
229static struct fb_var_screeninfo __devinitdata rivafb_default_var = {
230 .xres = 640,
231 .yres = 480,
232 .xres_virtual = 640,
233 .yres_virtual = 480,
234 .bits_per_pixel = 8,
235 .red = {0, 8, 0},
236 .green = {0, 8, 0},
237 .blue = {0, 8, 0},
238 .transp = {0, 0, 0},
239 .activate = FB_ACTIVATE_NOW,
240 .height = -1,
241 .width = -1,
242 .pixclock = 39721,
243 .left_margin = 40,
244 .right_margin = 24,
245 .upper_margin = 32,
246 .lower_margin = 11,
247 .hsync_len = 96,
248 .vsync_len = 2,
249 .vmode = FB_VMODE_NONINTERLACED
250};
251
252/* from GGI */
253static const struct riva_regs reg_template = {
254 {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
255 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
256 0x41, 0x01, 0x0F, 0x00, 0x00},
257 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */
258 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */
260 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
262 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */
264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, /* 0x40 */
266 },
267 {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
268 0xFF},
269 {0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
270 0xEB /* MISC */
271};
272
273/*
274 * Backlight control
275 */
Michael Hanselmann5474c122006-06-25 05:47:08 -0700276#ifdef CONFIG_FB_RIVA_BACKLIGHT
277/* We do not have any information about which values are allowed, thus
278 * we used safe values.
279 */
280#define MIN_LEVEL 0x158
281#define MAX_LEVEL 0x534
282
283static struct backlight_properties riva_bl_data;
284
285static int riva_bl_get_level_brightness(struct riva_par *par,
286 int level)
287{
288 struct fb_info *info = pci_get_drvdata(par->pdev);
289 int nlevel;
290
291 /* Get and convert the value */
292 mutex_lock(&info->bl_mutex);
293 nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
294 mutex_unlock(&info->bl_mutex);
295
296 if (nlevel < 0)
297 nlevel = 0;
298 else if (nlevel < MIN_LEVEL)
299 nlevel = MIN_LEVEL;
300 else if (nlevel > MAX_LEVEL)
301 nlevel = MAX_LEVEL;
302
303 return nlevel;
304}
305
306static int riva_bl_update_status(struct backlight_device *bd)
307{
308 struct riva_par *par = class_get_devdata(&bd->class_dev);
309 U032 tmp_pcrt, tmp_pmc;
310 int level;
311
312 if (bd->props->power != FB_BLANK_UNBLANK ||
313 bd->props->fb_blank != FB_BLANK_UNBLANK)
314 level = 0;
315 else
316 level = bd->props->brightness;
317
318 tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
319 tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
320 if(level > 0) {
321 tmp_pcrt |= 0x1;
322 tmp_pmc |= (1 << 31); /* backlight bit */
323 tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
324 }
325 par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
326 par->riva.PMC[0x10F0/4] = tmp_pmc;
327
328 return 0;
329}
330
331static int riva_bl_get_brightness(struct backlight_device *bd)
332{
333 return bd->props->brightness;
334}
335
336static struct backlight_properties riva_bl_data = {
337 .owner = THIS_MODULE,
338 .get_brightness = riva_bl_get_brightness,
339 .update_status = riva_bl_update_status,
340 .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
341};
342
343static void riva_bl_init(struct riva_par *par)
344{
345 struct fb_info *info = pci_get_drvdata(par->pdev);
346 struct backlight_device *bd;
347 char name[12];
348
349 if (!par->FlatPanel)
350 return;
351
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352#ifdef CONFIG_PMAC_BACKLIGHT
Michael Hanselmann5474c122006-06-25 05:47:08 -0700353 if (!machine_is(powermac) ||
354 !pmac_has_backlight_type("mnca"))
355 return;
356#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Michael Hanselmann5474c122006-06-25 05:47:08 -0700358 snprintf(name, sizeof(name), "rivabl%d", info->node);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Michael Hanselmann5474c122006-06-25 05:47:08 -0700360 bd = backlight_device_register(name, par, &riva_bl_data);
361 if (IS_ERR(bd)) {
362 info->bl_dev = NULL;
363 printk("riva: Backlight registration failed\n");
364 goto error;
365 }
366
367 mutex_lock(&info->bl_mutex);
368 info->bl_dev = bd;
369 fb_bl_default_curve(info, 0,
370 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
371 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
372 mutex_unlock(&info->bl_mutex);
373
374 up(&bd->sem);
375 bd->props->brightness = riva_bl_data.max_brightness;
376 bd->props->power = FB_BLANK_UNBLANK;
377 bd->props->update_status(bd);
378 down(&bd->sem);
379
380#ifdef CONFIG_PMAC_BACKLIGHT
381 mutex_lock(&pmac_backlight_mutex);
382 if (!pmac_backlight)
383 pmac_backlight = bd;
384 mutex_unlock(&pmac_backlight_mutex);
385#endif
386
387 printk("riva: Backlight initialized (%s)\n", name);
388
389 return;
390
391error:
392 return;
393}
394
395static void riva_bl_exit(struct riva_par *par)
396{
397 struct fb_info *info = pci_get_drvdata(par->pdev);
398
399#ifdef CONFIG_PMAC_BACKLIGHT
400 mutex_lock(&pmac_backlight_mutex);
401#endif
402
403 mutex_lock(&info->bl_mutex);
404 if (info->bl_dev) {
405#ifdef CONFIG_PMAC_BACKLIGHT
406 if (pmac_backlight == info->bl_dev)
407 pmac_backlight = NULL;
408#endif
409
410 backlight_device_unregister(info->bl_dev);
411
412 printk("riva: Backlight unloaded\n");
413 }
414 mutex_unlock(&info->bl_mutex);
415
416#ifdef CONFIG_PMAC_BACKLIGHT
417 mutex_unlock(&pmac_backlight_mutex);
418#endif
419}
420#else
421static inline void riva_bl_init(struct riva_par *par) {}
422static inline void riva_bl_exit(struct riva_par *par) {}
423#endif /* CONFIG_FB_RIVA_BACKLIGHT */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
425/* ------------------------------------------------------------------------- *
426 *
427 * MMIO access macros
428 *
429 * ------------------------------------------------------------------------- */
430
431static inline void CRTCout(struct riva_par *par, unsigned char index,
432 unsigned char val)
433{
434 VGA_WR08(par->riva.PCIO, 0x3d4, index);
435 VGA_WR08(par->riva.PCIO, 0x3d5, val);
436}
437
438static inline unsigned char CRTCin(struct riva_par *par,
439 unsigned char index)
440{
441 VGA_WR08(par->riva.PCIO, 0x3d4, index);
442 return (VGA_RD08(par->riva.PCIO, 0x3d5));
443}
444
445static inline void GRAout(struct riva_par *par, unsigned char index,
446 unsigned char val)
447{
448 VGA_WR08(par->riva.PVIO, 0x3ce, index);
449 VGA_WR08(par->riva.PVIO, 0x3cf, val);
450}
451
452static inline unsigned char GRAin(struct riva_par *par,
453 unsigned char index)
454{
455 VGA_WR08(par->riva.PVIO, 0x3ce, index);
456 return (VGA_RD08(par->riva.PVIO, 0x3cf));
457}
458
459static inline void SEQout(struct riva_par *par, unsigned char index,
460 unsigned char val)
461{
462 VGA_WR08(par->riva.PVIO, 0x3c4, index);
463 VGA_WR08(par->riva.PVIO, 0x3c5, val);
464}
465
466static inline unsigned char SEQin(struct riva_par *par,
467 unsigned char index)
468{
469 VGA_WR08(par->riva.PVIO, 0x3c4, index);
470 return (VGA_RD08(par->riva.PVIO, 0x3c5));
471}
472
473static inline void ATTRout(struct riva_par *par, unsigned char index,
474 unsigned char val)
475{
476 VGA_WR08(par->riva.PCIO, 0x3c0, index);
477 VGA_WR08(par->riva.PCIO, 0x3c0, val);
478}
479
480static inline unsigned char ATTRin(struct riva_par *par,
481 unsigned char index)
482{
483 VGA_WR08(par->riva.PCIO, 0x3c0, index);
484 return (VGA_RD08(par->riva.PCIO, 0x3c1));
485}
486
487static inline void MISCout(struct riva_par *par, unsigned char val)
488{
489 VGA_WR08(par->riva.PVIO, 0x3c2, val);
490}
491
492static inline unsigned char MISCin(struct riva_par *par)
493{
494 return (VGA_RD08(par->riva.PVIO, 0x3cc));
495}
496
497static u8 byte_rev[256] = {
498 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
499 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
500 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
501 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
502 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
503 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
504 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
505 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
506 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
507 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
508 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
509 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
510 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
511 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
512 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
513 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
514 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
515 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
516 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
517 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
518 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
519 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
520 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
521 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
522 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
523 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
524 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
525 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
526 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
527 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
528 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
529 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
530};
531
532static inline void reverse_order(u32 *l)
533{
534 u8 *a = (u8 *)l;
535 *a = byte_rev[*a], a++;
536 *a = byte_rev[*a], a++;
537 *a = byte_rev[*a], a++;
538 *a = byte_rev[*a];
539}
540
541/* ------------------------------------------------------------------------- *
542 *
543 * cursor stuff
544 *
545 * ------------------------------------------------------------------------- */
546
547/**
548 * rivafb_load_cursor_image - load cursor image to hardware
549 * @data: address to monochrome bitmap (1 = foreground color, 0 = background)
550 * @par: pointer to private data
551 * @w: width of cursor image in pixels
552 * @h: height of cursor image in scanlines
553 * @bg: background color (ARGB1555) - alpha bit determines opacity
554 * @fg: foreground color (ARGB1555)
555 *
556 * DESCRIPTiON:
557 * Loads cursor image based on a monochrome source and mask bitmap. The
558 * image bits determines the color of the pixel, 0 for background, 1 for
559 * foreground. Only the affected region (as determined by @w and @h
560 * parameters) will be updated.
561 *
562 * CALLED FROM:
563 * rivafb_cursor()
564 */
565static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
566 u16 bg, u16 fg, u32 w, u32 h)
567{
568 int i, j, k = 0;
569 u32 b, tmp;
570 u32 *data = (u32 *)data8;
571 bg = le16_to_cpu(bg);
572 fg = le16_to_cpu(fg);
573
574 w = (w + 1) & ~1;
575
576 for (i = 0; i < h; i++) {
577 b = *data++;
578 reverse_order(&b);
579
580 for (j = 0; j < w/2; j++) {
581 tmp = 0;
582#if defined (__BIG_ENDIAN)
583 tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
584 b <<= 1;
585 tmp |= (b & (1 << 31)) ? fg : bg;
586 b <<= 1;
587#else
588 tmp = (b & 1) ? fg : bg;
589 b >>= 1;
590 tmp |= (b & 1) ? fg << 16 : bg << 16;
591 b >>= 1;
592#endif
593 writel(tmp, &par->riva.CURSOR[k++]);
594 }
595 k += (MAX_CURS - w)/2;
596 }
597}
598
599/* ------------------------------------------------------------------------- *
600 *
601 * general utility functions
602 *
603 * ------------------------------------------------------------------------- */
604
605/**
606 * riva_wclut - set CLUT entry
607 * @chip: pointer to RIVA_HW_INST object
608 * @regnum: register number
609 * @red: red component
610 * @green: green component
611 * @blue: blue component
612 *
613 * DESCRIPTION:
614 * Sets color register @regnum.
615 *
616 * CALLED FROM:
617 * rivafb_setcolreg()
618 */
619static void riva_wclut(RIVA_HW_INST *chip,
620 unsigned char regnum, unsigned char red,
621 unsigned char green, unsigned char blue)
622{
623 VGA_WR08(chip->PDIO, 0x3c8, regnum);
624 VGA_WR08(chip->PDIO, 0x3c9, red);
625 VGA_WR08(chip->PDIO, 0x3c9, green);
626 VGA_WR08(chip->PDIO, 0x3c9, blue);
627}
628
629/**
630 * riva_rclut - read fromCLUT register
631 * @chip: pointer to RIVA_HW_INST object
632 * @regnum: register number
633 * @red: red component
634 * @green: green component
635 * @blue: blue component
636 *
637 * DESCRIPTION:
638 * Reads red, green, and blue from color register @regnum.
639 *
640 * CALLED FROM:
641 * rivafb_setcolreg()
642 */
643static void riva_rclut(RIVA_HW_INST *chip,
644 unsigned char regnum, unsigned char *red,
645 unsigned char *green, unsigned char *blue)
646{
647
648 VGA_WR08(chip->PDIO, 0x3c7, regnum);
649 *red = VGA_RD08(chip->PDIO, 0x3c9);
650 *green = VGA_RD08(chip->PDIO, 0x3c9);
651 *blue = VGA_RD08(chip->PDIO, 0x3c9);
652}
653
654/**
655 * riva_save_state - saves current chip state
656 * @par: pointer to riva_par object containing info for current riva board
657 * @regs: pointer to riva_regs object
658 *
659 * DESCRIPTION:
660 * Saves current chip state to @regs.
661 *
662 * CALLED FROM:
663 * rivafb_probe()
664 */
665/* from GGI */
666static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
667{
668 int i;
669
670 NVTRACE_ENTER();
671 par->riva.LockUnlock(&par->riva, 0);
672
673 par->riva.UnloadStateExt(&par->riva, &regs->ext);
674
675 regs->misc_output = MISCin(par);
676
677 for (i = 0; i < NUM_CRT_REGS; i++)
678 regs->crtc[i] = CRTCin(par, i);
679
680 for (i = 0; i < NUM_ATC_REGS; i++)
681 regs->attr[i] = ATTRin(par, i);
682
683 for (i = 0; i < NUM_GRC_REGS; i++)
684 regs->gra[i] = GRAin(par, i);
685
686 for (i = 0; i < NUM_SEQ_REGS; i++)
687 regs->seq[i] = SEQin(par, i);
688 NVTRACE_LEAVE();
689}
690
691/**
692 * riva_load_state - loads current chip state
693 * @par: pointer to riva_par object containing info for current riva board
694 * @regs: pointer to riva_regs object
695 *
696 * DESCRIPTION:
697 * Loads chip state from @regs.
698 *
699 * CALLED FROM:
700 * riva_load_video_mode()
701 * rivafb_probe()
702 * rivafb_remove()
703 */
704/* from GGI */
705static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
706{
707 RIVA_HW_STATE *state = &regs->ext;
708 int i;
709
710 NVTRACE_ENTER();
711 CRTCout(par, 0x11, 0x00);
712
713 par->riva.LockUnlock(&par->riva, 0);
714
715 par->riva.LoadStateExt(&par->riva, state);
716
717 MISCout(par, regs->misc_output);
718
719 for (i = 0; i < NUM_CRT_REGS; i++) {
720 switch (i) {
721 case 0x19:
722 case 0x20 ... 0x40:
723 break;
724 default:
725 CRTCout(par, i, regs->crtc[i]);
726 }
727 }
728
729 for (i = 0; i < NUM_ATC_REGS; i++)
730 ATTRout(par, i, regs->attr[i]);
731
732 for (i = 0; i < NUM_GRC_REGS; i++)
733 GRAout(par, i, regs->gra[i]);
734
735 for (i = 0; i < NUM_SEQ_REGS; i++)
736 SEQout(par, i, regs->seq[i]);
737 NVTRACE_LEAVE();
738}
739
740/**
741 * riva_load_video_mode - calculate timings
742 * @info: pointer to fb_info object containing info for current riva board
743 *
744 * DESCRIPTION:
745 * Calculate some timings and then send em off to riva_load_state().
746 *
747 * CALLED FROM:
748 * rivafb_set_par()
749 */
750static void riva_load_video_mode(struct fb_info *info)
751{
752 int bpp, width, hDisplaySize, hDisplay, hStart,
753 hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
754 int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
Antonino A. Daplasf4a41832006-01-09 20:53:04 -0800755 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 struct riva_regs newmode;
757
758 NVTRACE_ENTER();
759 /* time to calculate */
760 rivafb_blank(1, info);
761
762 bpp = info->var.bits_per_pixel;
763 if (bpp == 16 && info->var.green.length == 5)
764 bpp = 15;
765 width = info->var.xres_virtual;
766 hDisplaySize = info->var.xres;
767 hDisplay = (hDisplaySize / 8) - 1;
768 hStart = (hDisplaySize + info->var.right_margin) / 8 - 1;
769 hEnd = (hDisplaySize + info->var.right_margin +
770 info->var.hsync_len) / 8 - 1;
771 hTotal = (hDisplaySize + info->var.right_margin +
772 info->var.hsync_len + info->var.left_margin) / 8 - 5;
773 hBlankStart = hDisplay;
774 hBlankEnd = hTotal + 4;
775
776 height = info->var.yres_virtual;
777 vDisplay = info->var.yres - 1;
778 vStart = info->var.yres + info->var.lower_margin - 1;
779 vEnd = info->var.yres + info->var.lower_margin +
780 info->var.vsync_len - 1;
781 vTotal = info->var.yres + info->var.lower_margin +
782 info->var.vsync_len + info->var.upper_margin + 2;
783 vBlankStart = vDisplay;
784 vBlankEnd = vTotal + 1;
785 dotClock = 1000000000 / info->var.pixclock;
786
787 memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
788
789 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
790 vTotal |= 1;
791
792 if (par->FlatPanel) {
793 vStart = vTotal - 3;
794 vEnd = vTotal - 2;
795 vBlankStart = vStart;
796 hStart = hTotal - 3;
797 hEnd = hTotal - 2;
798 hBlankEnd = hTotal + 4;
799 }
800
801 newmode.crtc[0x0] = Set8Bits (hTotal);
802 newmode.crtc[0x1] = Set8Bits (hDisplay);
803 newmode.crtc[0x2] = Set8Bits (hBlankStart);
804 newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
805 newmode.crtc[0x4] = Set8Bits (hStart);
806 newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
807 | SetBitField (hEnd, 4: 0, 4:0);
808 newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
809 newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
810 | SetBitField (vDisplay, 8: 8, 1:1)
811 | SetBitField (vStart, 8: 8, 2:2)
812 | SetBitField (vBlankStart, 8: 8, 3:3)
813 | SetBit (4)
814 | SetBitField (vTotal, 9: 9, 5:5)
815 | SetBitField (vDisplay, 9: 9, 6:6)
816 | SetBitField (vStart, 9: 9, 7:7);
817 newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
818 | SetBit (6);
819 newmode.crtc[0x10] = Set8Bits (vStart);
820 newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
821 | SetBit (5);
822 newmode.crtc[0x12] = Set8Bits (vDisplay);
823 newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
824 newmode.crtc[0x15] = Set8Bits (vBlankStart);
825 newmode.crtc[0x16] = Set8Bits (vBlankEnd);
826
827 newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
828 | SetBitField(vBlankStart,10:10,3:3)
829 | SetBitField(vStart,10:10,2:2)
830 | SetBitField(vDisplay,10:10,1:1)
831 | SetBitField(vTotal,10:10,0:0);
832 newmode.ext.horiz = SetBitField(hTotal,8:8,0:0)
833 | SetBitField(hDisplay,8:8,1:1)
834 | SetBitField(hBlankStart,8:8,2:2)
835 | SetBitField(hStart,8:8,3:3);
836 newmode.ext.extra = SetBitField(vTotal,11:11,0:0)
837 | SetBitField(vDisplay,11:11,2:2)
838 | SetBitField(vStart,11:11,4:4)
839 | SetBitField(vBlankStart,11:11,6:6);
840
841 if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
842 int tmp = (hTotal >> 1) & ~1;
843 newmode.ext.interlace = Set8Bits(tmp);
844 newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4);
845 } else
846 newmode.ext.interlace = 0xff; /* interlace off */
847
848 if (par->riva.Architecture >= NV_ARCH_10)
849 par->riva.CURSOR = (U032 __iomem *)(info->screen_base + par->riva.CursorStart);
850
851 if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
852 newmode.misc_output &= ~0x40;
853 else
854 newmode.misc_output |= 0x40;
855 if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
856 newmode.misc_output &= ~0x80;
857 else
858 newmode.misc_output |= 0x80;
859
860 par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
861 hDisplaySize, height, dotClock);
862
863 newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) &
864 0xfff000ff;
865 if (par->FlatPanel == 1) {
866 newmode.ext.pixel |= (1 << 7);
867 newmode.ext.scale |= (1 << 8);
868 }
869 if (par->SecondCRTC) {
870 newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) &
871 ~0x00001000;
872 newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) |
873 0x00001000;
874 newmode.ext.crtcOwner = 3;
875 newmode.ext.pllsel |= 0x20000800;
876 newmode.ext.vpll2 = newmode.ext.vpll;
877 } else if (par->riva.twoHeads) {
878 newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) |
879 0x00001000;
880 newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) &
881 ~0x00001000;
882 newmode.ext.crtcOwner = 0;
883 newmode.ext.vpll2 = NV_RD32(par->riva.PRAMDAC0, 0x00000520);
884 }
885 if (par->FlatPanel == 1) {
886 newmode.ext.pixel |= (1 << 7);
887 newmode.ext.scale |= (1 << 8);
888 }
889 newmode.ext.cursorConfig = 0x02000100;
890 par->current_state = newmode;
891 riva_load_state(par, &par->current_state);
892 par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
893 rivafb_blank(0, info);
894 NVTRACE_LEAVE();
895}
896
897static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
898{
899 NVTRACE_ENTER();
900 var->xres = var->xres_virtual = modedb->xres;
901 var->yres = modedb->yres;
902 if (var->yres_virtual < var->yres)
903 var->yres_virtual = var->yres;
904 var->xoffset = var->yoffset = 0;
905 var->pixclock = modedb->pixclock;
906 var->left_margin = modedb->left_margin;
907 var->right_margin = modedb->right_margin;
908 var->upper_margin = modedb->upper_margin;
909 var->lower_margin = modedb->lower_margin;
910 var->hsync_len = modedb->hsync_len;
911 var->vsync_len = modedb->vsync_len;
912 var->sync = modedb->sync;
913 var->vmode = modedb->vmode;
914 NVTRACE_LEAVE();
915}
916
917/**
918 * rivafb_do_maximize -
919 * @info: pointer to fb_info object containing info for current riva board
920 * @var:
921 * @nom:
922 * @den:
923 *
924 * DESCRIPTION:
925 * .
926 *
927 * RETURNS:
928 * -EINVAL on failure, 0 on success
929 *
930 *
931 * CALLED FROM:
932 * rivafb_check_var()
933 */
934static int rivafb_do_maximize(struct fb_info *info,
935 struct fb_var_screeninfo *var,
936 int nom, int den)
937{
938 static struct {
939 int xres, yres;
940 } modes[] = {
941 {1600, 1280},
942 {1280, 1024},
943 {1024, 768},
944 {800, 600},
945 {640, 480},
946 {-1, -1}
947 };
948 int i;
949
950 NVTRACE_ENTER();
951 /* use highest possible virtual resolution */
952 if (var->xres_virtual == -1 && var->yres_virtual == -1) {
953 printk(KERN_WARNING PFX
954 "using maximum available virtual resolution\n");
955 for (i = 0; modes[i].xres != -1; i++) {
956 if (modes[i].xres * nom / den * modes[i].yres <
957 info->fix.smem_len)
958 break;
959 }
960 if (modes[i].xres == -1) {
961 printk(KERN_ERR PFX
962 "could not find a virtual resolution that fits into video memory!!\n");
963 NVTRACE("EXIT - EINVAL error\n");
964 return -EINVAL;
965 }
966 var->xres_virtual = modes[i].xres;
967 var->yres_virtual = modes[i].yres;
968
969 printk(KERN_INFO PFX
970 "virtual resolution set to maximum of %dx%d\n",
971 var->xres_virtual, var->yres_virtual);
972 } else if (var->xres_virtual == -1) {
973 var->xres_virtual = (info->fix.smem_len * den /
974 (nom * var->yres_virtual)) & ~15;
975 printk(KERN_WARNING PFX
976 "setting virtual X resolution to %d\n", var->xres_virtual);
977 } else if (var->yres_virtual == -1) {
978 var->xres_virtual = (var->xres_virtual + 15) & ~15;
979 var->yres_virtual = info->fix.smem_len * den /
980 (nom * var->xres_virtual);
981 printk(KERN_WARNING PFX
982 "setting virtual Y resolution to %d\n", var->yres_virtual);
983 } else {
984 var->xres_virtual = (var->xres_virtual + 15) & ~15;
985 if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
986 printk(KERN_ERR PFX
987 "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
988 var->xres, var->yres, var->bits_per_pixel);
989 NVTRACE("EXIT - EINVAL error\n");
990 return -EINVAL;
991 }
992 }
993
994 if (var->xres_virtual * nom / den >= 8192) {
995 printk(KERN_WARNING PFX
996 "virtual X resolution (%d) is too high, lowering to %d\n",
997 var->xres_virtual, 8192 * den / nom - 16);
998 var->xres_virtual = 8192 * den / nom - 16;
999 }
1000
1001 if (var->xres_virtual < var->xres) {
1002 printk(KERN_ERR PFX
1003 "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
1004 return -EINVAL;
1005 }
1006
1007 if (var->yres_virtual < var->yres) {
1008 printk(KERN_ERR PFX
1009 "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
1010 return -EINVAL;
1011 }
1012 if (var->yres_virtual > 0x7fff/nom)
1013 var->yres_virtual = 0x7fff/nom;
1014 if (var->xres_virtual > 0x7fff/nom)
1015 var->xres_virtual = 0x7fff/nom;
1016 NVTRACE_LEAVE();
1017 return 0;
1018}
1019
1020static void
1021riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
1022{
1023 RIVA_FIFO_FREE(par->riva, Patt, 4);
1024 NV_WR32(&par->riva.Patt->Color0, 0, clr0);
1025 NV_WR32(&par->riva.Patt->Color1, 0, clr1);
1026 NV_WR32(par->riva.Patt->Monochrome, 0, pat0);
1027 NV_WR32(par->riva.Patt->Monochrome, 4, pat1);
1028}
1029
1030/* acceleration routines */
1031static inline void wait_for_idle(struct riva_par *par)
1032{
1033 while (par->riva.Busy(&par->riva));
1034}
1035
1036/*
1037 * Set ROP. Translate X rop into ROP3. Internal routine.
1038 */
1039static void
1040riva_set_rop_solid(struct riva_par *par, int rop)
1041{
1042 riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
1043 RIVA_FIFO_FREE(par->riva, Rop, 1);
1044 NV_WR32(&par->riva.Rop->Rop3, 0, rop);
1045
1046}
1047
1048static void riva_setup_accel(struct fb_info *info)
1049{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001050 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
1052 RIVA_FIFO_FREE(par->riva, Clip, 2);
1053 NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0);
1054 NV_WR32(&par->riva.Clip->WidthHeight, 0,
1055 (info->var.xres_virtual & 0xffff) |
1056 (info->var.yres_virtual << 16));
1057 riva_set_rop_solid(par, 0xcc);
1058 wait_for_idle(par);
1059}
1060
1061/**
1062 * riva_get_cmap_len - query current color map length
1063 * @var: standard kernel fb changeable data
1064 *
1065 * DESCRIPTION:
1066 * Get current color map length.
1067 *
1068 * RETURNS:
1069 * Length of color map
1070 *
1071 * CALLED FROM:
1072 * rivafb_setcolreg()
1073 */
1074static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
1075{
1076 int rc = 256; /* reasonable default */
1077
1078 switch (var->green.length) {
1079 case 8:
1080 rc = 256; /* 256 entries (2^8), 8 bpp and RGB8888 */
1081 break;
1082 case 5:
1083 rc = 32; /* 32 entries (2^5), 16 bpp, RGB555 */
1084 break;
1085 case 6:
1086 rc = 64; /* 64 entries (2^6), 16 bpp, RGB565 */
1087 break;
1088 default:
1089 /* should not occur */
1090 break;
1091 }
1092 return rc;
1093}
1094
1095/* ------------------------------------------------------------------------- *
1096 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 * framebuffer operations
1098 *
1099 * ------------------------------------------------------------------------- */
1100
1101static int rivafb_open(struct fb_info *info, int user)
1102{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001103 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 int cnt = atomic_read(&par->ref_count);
1105
1106 NVTRACE_ENTER();
1107 if (!cnt) {
1108#ifdef CONFIG_X86
1109 memset(&par->state, 0, sizeof(struct vgastate));
1110 par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
1111 /* save the DAC for Riva128 */
1112 if (par->riva.Architecture == NV_ARCH_03)
1113 par->state.flags |= VGA_SAVE_CMAP;
1114 save_vga(&par->state);
1115#endif
1116 /* vgaHWunlock() + riva unlock (0x7F) */
1117 CRTCout(par, 0x11, 0xFF);
1118 par->riva.LockUnlock(&par->riva, 0);
1119
1120 riva_save_state(par, &par->initial_state);
1121 }
1122 atomic_inc(&par->ref_count);
1123 NVTRACE_LEAVE();
1124 return 0;
1125}
1126
1127static int rivafb_release(struct fb_info *info, int user)
1128{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001129 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 int cnt = atomic_read(&par->ref_count);
1131
1132 NVTRACE_ENTER();
1133 if (!cnt)
1134 return -EINVAL;
1135 if (cnt == 1) {
1136 par->riva.LockUnlock(&par->riva, 0);
1137 par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);
1138 riva_load_state(par, &par->initial_state);
1139#ifdef CONFIG_X86
1140 restore_vga(&par->state);
1141#endif
1142 par->riva.LockUnlock(&par->riva, 1);
1143 }
1144 atomic_dec(&par->ref_count);
1145 NVTRACE_LEAVE();
1146 return 0;
1147}
1148
1149static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1150{
1151 struct fb_videomode *mode;
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001152 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 int nom, den; /* translating from pixels->bytes */
1154 int mode_valid = 0;
1155
1156 NVTRACE_ENTER();
1157 switch (var->bits_per_pixel) {
1158 case 1 ... 8:
1159 var->red.offset = var->green.offset = var->blue.offset = 0;
1160 var->red.length = var->green.length = var->blue.length = 8;
1161 var->bits_per_pixel = 8;
1162 nom = den = 1;
1163 break;
1164 case 9 ... 15:
1165 var->green.length = 5;
1166 /* fall through */
1167 case 16:
1168 var->bits_per_pixel = 16;
1169 /* The Riva128 supports RGB555 only */
1170 if (par->riva.Architecture == NV_ARCH_03)
1171 var->green.length = 5;
1172 if (var->green.length == 5) {
1173 /* 0rrrrrgg gggbbbbb */
1174 var->red.offset = 10;
1175 var->green.offset = 5;
1176 var->blue.offset = 0;
1177 var->red.length = 5;
1178 var->green.length = 5;
1179 var->blue.length = 5;
1180 } else {
1181 /* rrrrrggg gggbbbbb */
1182 var->red.offset = 11;
1183 var->green.offset = 5;
1184 var->blue.offset = 0;
1185 var->red.length = 5;
1186 var->green.length = 6;
1187 var->blue.length = 5;
1188 }
1189 nom = 2;
1190 den = 1;
1191 break;
1192 case 17 ... 32:
1193 var->red.length = var->green.length = var->blue.length = 8;
1194 var->bits_per_pixel = 32;
1195 var->red.offset = 16;
1196 var->green.offset = 8;
1197 var->blue.offset = 0;
1198 nom = 4;
1199 den = 1;
1200 break;
1201 default:
1202 printk(KERN_ERR PFX
1203 "mode %dx%dx%d rejected...color depth not supported.\n",
1204 var->xres, var->yres, var->bits_per_pixel);
1205 NVTRACE("EXIT, returning -EINVAL\n");
1206 return -EINVAL;
1207 }
1208
1209 if (!strictmode) {
1210 if (!info->monspecs.vfmax || !info->monspecs.hfmax ||
1211 !info->monspecs.dclkmax || !fb_validate_mode(var, info))
1212 mode_valid = 1;
1213 }
1214
1215 /* calculate modeline if supported by monitor */
1216 if (!mode_valid && info->monspecs.gtf) {
1217 if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1218 mode_valid = 1;
1219 }
1220
1221 if (!mode_valid) {
1222 mode = fb_find_best_mode(var, &info->modelist);
1223 if (mode) {
1224 riva_update_var(var, mode);
1225 mode_valid = 1;
1226 }
1227 }
1228
1229 if (!mode_valid && info->monspecs.modedb_len)
1230 return -EINVAL;
1231
1232 if (var->xres_virtual < var->xres)
1233 var->xres_virtual = var->xres;
1234 if (var->yres_virtual <= var->yres)
1235 var->yres_virtual = -1;
1236 if (rivafb_do_maximize(info, var, nom, den) < 0)
1237 return -EINVAL;
1238
1239 if (var->xoffset < 0)
1240 var->xoffset = 0;
1241 if (var->yoffset < 0)
1242 var->yoffset = 0;
1243
1244 /* truncate xoffset and yoffset to maximum if too high */
1245 if (var->xoffset > var->xres_virtual - var->xres)
1246 var->xoffset = var->xres_virtual - var->xres - 1;
1247
1248 if (var->yoffset > var->yres_virtual - var->yres)
1249 var->yoffset = var->yres_virtual - var->yres - 1;
1250
1251 var->red.msb_right =
1252 var->green.msb_right =
1253 var->blue.msb_right =
1254 var->transp.offset = var->transp.length = var->transp.msb_right = 0;
1255 NVTRACE_LEAVE();
1256 return 0;
1257}
1258
1259static int rivafb_set_par(struct fb_info *info)
1260{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001261 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
1263 NVTRACE_ENTER();
1264 /* vgaHWunlock() + riva unlock (0x7F) */
1265 CRTCout(par, 0x11, 0xFF);
1266 par->riva.LockUnlock(&par->riva, 0);
1267 riva_load_video_mode(info);
1268 if(!(info->flags & FBINFO_HWACCEL_DISABLED))
1269 riva_setup_accel(info);
1270
1271 par->cursor_reset = 1;
1272 info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
1273 info->fix.visual = (info->var.bits_per_pixel == 8) ?
1274 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1275
1276 if (info->flags & FBINFO_HWACCEL_DISABLED)
1277 info->pixmap.scan_align = 1;
1278 else
1279 info->pixmap.scan_align = 4;
1280 NVTRACE_LEAVE();
1281 return 0;
1282}
1283
1284/**
1285 * rivafb_pan_display
1286 * @var: standard kernel fb changeable data
1287 * @con: TODO
1288 * @info: pointer to fb_info object containing info for current riva board
1289 *
1290 * DESCRIPTION:
1291 * Pan (or wrap, depending on the `vmode' field) the display using the
1292 * `xoffset' and `yoffset' fields of the `var' structure.
1293 * If the values don't fit, return -EINVAL.
1294 *
1295 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1296 */
1297static int rivafb_pan_display(struct fb_var_screeninfo *var,
1298 struct fb_info *info)
1299{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001300 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 unsigned int base;
1302
1303 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 base = var->yoffset * info->fix.line_length + var->xoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 par->riva.SetStartAddress(&par->riva, base);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 NVTRACE_LEAVE();
1307 return 0;
1308}
1309
1310static int rivafb_blank(int blank, struct fb_info *info)
1311{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001312 struct riva_par *par= info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 unsigned char tmp, vesa;
1314
1315 tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
1316 vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
1317
1318 NVTRACE_ENTER();
1319
1320 if (blank)
1321 tmp |= 0x20;
1322
1323 switch (blank) {
1324 case FB_BLANK_UNBLANK:
1325 case FB_BLANK_NORMAL:
1326 break;
1327 case FB_BLANK_VSYNC_SUSPEND:
1328 vesa |= 0x80;
1329 break;
1330 case FB_BLANK_HSYNC_SUSPEND:
1331 vesa |= 0x40;
1332 break;
1333 case FB_BLANK_POWERDOWN:
1334 vesa |= 0xc0;
1335 break;
1336 }
1337
1338 SEQout(par, 0x01, tmp);
1339 CRTCout(par, 0x1a, vesa);
1340
Michael Hanselmann5474c122006-06-25 05:47:08 -07001341#ifdef CONFIG_FB_RIVA_BACKLIGHT
1342 mutex_lock(&info->bl_mutex);
1343 if (info->bl_dev) {
1344 down(&info->bl_dev->sem);
1345 info->bl_dev->props->power = blank;
1346 info->bl_dev->props->update_status(info->bl_dev);
1347 up(&info->bl_dev->sem);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 }
Michael Hanselmann5474c122006-06-25 05:47:08 -07001349 mutex_unlock(&info->bl_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350#endif
1351
1352 NVTRACE_LEAVE();
1353
1354 return 0;
1355}
1356
1357/**
1358 * rivafb_setcolreg
1359 * @regno: register index
1360 * @red: red component
1361 * @green: green component
1362 * @blue: blue component
1363 * @transp: transparency
1364 * @info: pointer to fb_info object containing info for current riva board
1365 *
1366 * DESCRIPTION:
1367 * Set a single color register. The values supplied have a 16 bit
1368 * magnitude.
1369 *
1370 * RETURNS:
1371 * Return != 0 for invalid regno.
1372 *
1373 * CALLED FROM:
1374 * fbcmap.c:fb_set_cmap()
1375 */
1376static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1377 unsigned blue, unsigned transp,
1378 struct fb_info *info)
1379{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001380 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 RIVA_HW_INST *chip = &par->riva;
1382 int i;
1383
1384 if (regno >= riva_get_cmap_len(&info->var))
1385 return -EINVAL;
1386
1387 if (info->var.grayscale) {
1388 /* gray = 0.30*R + 0.59*G + 0.11*B */
1389 red = green = blue =
1390 (red * 77 + green * 151 + blue * 28) >> 8;
1391 }
1392
1393 if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
1394 ((u32 *) info->pseudo_palette)[regno] =
1395 (regno << info->var.red.offset) |
1396 (regno << info->var.green.offset) |
1397 (regno << info->var.blue.offset);
1398 /*
1399 * The Riva128 2D engine requires color information in
1400 * TrueColor format even if framebuffer is in DirectColor
1401 */
1402 if (par->riva.Architecture == NV_ARCH_03) {
1403 switch (info->var.bits_per_pixel) {
1404 case 16:
1405 par->palette[regno] = ((red & 0xf800) >> 1) |
1406 ((green & 0xf800) >> 6) |
1407 ((blue & 0xf800) >> 11);
1408 break;
1409 case 32:
1410 par->palette[regno] = ((red & 0xff00) << 8) |
1411 ((green & 0xff00)) |
1412 ((blue & 0xff00) >> 8);
1413 break;
1414 }
1415 }
1416 }
1417
1418 switch (info->var.bits_per_pixel) {
1419 case 8:
1420 /* "transparent" stuff is completely ignored. */
1421 riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
1422 break;
1423 case 16:
1424 if (info->var.green.length == 5) {
1425 for (i = 0; i < 8; i++) {
1426 riva_wclut(chip, regno*8+i, red >> 8,
1427 green >> 8, blue >> 8);
1428 }
1429 } else {
1430 u8 r, g, b;
1431
1432 if (regno < 32) {
1433 for (i = 0; i < 8; i++) {
1434 riva_wclut(chip, regno*8+i,
1435 red >> 8, green >> 8,
1436 blue >> 8);
1437 }
1438 }
1439 riva_rclut(chip, regno*4, &r, &g, &b);
1440 for (i = 0; i < 4; i++)
1441 riva_wclut(chip, regno*4+i, r,
1442 green >> 8, b);
1443 }
1444 break;
1445 case 32:
1446 riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
1447 break;
1448 default:
1449 /* do nothing */
1450 break;
1451 }
1452 return 0;
1453}
1454
1455/**
1456 * rivafb_fillrect - hardware accelerated color fill function
1457 * @info: pointer to fb_info structure
1458 * @rect: pointer to fb_fillrect structure
1459 *
1460 * DESCRIPTION:
1461 * This function fills up a region of framebuffer memory with a solid
1462 * color with a choice of two different ROP's, copy or invert.
1463 *
1464 * CALLED FROM:
1465 * framebuffer hook
1466 */
1467static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
1468{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001469 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 u_int color, rop = 0;
1471
1472 if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
1473 cfb_fillrect(info, rect);
1474 return;
1475 }
1476
1477 if (info->var.bits_per_pixel == 8)
1478 color = rect->color;
1479 else {
1480 if (par->riva.Architecture != NV_ARCH_03)
1481 color = ((u32 *)info->pseudo_palette)[rect->color];
1482 else
1483 color = par->palette[rect->color];
1484 }
1485
1486 switch (rect->rop) {
1487 case ROP_XOR:
1488 rop = 0x66;
1489 break;
1490 case ROP_COPY:
1491 default:
1492 rop = 0xCC;
1493 break;
1494 }
1495
1496 riva_set_rop_solid(par, rop);
1497
1498 RIVA_FIFO_FREE(par->riva, Bitmap, 1);
1499 NV_WR32(&par->riva.Bitmap->Color1A, 0, color);
1500
1501 RIVA_FIFO_FREE(par->riva, Bitmap, 2);
1502 NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].TopLeft, 0,
1503 (rect->dx << 16) | rect->dy);
1504 mb();
1505 NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].WidthHeight, 0,
1506 (rect->width << 16) | rect->height);
1507 mb();
1508 riva_set_rop_solid(par, 0xcc);
1509
1510}
1511
1512/**
1513 * rivafb_copyarea - hardware accelerated blit function
1514 * @info: pointer to fb_info structure
1515 * @region: pointer to fb_copyarea structure
1516 *
1517 * DESCRIPTION:
1518 * This copies an area of pixels from one location to another
1519 *
1520 * CALLED FROM:
1521 * framebuffer hook
1522 */
1523static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
1524{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001525 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 if ((info->flags & FBINFO_HWACCEL_DISABLED)) {
1528 cfb_copyarea(info, region);
1529 return;
1530 }
1531
1532 RIVA_FIFO_FREE(par->riva, Blt, 3);
1533 NV_WR32(&par->riva.Blt->TopLeftSrc, 0,
1534 (region->sy << 16) | region->sx);
1535 NV_WR32(&par->riva.Blt->TopLeftDst, 0,
1536 (region->dy << 16) | region->dx);
1537 mb();
1538 NV_WR32(&par->riva.Blt->WidthHeight, 0,
1539 (region->height << 16) | region->width);
1540 mb();
1541}
1542
1543static inline void convert_bgcolor_16(u32 *col)
1544{
1545 *col = ((*col & 0x0000F800) << 8)
1546 | ((*col & 0x00007E0) << 5)
1547 | ((*col & 0x0000001F) << 3)
1548 | 0xFF000000;
1549 mb();
1550}
1551
1552/**
1553 * rivafb_imageblit: hardware accelerated color expand function
1554 * @info: pointer to fb_info structure
1555 * @image: pointer to fb_image structure
1556 *
1557 * DESCRIPTION:
1558 * If the source is a monochrome bitmap, the function fills up a a region
1559 * of framebuffer memory with pixels whose color is determined by the bit
1560 * setting of the bitmap, 1 - foreground, 0 - background.
1561 *
1562 * If the source is not a monochrome bitmap, color expansion is not done.
1563 * In this case, it is channeled to a software function.
1564 *
1565 * CALLED FROM:
1566 * framebuffer hook
1567 */
1568static void rivafb_imageblit(struct fb_info *info,
1569 const struct fb_image *image)
1570{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001571 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 u32 fgx = 0, bgx = 0, width, tmp;
1573 u8 *cdat = (u8 *) image->data;
1574 volatile u32 __iomem *d;
1575 int i, size;
1576
1577 if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) {
1578 cfb_imageblit(info, image);
1579 return;
1580 }
1581
1582 switch (info->var.bits_per_pixel) {
1583 case 8:
1584 fgx = image->fg_color;
1585 bgx = image->bg_color;
1586 break;
1587 case 16:
1588 case 32:
1589 if (par->riva.Architecture != NV_ARCH_03) {
1590 fgx = ((u32 *)info->pseudo_palette)[image->fg_color];
1591 bgx = ((u32 *)info->pseudo_palette)[image->bg_color];
1592 } else {
1593 fgx = par->palette[image->fg_color];
1594 bgx = par->palette[image->bg_color];
1595 }
1596 if (info->var.green.length == 6)
1597 convert_bgcolor_16(&bgx);
1598 break;
1599 }
1600
1601 RIVA_FIFO_FREE(par->riva, Bitmap, 7);
1602 NV_WR32(&par->riva.Bitmap->ClipE.TopLeft, 0,
1603 (image->dy << 16) | (image->dx & 0xFFFF));
1604 NV_WR32(&par->riva.Bitmap->ClipE.BottomRight, 0,
1605 (((image->dy + image->height) << 16) |
1606 ((image->dx + image->width) & 0xffff)));
1607 NV_WR32(&par->riva.Bitmap->Color0E, 0, bgx);
1608 NV_WR32(&par->riva.Bitmap->Color1E, 0, fgx);
1609 NV_WR32(&par->riva.Bitmap->WidthHeightInE, 0,
1610 (image->height << 16) | ((image->width + 31) & ~31));
1611 NV_WR32(&par->riva.Bitmap->WidthHeightOutE, 0,
1612 (image->height << 16) | ((image->width + 31) & ~31));
1613 NV_WR32(&par->riva.Bitmap->PointE, 0,
1614 (image->dy << 16) | (image->dx & 0xFFFF));
1615
1616 d = &par->riva.Bitmap->MonochromeData01E;
1617
1618 width = (image->width + 31)/32;
1619 size = width * image->height;
1620 while (size >= 16) {
1621 RIVA_FIFO_FREE(par->riva, Bitmap, 16);
1622 for (i = 0; i < 16; i++) {
1623 tmp = *((u32 *)cdat);
1624 cdat = (u8 *)((u32 *)cdat + 1);
1625 reverse_order(&tmp);
1626 NV_WR32(d, i*4, tmp);
1627 }
1628 size -= 16;
1629 }
1630 if (size) {
1631 RIVA_FIFO_FREE(par->riva, Bitmap, size);
1632 for (i = 0; i < size; i++) {
1633 tmp = *((u32 *) cdat);
1634 cdat = (u8 *)((u32 *)cdat + 1);
1635 reverse_order(&tmp);
1636 NV_WR32(d, i*4, tmp);
1637 }
1638 }
1639}
1640
1641/**
1642 * rivafb_cursor - hardware cursor function
1643 * @info: pointer to info structure
1644 * @cursor: pointer to fbcursor structure
1645 *
1646 * DESCRIPTION:
1647 * A cursor function that supports displaying a cursor image via hardware.
1648 * Within the kernel, copy and invert rops are supported. If exported
1649 * to user space, only the copy rop will be supported.
1650 *
1651 * CALLED FROM
1652 * framebuffer hook
1653 */
1654static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1655{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001656 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 u8 data[MAX_CURS * MAX_CURS/8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 int i, set = cursor->set;
James Simmonsf1ab5da2005-06-21 17:17:07 -07001659 u16 fg, bg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660
James Simmonsf1ab5da2005-06-21 17:17:07 -07001661 if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
1662 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663
1664 par->riva.ShowHideCursor(&par->riva, 0);
1665
1666 if (par->cursor_reset) {
1667 set = FB_CUR_SETALL;
1668 par->cursor_reset = 0;
1669 }
1670
1671 if (set & FB_CUR_SETSIZE)
1672 memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
1673
1674 if (set & FB_CUR_SETPOS) {
1675 u32 xx, yy, temp;
1676
1677 yy = cursor->image.dy - info->var.yoffset;
1678 xx = cursor->image.dx - info->var.xoffset;
1679 temp = xx & 0xFFFF;
1680 temp |= yy << 16;
1681
1682 NV_WR32(par->riva.PRAMDAC, 0x0000300, temp);
1683 }
1684
1685
1686 if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
1687 u32 bg_idx = cursor->image.bg_color;
1688 u32 fg_idx = cursor->image.fg_color;
1689 u32 s_pitch = (cursor->image.width+7) >> 3;
1690 u32 d_pitch = MAX_CURS/8;
1691 u8 *dat = (u8 *) cursor->image.data;
1692 u8 *msk = (u8 *) cursor->mask;
1693 u8 *src;
1694
1695 src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
1696
1697 if (src) {
1698 switch (cursor->rop) {
1699 case ROP_XOR:
James Simmonsf1ab5da2005-06-21 17:17:07 -07001700 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 src[i] = dat[i] ^ msk[i];
1702 break;
1703 case ROP_COPY:
1704 default:
James Simmonsf1ab5da2005-06-21 17:17:07 -07001705 for (i = 0; i < s_pitch * cursor->image.height; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 src[i] = dat[i] & msk[i];
1707 break;
1708 }
1709
James Simmonsf1ab5da2005-06-21 17:17:07 -07001710 fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
1711 cursor->image.height);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712
1713 bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
1714 ((info->cmap.green[bg_idx] & 0xf8) << 2) |
1715 ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
1716 1 << 15;
1717
1718 fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
1719 ((info->cmap.green[fg_idx] & 0xf8) << 2) |
1720 ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
1721 1 << 15;
1722
1723 par->riva.LockUnlock(&par->riva, 0);
1724
1725 rivafb_load_cursor_image(par, data, bg, fg,
1726 cursor->image.width,
1727 cursor->image.height);
1728 kfree(src);
1729 }
1730 }
1731
1732 if (cursor->enable)
1733 par->riva.ShowHideCursor(&par->riva, 1);
1734
1735 return 0;
1736}
1737
1738static int rivafb_sync(struct fb_info *info)
1739{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001740 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
1742 wait_for_idle(par);
1743 return 0;
1744}
1745
1746/* ------------------------------------------------------------------------- *
1747 *
1748 * initialization helper functions
1749 *
1750 * ------------------------------------------------------------------------- */
1751
1752/* kernel interface */
1753static struct fb_ops riva_fb_ops = {
1754 .owner = THIS_MODULE,
1755 .fb_open = rivafb_open,
1756 .fb_release = rivafb_release,
1757 .fb_check_var = rivafb_check_var,
1758 .fb_set_par = rivafb_set_par,
1759 .fb_setcolreg = rivafb_setcolreg,
1760 .fb_pan_display = rivafb_pan_display,
1761 .fb_blank = rivafb_blank,
1762 .fb_fillrect = rivafb_fillrect,
1763 .fb_copyarea = rivafb_copyarea,
1764 .fb_imageblit = rivafb_imageblit,
1765 .fb_cursor = rivafb_cursor,
1766 .fb_sync = rivafb_sync,
1767};
1768
1769static int __devinit riva_set_fbinfo(struct fb_info *info)
1770{
1771 unsigned int cmap_len;
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001772 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
1774 NVTRACE_ENTER();
1775 info->flags = FBINFO_DEFAULT
1776 | FBINFO_HWACCEL_XPAN
1777 | FBINFO_HWACCEL_YPAN
1778 | FBINFO_HWACCEL_COPYAREA
1779 | FBINFO_HWACCEL_FILLRECT
1780 | FBINFO_HWACCEL_IMAGEBLIT;
1781
1782 /* Accel seems to not work properly on NV30 yet...*/
1783 if ((par->riva.Architecture == NV_ARCH_30) || noaccel) {
1784 printk(KERN_DEBUG PFX "disabling acceleration\n");
1785 info->flags |= FBINFO_HWACCEL_DISABLED;
1786 }
1787
1788 info->var = rivafb_default_var;
1789 info->fix.visual = (info->var.bits_per_pixel == 8) ?
1790 FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
1791
1792 info->pseudo_palette = par->pseudo_palette;
1793
1794 cmap_len = riva_get_cmap_len(&info->var);
1795 fb_alloc_cmap(&info->cmap, cmap_len, 0);
1796
1797 info->pixmap.size = 8 * 1024;
1798 info->pixmap.buf_align = 4;
James Simmons58a60642005-06-21 17:17:08 -07001799 info->pixmap.access_align = 32;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1801 info->var.yres_virtual = -1;
1802 NVTRACE_LEAVE();
1803 return (rivafb_check_var(&info->var, info));
1804}
1805
1806#ifdef CONFIG_PPC_OF
1807static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd)
1808{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001809 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 struct device_node *dp;
1811 unsigned char *pedid = NULL;
1812 unsigned char *disptype = NULL;
1813 static char *propnames[] = {
1814 "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
1815 int i;
1816
1817 NVTRACE_ENTER();
1818 dp = pci_device_to_OF_node(pd);
1819 for (; dp != NULL; dp = dp->child) {
1820 disptype = (unsigned char *)get_property(dp, "display-type", NULL);
1821 if (disptype == NULL)
1822 continue;
1823 if (strncmp(disptype, "LCD", 3) != 0)
1824 continue;
1825 for (i = 0; propnames[i] != NULL; ++i) {
1826 pedid = (unsigned char *)
1827 get_property(dp, propnames[i], NULL);
1828 if (pedid != NULL) {
1829 par->EDID = pedid;
1830 NVTRACE("LCD found.\n");
1831 return 1;
1832 }
1833 }
1834 }
1835 NVTRACE_LEAVE();
1836 return 0;
1837}
1838#endif /* CONFIG_PPC_OF */
1839
1840#if defined(CONFIG_FB_RIVA_I2C) && !defined(CONFIG_PPC_OF)
1841static int __devinit riva_get_EDID_i2c(struct fb_info *info)
1842{
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001843 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 struct fb_var_screeninfo var;
1845 int i;
1846
1847 NVTRACE_ENTER();
1848 riva_create_i2c_busses(par);
1849 for (i = 0; i < par->bus; i++) {
1850 riva_probe_i2c_connector(par, i+1, &par->EDID);
1851 if (par->EDID && !fb_parse_edid(par->EDID, &var)) {
1852 printk(PFX "Found EDID Block from BUS %i\n", i);
1853 break;
1854 }
1855 }
1856
1857 NVTRACE_LEAVE();
1858 return (par->EDID) ? 1 : 0;
1859}
1860#endif /* CONFIG_FB_RIVA_I2C */
1861
1862static void __devinit riva_update_default_var(struct fb_var_screeninfo *var,
1863 struct fb_info *info)
1864{
1865 struct fb_monspecs *specs = &info->monspecs;
1866 struct fb_videomode modedb;
1867
1868 NVTRACE_ENTER();
1869 /* respect mode options */
1870 if (mode_option) {
1871 fb_find_mode(var, info, mode_option,
1872 specs->modedb, specs->modedb_len,
1873 NULL, 8);
1874 } else if (specs->modedb != NULL) {
1875 /* get preferred timing */
1876 if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
1877 int i;
1878
1879 for (i = 0; i < specs->modedb_len; i++) {
1880 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
1881 modedb = specs->modedb[i];
1882 break;
1883 }
1884 }
1885 } else {
1886 /* otherwise, get first mode in database */
1887 modedb = specs->modedb[0];
1888 }
1889 var->bits_per_pixel = 8;
1890 riva_update_var(var, &modedb);
1891 }
1892 NVTRACE_LEAVE();
1893}
1894
1895
1896static void __devinit riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
1897{
1898 NVTRACE_ENTER();
1899#ifdef CONFIG_PPC_OF
1900 if (!riva_get_EDID_OF(info, pdev))
1901 printk(PFX "could not retrieve EDID from OF\n");
Olaf Hering44456d32005-07-27 11:45:17 -07001902#elif defined(CONFIG_FB_RIVA_I2C)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 if (!riva_get_EDID_i2c(info))
1904 printk(PFX "could not retrieve EDID from DDC/I2C\n");
1905#endif
1906 NVTRACE_LEAVE();
1907}
1908
1909
1910static void __devinit riva_get_edidinfo(struct fb_info *info)
1911{
1912 struct fb_var_screeninfo *var = &rivafb_default_var;
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001913 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914
1915 fb_edid_to_monspecs(par->EDID, &info->monspecs);
1916 fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len,
1917 &info->modelist);
1918 riva_update_default_var(var, info);
1919
1920 /* if user specified flatpanel, we respect that */
1921 if (info->monspecs.input & FB_DISP_DDI)
1922 par->FlatPanel = 1;
1923}
1924
1925/* ------------------------------------------------------------------------- *
1926 *
1927 * PCI bus
1928 *
1929 * ------------------------------------------------------------------------- */
1930
1931static u32 __devinit riva_get_arch(struct pci_dev *pd)
1932{
1933 u32 arch = 0;
1934
1935 switch (pd->device & 0x0ff0) {
1936 case 0x0100: /* GeForce 256 */
1937 case 0x0110: /* GeForce2 MX */
1938 case 0x0150: /* GeForce2 */
1939 case 0x0170: /* GeForce4 MX */
1940 case 0x0180: /* GeForce4 MX (8x AGP) */
1941 case 0x01A0: /* nForce */
1942 case 0x01F0: /* nForce2 */
1943 arch = NV_ARCH_10;
1944 break;
1945 case 0x0200: /* GeForce3 */
1946 case 0x0250: /* GeForce4 Ti */
1947 case 0x0280: /* GeForce4 Ti (8x AGP) */
1948 arch = NV_ARCH_20;
1949 break;
1950 case 0x0300: /* GeForceFX 5800 */
1951 case 0x0310: /* GeForceFX 5600 */
1952 case 0x0320: /* GeForceFX 5200 */
1953 case 0x0330: /* GeForceFX 5900 */
1954 case 0x0340: /* GeForceFX 5700 */
1955 arch = NV_ARCH_30;
1956 break;
1957 case 0x0020: /* TNT, TNT2 */
1958 arch = NV_ARCH_04;
1959 break;
1960 case 0x0010: /* Riva128 */
1961 arch = NV_ARCH_03;
1962 break;
1963 default: /* unknown architecture */
1964 break;
1965 }
1966 return arch;
1967}
1968
1969static int __devinit rivafb_probe(struct pci_dev *pd,
1970 const struct pci_device_id *ent)
1971{
1972 struct riva_par *default_par;
1973 struct fb_info *info;
1974 int ret;
1975
1976 NVTRACE_ENTER();
1977 assert(pd != NULL);
1978
1979 info = framebuffer_alloc(sizeof(struct riva_par), &pd->dev);
1980 if (!info) {
1981 printk (KERN_ERR PFX "could not allocate memory\n");
1982 ret = -ENOMEM;
1983 goto err_ret;
1984 }
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08001985 default_par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 default_par->pdev = pd;
1987
1988 info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
1989 if (info->pixmap.addr == NULL) {
1990 ret = -ENOMEM;
1991 goto err_framebuffer_release;
1992 }
1993 memset(info->pixmap.addr, 0, 8 * 1024);
1994
1995 ret = pci_enable_device(pd);
1996 if (ret < 0) {
1997 printk(KERN_ERR PFX "cannot enable PCI device\n");
1998 goto err_free_pixmap;
1999 }
2000
2001 ret = pci_request_regions(pd, "rivafb");
2002 if (ret < 0) {
2003 printk(KERN_ERR PFX "cannot request PCI regions\n");
2004 goto err_disable_device;
2005 }
2006
2007 default_par->riva.Architecture = riva_get_arch(pd);
2008
2009 default_par->Chipset = (pd->vendor << 16) | pd->device;
2010 printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 if(default_par->riva.Architecture == 0) {
2013 printk(KERN_ERR PFX "unknown NV_ARCH\n");
2014 ret=-ENODEV;
2015 goto err_release_region;
2016 }
2017 if(default_par->riva.Architecture == NV_ARCH_10 ||
2018 default_par->riva.Architecture == NV_ARCH_20 ||
2019 default_par->riva.Architecture == NV_ARCH_30) {
2020 sprintf(rivafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
2021 } else {
2022 sprintf(rivafb_fix.id, "NV%x", default_par->riva.Architecture);
2023 }
2024
2025 default_par->FlatPanel = flatpanel;
2026 if (flatpanel == 1)
2027 printk(KERN_INFO PFX "flatpanel support enabled\n");
2028 default_par->forceCRTC = forceCRTC;
2029
2030 rivafb_fix.mmio_len = pci_resource_len(pd, 0);
2031 rivafb_fix.smem_len = pci_resource_len(pd, 1);
2032
2033 {
2034 /* enable IO and mem if not already done */
2035 unsigned short cmd;
2036
2037 pci_read_config_word(pd, PCI_COMMAND, &cmd);
2038 cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
2039 pci_write_config_word(pd, PCI_COMMAND, cmd);
2040 }
2041
2042 rivafb_fix.mmio_start = pci_resource_start(pd, 0);
2043 rivafb_fix.smem_start = pci_resource_start(pd, 1);
2044
2045 default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
2046 rivafb_fix.mmio_len);
2047 if (!default_par->ctrl_base) {
2048 printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
2049 ret = -EIO;
2050 goto err_release_region;
2051 }
2052
2053 switch (default_par->riva.Architecture) {
2054 case NV_ARCH_03:
2055 /* Riva128's PRAMIN is in the "framebuffer" space
2056 * Since these cards were never made with more than 8 megabytes
2057 * we can safely allocate this separately.
2058 */
2059 default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
2060 if (!default_par->riva.PRAMIN) {
2061 printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
2062 ret = -EIO;
2063 goto err_iounmap_ctrl_base;
2064 }
2065 break;
2066 case NV_ARCH_04:
2067 case NV_ARCH_10:
2068 case NV_ARCH_20:
2069 case NV_ARCH_30:
2070 default_par->riva.PCRTC0 =
2071 (u32 __iomem *)(default_par->ctrl_base + 0x00600000);
2072 default_par->riva.PRAMIN =
2073 (u32 __iomem *)(default_par->ctrl_base + 0x00710000);
2074 break;
2075 }
2076 riva_common_setup(default_par);
2077
2078 if (default_par->riva.Architecture == NV_ARCH_03) {
2079 default_par->riva.PCRTC = default_par->riva.PCRTC0
2080 = default_par->riva.PGRAPH;
2081 }
2082
2083 rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
2084 default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
2085 info->screen_base = ioremap(rivafb_fix.smem_start,
2086 rivafb_fix.smem_len);
2087 if (!info->screen_base) {
2088 printk(KERN_ERR PFX "cannot ioremap FB base\n");
2089 ret = -EIO;
2090 goto err_iounmap_pramin;
2091 }
2092
2093#ifdef CONFIG_MTRR
2094 if (!nomtrr) {
2095 default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
2096 rivafb_fix.smem_len,
2097 MTRR_TYPE_WRCOMB, 1);
2098 if (default_par->mtrr.vram < 0) {
2099 printk(KERN_ERR PFX "unable to setup MTRR\n");
2100 } else {
2101 default_par->mtrr.vram_valid = 1;
2102 /* let there be speed */
2103 printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
2104 }
2105 }
2106#endif /* CONFIG_MTRR */
2107
2108 info->fbops = &riva_fb_ops;
2109 info->fix = rivafb_fix;
2110 riva_get_EDID(info, pd);
2111 riva_get_edidinfo(info);
2112
2113 ret=riva_set_fbinfo(info);
2114 if (ret < 0) {
2115 printk(KERN_ERR PFX "error setting initial video mode\n");
2116 goto err_iounmap_screen_base;
2117 }
2118
2119 fb_destroy_modedb(info->monspecs.modedb);
2120 info->monspecs.modedb = NULL;
2121 ret = register_framebuffer(info);
2122 if (ret < 0) {
2123 printk(KERN_ERR PFX
2124 "error registering riva framebuffer\n");
2125 goto err_iounmap_screen_base;
2126 }
2127
2128 pci_set_drvdata(pd, info);
2129
2130 printk(KERN_INFO PFX
2131 "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n",
2132 info->fix.id,
2133 RIVAFB_VERSION,
2134 info->fix.smem_len / (1024 * 1024),
2135 info->fix.smem_start);
Michael Hanselmann5474c122006-06-25 05:47:08 -07002136
2137 riva_bl_init(info->par);
2138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 NVTRACE_LEAVE();
2140 return 0;
2141
2142err_iounmap_screen_base:
2143#ifdef CONFIG_FB_RIVA_I2C
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08002144 riva_delete_i2c_busses(info->par);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145#endif
2146 iounmap(info->screen_base);
2147err_iounmap_pramin:
2148 if (default_par->riva.Architecture == NV_ARCH_03)
2149 iounmap(default_par->riva.PRAMIN);
2150err_iounmap_ctrl_base:
2151 iounmap(default_par->ctrl_base);
2152err_release_region:
2153 pci_release_regions(pd);
2154err_disable_device:
2155 pci_disable_device(pd);
2156err_free_pixmap:
2157 kfree(info->pixmap.addr);
2158err_framebuffer_release:
2159 framebuffer_release(info);
2160err_ret:
2161 return ret;
2162}
2163
2164static void __exit rivafb_remove(struct pci_dev *pd)
2165{
2166 struct fb_info *info = pci_get_drvdata(pd);
Antonino A. Daplasf4a41832006-01-09 20:53:04 -08002167 struct riva_par *par = info->par;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
2169 NVTRACE_ENTER();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170
Michael Hanselmann5474c122006-06-25 05:47:08 -07002171 riva_bl_exit(par);
2172
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173#ifdef CONFIG_FB_RIVA_I2C
2174 riva_delete_i2c_busses(par);
2175 kfree(par->EDID);
2176#endif
2177
2178 unregister_framebuffer(info);
2179#ifdef CONFIG_MTRR
2180 if (par->mtrr.vram_valid)
2181 mtrr_del(par->mtrr.vram, info->fix.smem_start,
2182 info->fix.smem_len);
2183#endif /* CONFIG_MTRR */
2184
2185 iounmap(par->ctrl_base);
2186 iounmap(info->screen_base);
2187 if (par->riva.Architecture == NV_ARCH_03)
2188 iounmap(par->riva.PRAMIN);
2189 pci_release_regions(pd);
2190 pci_disable_device(pd);
2191 kfree(info->pixmap.addr);
2192 framebuffer_release(info);
2193 pci_set_drvdata(pd, NULL);
2194 NVTRACE_LEAVE();
2195}
2196
2197/* ------------------------------------------------------------------------- *
2198 *
2199 * initialization
2200 *
2201 * ------------------------------------------------------------------------- */
2202
2203#ifndef MODULE
2204static int __init rivafb_setup(char *options)
2205{
2206 char *this_opt;
2207
2208 NVTRACE_ENTER();
2209 if (!options || !*options)
2210 return 0;
2211
2212 while ((this_opt = strsep(&options, ",")) != NULL) {
2213 if (!strncmp(this_opt, "forceCRTC", 9)) {
2214 char *p;
2215
2216 p = this_opt + 9;
2217 if (!*p || !*(++p)) continue;
2218 forceCRTC = *p - '0';
2219 if (forceCRTC < 0 || forceCRTC > 1)
2220 forceCRTC = -1;
2221 } else if (!strncmp(this_opt, "flatpanel", 9)) {
2222 flatpanel = 1;
2223#ifdef CONFIG_MTRR
2224 } else if (!strncmp(this_opt, "nomtrr", 6)) {
2225 nomtrr = 1;
2226#endif
2227 } else if (!strncmp(this_opt, "strictmode", 10)) {
2228 strictmode = 1;
2229 } else if (!strncmp(this_opt, "noaccel", 7)) {
2230 noaccel = 1;
2231 } else
2232 mode_option = this_opt;
2233 }
2234 NVTRACE_LEAVE();
2235 return 0;
2236}
2237#endif /* !MODULE */
2238
2239static struct pci_driver rivafb_driver = {
2240 .name = "rivafb",
2241 .id_table = rivafb_pci_tbl,
2242 .probe = rivafb_probe,
2243 .remove = __exit_p(rivafb_remove),
2244};
2245
2246
2247
2248/* ------------------------------------------------------------------------- *
2249 *
2250 * modularization
2251 *
2252 * ------------------------------------------------------------------------- */
2253
2254static int __devinit rivafb_init(void)
2255{
2256#ifndef MODULE
2257 char *option = NULL;
2258
2259 if (fb_get_options("rivafb", &option))
2260 return -ENODEV;
2261 rivafb_setup(option);
2262#endif
2263 return pci_register_driver(&rivafb_driver);
2264}
2265
2266
2267module_init(rivafb_init);
2268
2269#ifdef MODULE
2270static void __exit rivafb_exit(void)
2271{
2272 pci_unregister_driver(&rivafb_driver);
2273}
2274
2275module_exit(rivafb_exit);
2276#endif /* MODULE */
2277
2278module_param(noaccel, bool, 0);
2279MODULE_PARM_DESC(noaccel, "bool: disable acceleration");
2280module_param(flatpanel, int, 0);
2281MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
2282module_param(forceCRTC, int, 0);
2283MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
2284#ifdef CONFIG_MTRR
2285module_param(nomtrr, bool, 0);
2286MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
2287#endif
2288module_param(strictmode, bool, 0);
2289MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
2290
2291MODULE_AUTHOR("Ani Joshi, maintainer");
2292MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, and the GeForce series");
2293MODULE_LICENSE("GPL");