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