2 * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device
4 * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net>
8 * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets
9 * and enabling the power-on state of
10 * external VGA connectors for
13 * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of
16 * Brad Corrion <bcorrion@web-co.com> - alpha testing of customized
19 * The code framework is a modification of vfb.c by Geert Uytterhoeven.
20 * DotClock and PLL calculations are partly based on i810_driver.c
21 * in xfree86 v4.0.3 by Precision Insight.
22 * Watermark calculation and tables are based on i810_wmark.c
23 * in xfre86 v4.0.3 by Precision Insight. Slight modifications
24 * only to allow for integer operations instead of floating point.
26 * This file is subject to the terms and conditions of the GNU General Public
27 * License. See the file COPYING in the main directory of this archive for
31 #include <linux/module.h>
32 #include <linux/config.h>
33 #include <linux/kernel.h>
34 #include <linux/errno.h>
35 #include <linux/string.h>
37 #include <linux/tty.h>
38 #include <linux/slab.h>
40 #include <linux/init.h>
41 #include <linux/pci.h>
42 #include <linux/pci_ids.h>
43 #include <linux/resource.h>
44 #include <linux/unistd.h>
47 #include <asm/div64.h>
55 #include "i810_regs.h"
57 #include "i810_main.h"
60 static const char *i810_pci_list
[] __devinitdata
= {
61 "Intel(R) 810 Framebuffer Device" ,
62 "Intel(R) 810-DC100 Framebuffer Device" ,
63 "Intel(R) 810E Framebuffer Device" ,
64 "Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device" ,
65 "Intel(R) 815 (Internal Graphics only) Framebuffer Device" ,
66 "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"
69 static struct pci_device_id i810fb_pci_tbl
[] = {
70 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810_IG1
,
71 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
72 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810_IG3
,
73 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 1 },
74 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82810E_IG
,
75 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 2 },
76 /* mvo: added i815 PCI-ID */
77 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82815_100
,
78 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 3 },
79 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82815_NOAGP
,
80 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 4 },
81 { PCI_VENDOR_ID_INTEL
, PCI_DEVICE_ID_INTEL_82815_CGC
,
82 PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 5 },
86 static struct pci_driver i810fb_driver
= {
88 .id_table
= i810fb_pci_tbl
,
89 .probe
= i810fb_init_pci
,
90 .remove
= __exit_p(i810fb_remove_pci
),
91 .suspend
= i810fb_suspend
,
92 .resume
= i810fb_resume
,
95 static int vram __initdata
= 4;
96 static int bpp __initdata
= 8;
97 static int mtrr __initdata
= 0;
98 static int accel __initdata
= 0;
99 static int hsync1 __initdata
= 0;
100 static int hsync2 __initdata
= 0;
101 static int vsync1 __initdata
= 0;
102 static int vsync2 __initdata
= 0;
103 static int xres __initdata
= 640;
104 static int yres __initdata
= 480;
105 static int vyres __initdata
= 0;
106 static int sync __initdata
= 0;
107 static int ext_vga __initdata
= 0;
108 static int dcolor __initdata
= 0;
110 /*------------------------------------------------------------*/
112 /**************************************************************
113 * Hardware Low Level Routines *
114 **************************************************************/
117 * i810_screen_off - turns off/on display
118 * @mmio: address of register space
122 * Blanks/unblanks the display
124 static void i810_screen_off(u8
*mmio
, u8 mode
)
126 u32 count
= WAIT_COUNT
;
129 i810_writeb(SR_INDEX
, mmio
, SR01
);
130 val
= i810_readb(SR_DATA
, mmio
);
131 val
= (mode
== OFF
) ? val
| SCR_OFF
:
134 while((i810_readw(DISP_SL
, mmio
) & 0xFFF) && count
--);
135 i810_writeb(SR_INDEX
, mmio
, SR01
);
136 i810_writeb(SR_DATA
, mmio
, val
);
140 * i810_dram_off - turns off/on dram refresh
141 * @mmio: address of register space
145 * Turns off DRAM refresh. Must be off for only 2 vsyncs
146 * before data becomes corrupt
148 static void i810_dram_off(u8
*mmio
, u8 mode
)
152 val
= i810_readb(DRAMCH
, mmio
);
154 val
= (mode
== OFF
) ? val
: val
| DRAM_ON
;
155 i810_writeb(DRAMCH
, mmio
, val
);
159 * i810_protect_regs - allows rw/ro mode of certain VGA registers
160 * @mmio: address of register space
161 * @mode: protect/unprotect
164 * The IBM VGA standard allows protection of certain VGA registers.
165 * This will protect or unprotect them.
167 static void i810_protect_regs(u8
*mmio
, int mode
)
171 i810_writeb(CR_INDEX_CGA
, mmio
, CR11
);
172 reg
= i810_readb(CR_DATA_CGA
, mmio
);
173 reg
= (mode
== OFF
) ? reg
& ~0x80 :
176 i810_writeb(CR_INDEX_CGA
, mmio
, CR11
);
177 i810_writeb(CR_DATA_CGA
, mmio
, reg
);
181 * i810_load_pll - loads values for the hardware PLL clock
182 * @par: pointer to i810fb_par structure
185 * Loads the P, M, and N registers.
187 static void i810_load_pll(struct i810fb_par
*par
)
190 u8
*mmio
= par
->mmio_start_virtual
;
192 tmp1
= par
->regs
.M
| par
->regs
.N
<< 16;
193 tmp2
= i810_readl(DCLK_2D
, mmio
);
195 i810_writel(DCLK_2D
, mmio
, tmp1
| tmp2
);
198 tmp2
= i810_readl(DCLK_0DS
, mmio
);
199 tmp2
&= ~(P_OR
<< 16);
200 i810_writel(DCLK_0DS
, mmio
, (tmp1
<< 16) | tmp2
);
202 i810_writeb(MSR_WRITE
, mmio
, par
->regs
.msr
| 0xC8 | 1);
207 * i810_load_vga - load standard VGA registers
208 * @par: pointer to i810fb_par structure
211 * Load values to VGA registers
213 static void i810_load_vga(struct i810fb_par
*par
)
215 u8
*mmio
= par
->mmio_start_virtual
;
218 i810_writeb(CR_INDEX_CGA
, mmio
, CR70
);
219 i810_writeb(CR_DATA_CGA
, mmio
, par
->interlace
);
221 i810_writeb(CR_INDEX_CGA
, mmio
, CR00
);
222 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr00
);
223 i810_writeb(CR_INDEX_CGA
, mmio
, CR01
);
224 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr01
);
225 i810_writeb(CR_INDEX_CGA
, mmio
, CR02
);
226 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr02
);
227 i810_writeb(CR_INDEX_CGA
, mmio
, CR03
);
228 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr03
);
229 i810_writeb(CR_INDEX_CGA
, mmio
, CR04
);
230 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr04
);
231 i810_writeb(CR_INDEX_CGA
, mmio
, CR05
);
232 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr05
);
233 i810_writeb(CR_INDEX_CGA
, mmio
, CR06
);
234 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr06
);
235 i810_writeb(CR_INDEX_CGA
, mmio
, CR09
);
236 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr09
);
237 i810_writeb(CR_INDEX_CGA
, mmio
, CR10
);
238 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr10
);
239 i810_writeb(CR_INDEX_CGA
, mmio
, CR11
);
240 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr11
);
241 i810_writeb(CR_INDEX_CGA
, mmio
, CR12
);
242 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr12
);
243 i810_writeb(CR_INDEX_CGA
, mmio
, CR15
);
244 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr15
);
245 i810_writeb(CR_INDEX_CGA
, mmio
, CR16
);
246 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr16
);
250 * i810_load_vgax - load extended VGA registers
251 * @par: pointer to i810fb_par structure
254 * Load values to extended VGA registers
256 static void i810_load_vgax(struct i810fb_par
*par
)
258 u8
*mmio
= par
->mmio_start_virtual
;
260 i810_writeb(CR_INDEX_CGA
, mmio
, CR30
);
261 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr30
);
262 i810_writeb(CR_INDEX_CGA
, mmio
, CR31
);
263 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr31
);
264 i810_writeb(CR_INDEX_CGA
, mmio
, CR32
);
265 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr32
);
266 i810_writeb(CR_INDEX_CGA
, mmio
, CR33
);
267 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr33
);
268 i810_writeb(CR_INDEX_CGA
, mmio
, CR35
);
269 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr35
);
270 i810_writeb(CR_INDEX_CGA
, mmio
, CR39
);
271 i810_writeb(CR_DATA_CGA
, mmio
, par
->regs
.cr39
);
275 * i810_load_2d - load grahics registers
276 * @par: pointer to i810fb_par structure
279 * Load values to graphics registers
281 static void i810_load_2d(struct i810fb_par
*par
)
284 u8 tmp8
, *mmio
= par
->mmio_start_virtual
;
286 i810_writel(FW_BLC
, mmio
, par
->watermark
);
287 tmp
= i810_readl(PIXCONF
, mmio
);
289 i810_writel(PIXCONF
, mmio
, tmp
);
291 i810_writel(OVRACT
, mmio
, par
->ovract
);
293 i810_writeb(GR_INDEX
, mmio
, GR10
);
294 tmp8
= i810_readb(GR_DATA
, mmio
);
296 i810_writeb(GR_INDEX
, mmio
, GR10
);
297 i810_writeb(GR_DATA
, mmio
, tmp8
);
301 * i810_hires - enables high resolution mode
302 * @mmio: address of register space
304 static void i810_hires(u8
*mmio
)
308 i810_writeb(CR_INDEX_CGA
, mmio
, CR80
);
309 val
= i810_readb(CR_DATA_CGA
, mmio
);
310 i810_writeb(CR_INDEX_CGA
, mmio
, CR80
);
311 i810_writeb(CR_DATA_CGA
, mmio
, val
| 1);
315 * i810_load_pitch - loads the characters per line of the display
316 * @par: pointer to i810fb_par structure
319 * Loads the characters per line
321 static void i810_load_pitch(struct i810fb_par
*par
)
324 u8 val
, *mmio
= par
->mmio_start_virtual
;
326 pitch
= par
->pitch
>> 3;
327 i810_writeb(SR_INDEX
, mmio
, SR01
);
328 val
= i810_readb(SR_DATA
, mmio
);
331 i810_writeb(SR_INDEX
, mmio
, SR01
);
332 i810_writeb(SR_DATA
, mmio
, val
);
335 i810_writeb(CR_INDEX_CGA
, mmio
, CR13
);
336 i810_writeb(CR_DATA_CGA
, mmio
, (u8
) tmp
);
339 i810_writeb(CR_INDEX_CGA
, mmio
, CR41
);
340 val
= i810_readb(CR_DATA_CGA
, mmio
) & ~0x0F;
341 i810_writeb(CR_INDEX_CGA
, mmio
, CR41
);
342 i810_writeb(CR_DATA_CGA
, mmio
, (u8
) tmp
| val
);
346 * i810_load_color - loads the color depth of the display
347 * @par: pointer to i810fb_par structure
350 * Loads the color depth of the display and the graphics engine
352 static void i810_load_color(struct i810fb_par
*par
)
354 u8
*mmio
= par
->mmio_start_virtual
;
357 reg1
= i810_readl(PIXCONF
, mmio
) & ~(0xF0000 | 1 << 27);
358 reg2
= i810_readw(BLTCNTL
, mmio
) & ~0x30;
360 reg1
|= 0x8000 | par
->pixconf
;
361 reg2
|= par
->bltcntl
;
362 i810_writel(PIXCONF
, mmio
, reg1
);
363 i810_writew(BLTCNTL
, mmio
, reg2
);
367 * i810_load_regs - loads all registers for the mode
368 * @par: pointer to i810fb_par structure
373 static void i810_load_regs(struct i810fb_par
*par
)
375 u8
*mmio
= par
->mmio_start_virtual
;
377 i810_screen_off(mmio
, OFF
);
378 i810_protect_regs(mmio
, OFF
);
379 i810_dram_off(mmio
, OFF
);
383 i810_dram_off(mmio
, ON
);
386 i810_screen_off(mmio
, ON
);
387 i810_protect_regs(mmio
, ON
);
388 i810_load_color(par
);
389 i810_load_pitch(par
);
392 static void i810_write_dac(u8 regno
, u8 red
, u8 green
, u8 blue
,
395 i810_writeb(CLUT_INDEX_WRITE
, mmio
, regno
);
396 i810_writeb(CLUT_DATA
, mmio
, red
);
397 i810_writeb(CLUT_DATA
, mmio
, green
);
398 i810_writeb(CLUT_DATA
, mmio
, blue
);
401 static void i810_read_dac(u8 regno
, u8
*red
, u8
*green
, u8
*blue
,
404 i810_writeb(CLUT_INDEX_READ
, mmio
, regno
);
405 *red
= i810_readb(CLUT_DATA
, mmio
);
406 *green
= i810_readb(CLUT_DATA
, mmio
);
407 *blue
= i810_readb(CLUT_DATA
, mmio
);
410 /************************************************************
411 * VGA State Restore *
412 ************************************************************/
413 static void i810_restore_pll(struct i810fb_par
*par
)
416 u8
*mmio
= par
->mmio_start_virtual
;
418 tmp1
= par
->hw_state
.dclk_2d
;
419 tmp2
= i810_readl(DCLK_2D
, mmio
);
422 i810_writel(DCLK_2D
, mmio
, tmp1
| tmp2
);
424 tmp1
= par
->hw_state
.dclk_1d
;
425 tmp2
= i810_readl(DCLK_1D
, mmio
);
428 i810_writel(DCLK_1D
, mmio
, tmp1
| tmp2
);
430 i810_writel(DCLK_0DS
, mmio
, par
->hw_state
.dclk_0ds
);
433 static void i810_restore_dac(struct i810fb_par
*par
)
436 u8
*mmio
= par
->mmio_start_virtual
;
438 tmp1
= par
->hw_state
.pixconf
;
439 tmp2
= i810_readl(PIXCONF
, mmio
);
442 i810_writel(PIXCONF
, mmio
, tmp1
| tmp2
);
445 static void i810_restore_vgax(struct i810fb_par
*par
)
447 u8 i
, j
, *mmio
= par
->mmio_start_virtual
;
449 for (i
= 0; i
< 4; i
++) {
450 i810_writeb(CR_INDEX_CGA
, mmio
, CR30
+i
);
451 i810_writeb(CR_DATA_CGA
, mmio
, *(&(par
->hw_state
.cr30
) + i
));
453 i810_writeb(CR_INDEX_CGA
, mmio
, CR35
);
454 i810_writeb(CR_DATA_CGA
, mmio
, par
->hw_state
.cr35
);
455 i810_writeb(CR_INDEX_CGA
, mmio
, CR39
);
456 i810_writeb(CR_DATA_CGA
, mmio
, par
->hw_state
.cr39
);
457 i810_writeb(CR_INDEX_CGA
, mmio
, CR41
);
458 i810_writeb(CR_DATA_CGA
, mmio
, par
->hw_state
.cr39
);
460 /*restore interlace*/
461 i810_writeb(CR_INDEX_CGA
, mmio
, CR70
);
462 i
= par
->hw_state
.cr70
;
464 j
= i810_readb(CR_DATA_CGA
, mmio
);
465 i810_writeb(CR_INDEX_CGA
, mmio
, CR70
);
466 i810_writeb(CR_DATA_CGA
, mmio
, j
| i
);
468 i810_writeb(CR_INDEX_CGA
, mmio
, CR80
);
469 i810_writeb(CR_DATA_CGA
, mmio
, par
->hw_state
.cr80
);
470 i810_writeb(MSR_WRITE
, mmio
, par
->hw_state
.msr
);
471 i810_writeb(SR_INDEX
, mmio
, SR01
);
472 i
= (par
->hw_state
.sr01
) & ~0xE0 ;
473 j
= i810_readb(SR_DATA
, mmio
) & 0xE0;
474 i810_writeb(SR_INDEX
, mmio
, SR01
);
475 i810_writeb(SR_DATA
, mmio
, i
| j
);
478 static void i810_restore_vga(struct i810fb_par
*par
)
480 u8 i
, *mmio
= par
->mmio_start_virtual
;
482 for (i
= 0; i
< 10; i
++) {
483 i810_writeb(CR_INDEX_CGA
, mmio
, CR00
+ i
);
484 i810_writeb(CR_DATA_CGA
, mmio
, *((&par
->hw_state
.cr00
) + i
));
486 for (i
= 0; i
< 8; i
++) {
487 i810_writeb(CR_INDEX_CGA
, mmio
, CR10
+ i
);
488 i810_writeb(CR_DATA_CGA
, mmio
, *((&par
->hw_state
.cr10
) + i
));
492 static void i810_restore_addr_map(struct i810fb_par
*par
)
494 u8 tmp
, *mmio
= par
->mmio_start_virtual
;
496 i810_writeb(GR_INDEX
, mmio
, GR10
);
497 tmp
= i810_readb(GR_DATA
, mmio
);
498 tmp
&= ADDR_MAP_MASK
;
499 tmp
|= par
->hw_state
.gr10
;
500 i810_writeb(GR_INDEX
, mmio
, GR10
);
501 i810_writeb(GR_DATA
, mmio
, tmp
);
504 static void i810_restore_2d(struct i810fb_par
*par
)
508 u8
*mmio
= par
->mmio_start_virtual
;
510 tmp_word
= i810_readw(BLTCNTL
, mmio
);
511 tmp_word
&= ~(3 << 4);
512 tmp_word
|= par
->hw_state
.bltcntl
;
513 i810_writew(BLTCNTL
, mmio
, tmp_word
);
515 i810_dram_off(mmio
, OFF
);
516 i810_writel(PIXCONF
, mmio
, par
->hw_state
.pixconf
);
517 i810_dram_off(mmio
, ON
);
519 tmp_word
= i810_readw(HWSTAM
, mmio
);
521 tmp_word
|= par
->hw_state
.hwstam
;
522 i810_writew(HWSTAM
, mmio
, tmp_word
);
524 tmp_long
= i810_readl(FW_BLC
, mmio
);
525 tmp_long
&= FW_BLC_MASK
;
526 tmp_long
|= par
->hw_state
.fw_blc
;
527 i810_writel(FW_BLC
, mmio
, tmp_long
);
529 i810_writel(HWS_PGA
, mmio
, par
->hw_state
.hws_pga
);
530 i810_writew(IER
, mmio
, par
->hw_state
.ier
);
531 i810_writew(IMR
, mmio
, par
->hw_state
.imr
);
532 i810_writel(DPLYSTAS
, mmio
, par
->hw_state
.dplystas
);
535 static void i810_restore_vga_state(struct i810fb_par
*par
)
537 u8
*mmio
= par
->mmio_start_virtual
;
539 i810_screen_off(mmio
, OFF
);
540 i810_protect_regs(mmio
, OFF
);
541 i810_dram_off(mmio
, OFF
);
542 i810_restore_pll(par
);
543 i810_restore_dac(par
);
544 i810_restore_vga(par
);
545 i810_restore_vgax(par
);
546 i810_restore_addr_map(par
);
547 i810_dram_off(mmio
, ON
);
548 i810_restore_2d(par
);
549 i810_screen_off(mmio
, ON
);
550 i810_protect_regs(mmio
, ON
);
553 /***********************************************************************
555 ***********************************************************************/
557 static void i810_save_vgax(struct i810fb_par
*par
)
559 u8 i
, *mmio
= par
->mmio_start_virtual
;
561 for (i
= 0; i
< 4; i
++) {
562 i810_writeb(CR_INDEX_CGA
, mmio
, CR30
+ i
);
563 *(&(par
->hw_state
.cr30
) + i
) = i810_readb(CR_DATA_CGA
, mmio
);
565 i810_writeb(CR_INDEX_CGA
, mmio
, CR35
);
566 par
->hw_state
.cr35
= i810_readb(CR_DATA_CGA
, mmio
);
567 i810_writeb(CR_INDEX_CGA
, mmio
, CR39
);
568 par
->hw_state
.cr39
= i810_readb(CR_DATA_CGA
, mmio
);
569 i810_writeb(CR_INDEX_CGA
, mmio
, CR41
);
570 par
->hw_state
.cr41
= i810_readb(CR_DATA_CGA
, mmio
);
571 i810_writeb(CR_INDEX_CGA
, mmio
, CR70
);
572 par
->hw_state
.cr70
= i810_readb(CR_DATA_CGA
, mmio
);
573 par
->hw_state
.msr
= i810_readb(MSR_READ
, mmio
);
574 i810_writeb(CR_INDEX_CGA
, mmio
, CR80
);
575 par
->hw_state
.cr80
= i810_readb(CR_DATA_CGA
, mmio
);
576 i810_writeb(SR_INDEX
, mmio
, SR01
);
577 par
->hw_state
.sr01
= i810_readb(SR_DATA
, mmio
);
580 static void i810_save_vga(struct i810fb_par
*par
)
582 u8 i
, *mmio
= par
->mmio_start_virtual
;
584 for (i
= 0; i
< 10; i
++) {
585 i810_writeb(CR_INDEX_CGA
, mmio
, CR00
+ i
);
586 *((&par
->hw_state
.cr00
) + i
) = i810_readb(CR_DATA_CGA
, mmio
);
588 for (i
= 0; i
< 8; i
++) {
589 i810_writeb(CR_INDEX_CGA
, mmio
, CR10
+ i
);
590 *((&par
->hw_state
.cr10
) + i
) = i810_readb(CR_DATA_CGA
, mmio
);
594 static void i810_save_2d(struct i810fb_par
*par
)
596 u8
*mmio
= par
->mmio_start_virtual
;
598 par
->hw_state
.dclk_2d
= i810_readl(DCLK_2D
, mmio
);
599 par
->hw_state
.dclk_1d
= i810_readl(DCLK_1D
, mmio
);
600 par
->hw_state
.dclk_0ds
= i810_readl(DCLK_0DS
, mmio
);
601 par
->hw_state
.pixconf
= i810_readl(PIXCONF
, mmio
);
602 par
->hw_state
.fw_blc
= i810_readl(FW_BLC
, mmio
);
603 par
->hw_state
.bltcntl
= i810_readw(BLTCNTL
, mmio
);
604 par
->hw_state
.hwstam
= i810_readw(HWSTAM
, mmio
);
605 par
->hw_state
.hws_pga
= i810_readl(HWS_PGA
, mmio
);
606 par
->hw_state
.ier
= i810_readw(IER
, mmio
);
607 par
->hw_state
.imr
= i810_readw(IMR
, mmio
);
608 par
->hw_state
.dplystas
= i810_readl(DPLYSTAS
, mmio
);
611 static void i810_save_vga_state(struct i810fb_par
*par
)
618 /************************************************************
620 ************************************************************/
622 * get_line_length - calculates buffer pitch in bytes
623 * @par: pointer to i810fb_par structure
624 * @xres_virtual: virtual resolution of the frame
625 * @bpp: bits per pixel
628 * Calculates buffer pitch in bytes.
630 u32
get_line_length(struct i810fb_par
*par
, int xres_virtual
, int bpp
)
634 length
= xres_virtual
*bpp
;
635 length
= (length
+31)&-32;
641 * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value
642 * @freq: target pixelclock in picoseconds
643 * @m: where to write M register
644 * @n: where to write N register
645 * @p: where to write P register
648 * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P)
649 * Repeatedly computes the Freq until the actual Freq is equal to
650 * the target Freq or until the loop count is zero. In the latter
651 * case, the actual frequency nearest the target will be used.
653 static void i810_calc_dclk(u32 freq
, u32
*m
, u32
*n
, u32
*p
)
655 u32 m_reg
, n_reg
, p_divisor
, n_target_max
;
656 u32 m_target
, n_target
, p_target
, n_best
, m_best
, mod
;
657 u32 f_out
, target_freq
, diff
= 0, mod_min
, diff_min
;
659 diff_min
= mod_min
= 0xFFFFFFFF;
660 n_best
= m_best
= m_target
= f_out
= 0;
666 * find P such that target freq is 16x reference freq (Hz).
670 while(!((1000000 * p_divisor
)/(16 * 24 * target_freq
)) &&
676 n_reg
= m_reg
= n_target
= 3;
677 while (diff_min
&& mod_min
&& (n_target
< n_target_max
)) {
678 f_out
= (p_divisor
* n_reg
* 1000000)/(4 * 24 * m_reg
);
679 mod
= (p_divisor
* n_reg
* 1000000) % (4 * 24 * m_reg
);
682 if (f_out
<= target_freq
) {
684 diff
= target_freq
- f_out
;
687 diff
= f_out
- target_freq
;
690 if (diff_min
> diff
) {
696 if (!diff
&& mod_min
> mod
) {
702 if (m
) *m
= (m_best
- 2) & 0x3FF;
703 if (n
) *n
= (n_best
- 2) & 0x3FF;
704 if (p
) *p
= (p_target
<< 4);
707 /*************************************************************
708 * Hardware Cursor Routines *
709 *************************************************************/
712 * i810_enable_cursor - show or hide the hardware cursor
713 * @mmio: address of register space
714 * @mode: show (1) or hide (0)
717 * Shows or hides the hardware cursor
719 void i810_enable_cursor(u8
*mmio
, int mode
)
723 temp
= i810_readl(PIXCONF
, mmio
);
724 temp
= (mode
== ON
) ? temp
| CURSOR_ENABLE_MASK
:
725 temp
& ~CURSOR_ENABLE_MASK
;
727 i810_writel(PIXCONF
, mmio
, temp
);
730 static void i810_reset_cursor_image(struct i810fb_par
*par
)
732 u8
*addr
= par
->cursor_heap
.virtual;
735 for (i
= 64; i
--; ) {
736 for (j
= 0; j
< 8; j
++) {
737 i810_writeb(j
, addr
, 0xff);
738 i810_writeb(j
+8, addr
, 0x00);
744 static void i810_load_cursor_image(int width
, int height
, u8
*data
,
745 struct i810fb_par
*par
)
747 u8
*addr
= par
->cursor_heap
.virtual;
748 int i
, j
, w
= width
/8;
749 int mod
= width
% 8, t_mask
, d_mask
;
751 t_mask
= 0xff >> mod
;
752 d_mask
= ~(0xff >> mod
);
753 for (i
= height
; i
--; ) {
754 for (j
= 0; j
< w
; j
++) {
755 i810_writeb(j
+0, addr
, 0x00);
756 i810_writeb(j
+8, addr
, *data
++);
759 i810_writeb(j
+0, addr
, t_mask
);
760 i810_writeb(j
+8, addr
, *data
++ & d_mask
);
766 static void i810_load_cursor_colors(int fg
, int bg
, struct fb_info
*info
)
768 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
769 u8
*mmio
= par
->mmio_start_virtual
, temp
;
770 u8 red
, green
, blue
, trans
;
772 i810fb_getcolreg(bg
, &red
, &green
, &blue
, &trans
, info
);
774 temp
= i810_readb(PIXCONF1
, mmio
);
775 i810_writeb(PIXCONF1
, mmio
, temp
| EXTENDED_PALETTE
);
777 i810_write_dac(4, red
, green
, blue
, mmio
);
779 i810_writeb(PIXCONF1
, mmio
, temp
);
781 i810fb_getcolreg(fg
, &red
, &green
, &blue
, &trans
, info
);
782 temp
= i810_readb(PIXCONF1
, mmio
);
783 i810_writeb(PIXCONF1
, mmio
, temp
| EXTENDED_PALETTE
);
785 i810_write_dac(5, red
, green
, blue
, mmio
);
787 i810_writeb(PIXCONF1
, mmio
, temp
);
791 * i810_init_cursor - initializes the cursor
792 * @par: pointer to i810fb_par structure
795 * Initializes the cursor registers
797 static void i810_init_cursor(struct i810fb_par
*par
)
799 u8
*mmio
= par
->mmio_start_virtual
;
801 i810_enable_cursor(mmio
, OFF
);
802 i810_writel(CURBASE
, mmio
, par
->cursor_heap
.physical
);
803 i810_writew(CURCNTR
, mmio
, COORD_ACTIVE
| CURSOR_MODE_64_XOR
);
806 /*********************************************************************
807 * Framebuffer hook helpers *
808 *********************************************************************/
810 * i810_round_off - Round off values to capability of hardware
811 * @var: pointer to fb_var_screeninfo structure
814 * @var contains user-defined information for the mode to be set.
815 * This will try modify those values to ones nearest the
816 * capability of the hardware
818 static void i810_round_off(struct fb_var_screeninfo
*var
)
820 u32 xres
, yres
, vxres
, vyres
;
823 * Presently supports only these configurations
828 vxres
= var
->xres_virtual
;
829 vyres
= var
->yres_virtual
;
831 var
->bits_per_pixel
+= 7;
832 var
->bits_per_pixel
&= ~7;
834 if (var
->bits_per_pixel
< 8)
835 var
->bits_per_pixel
= 8;
836 if (var
->bits_per_pixel
> 32)
837 var
->bits_per_pixel
= 32;
839 round_off_xres(&xres
);
844 xres
= (xres
+ 7) & ~7;
849 round_off_yres(&xres
, &yres
);
858 if (var
->bits_per_pixel
== 32)
859 var
->accel_flags
= 0;
861 /* round of horizontal timings to nearest 8 pixels */
862 var
->left_margin
= (var
->left_margin
+ 4) & ~7;
863 var
->right_margin
= (var
->right_margin
+ 4) & ~7;
864 var
->hsync_len
= (var
->hsync_len
+ 4) & ~7;
866 if (var
->vmode
& FB_VMODE_INTERLACED
) {
867 if (!((yres
+ var
->upper_margin
+ var
->vsync_len
+
868 var
->lower_margin
) & 1))
874 var
->xres_virtual
= vxres
;
875 var
->yres_virtual
= vyres
;
879 * set_color_bitfields - sets rgba fields
880 * @var: pointer to fb_var_screeninfo
883 * The length, offset and ordering for each color field
884 * (red, green, blue) will be set as specified
887 static void set_color_bitfields(struct fb_var_screeninfo
*var
)
889 switch (var
->bits_per_pixel
) {
893 var
->green
.offset
= 0;
894 var
->green
.length
= 8;
895 var
->blue
.offset
= 0;
896 var
->blue
.length
= 8;
897 var
->transp
.offset
= 0;
898 var
->transp
.length
= 0;
901 var
->green
.length
= (var
->green
.length
== 5) ? 5 : 6;
903 var
->blue
.length
= 5;
904 var
->transp
.length
= 6 - var
->green
.length
;
905 var
->blue
.offset
= 0;
906 var
->green
.offset
= 5;
907 var
->red
.offset
= 5 + var
->green
.length
;
908 var
->transp
.offset
= (5 + var
->red
.offset
) & 15;
910 case 24: /* RGB 888 */
911 case 32: /* RGBA 8888 */
912 var
->red
.offset
= 16;
914 var
->green
.offset
= 8;
915 var
->green
.length
= 8;
916 var
->blue
.offset
= 0;
917 var
->blue
.length
= 8;
918 var
->transp
.length
= var
->bits_per_pixel
- 24;
919 var
->transp
.offset
= (var
->transp
.length
) ? 24 : 0;
922 var
->red
.msb_right
= 0;
923 var
->green
.msb_right
= 0;
924 var
->blue
.msb_right
= 0;
925 var
->transp
.msb_right
= 0;
929 * i810_check_params - check if contents in var are valid
930 * @var: pointer to fb_var_screeninfo
931 * @info: pointer to fb_info
934 * This will check if the framebuffer size is sufficient
935 * for the current mode and if the user's monitor has the
936 * required specifications to display the current mode.
938 static int i810_check_params(struct fb_var_screeninfo
*var
,
939 struct fb_info
*info
)
941 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
942 int line_length
, vidmem
;
943 u32 xres
, yres
, vxres
, vyres
;
947 vxres
= var
->xres_virtual
;
948 vyres
= var
->yres_virtual
;
953 line_length
= get_line_length(par
, vxres
,
954 var
->bits_per_pixel
);
956 vidmem
= line_length
*vyres
;
957 if (vidmem
> par
->fb
.size
) {
958 vyres
= par
->fb
.size
/line_length
;
961 vxres
= par
->fb
.size
/vyres
;
962 vxres
/= var
->bits_per_pixel
>> 3;
963 line_length
= get_line_length(par
, vxres
,
964 var
->bits_per_pixel
);
965 vidmem
= line_length
* yres
;
967 printk("i810fb: required video memory, "
968 "%d bytes, for %dx%d-%d (virtual) "
970 vidmem
, vxres
, vyres
,
971 var
->bits_per_pixel
);
979 switch (var
->bits_per_pixel
) {
981 info
->monspecs
.dclkmax
= 234000000;
984 info
->monspecs
.dclkmax
= 229000000;
988 info
->monspecs
.dclkmax
= 204000000;
991 info
->monspecs
.dclkmin
= 15000000;
993 if (fb_validate_mode(var
, info
)) {
994 if (fb_get_mode(FB_MAXTIMINGS
, 0, var
, info
))
1000 var
->xres_virtual
= vxres
;
1001 var
->yres_virtual
= vyres
;
1006 * encode_fix - fill up fb_fix_screeninfo structure
1007 * @fix: pointer to fb_fix_screeninfo
1008 * @info: pointer to fb_info
1011 * This will set up parameters that are unmodifiable by the user.
1013 static int encode_fix(struct fb_fix_screeninfo
*fix
, struct fb_info
*info
)
1015 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1017 memset(fix
, 0, sizeof(struct fb_fix_screeninfo
));
1019 strcpy(fix
->id
, "I810");
1020 fix
->smem_start
= par
->fb
.physical
;
1021 fix
->smem_len
= par
->fb
.size
;
1022 fix
->type
= FB_TYPE_PACKED_PIXELS
;
1027 switch (info
->var
.bits_per_pixel
) {
1029 fix
->visual
= FB_VISUAL_PSEUDOCOLOR
;
1034 if (info
->var
.nonstd
)
1035 fix
->visual
= FB_VISUAL_DIRECTCOLOR
;
1037 fix
->visual
= FB_VISUAL_TRUECOLOR
;
1043 fix
->line_length
= par
->pitch
;
1044 fix
->mmio_start
= par
->mmio_start_phys
;
1045 fix
->mmio_len
= MMIO_SIZE
;
1046 fix
->accel
= FB_ACCEL_I810
;
1052 * decode_var - modify par according to contents of var
1053 * @var: pointer to fb_var_screeninfo
1054 * @par: pointer to i810fb_par
1057 * Based on the contents of @var, @par will be dynamically filled up.
1058 * @par contains all information necessary to modify the hardware.
1060 static void decode_var(const struct fb_var_screeninfo
*var
,
1061 struct i810fb_par
*par
)
1063 u32 xres
, yres
, vxres
, vyres
;
1067 vxres
= var
->xres_virtual
;
1068 vyres
= var
->yres_virtual
;
1070 switch (var
->bits_per_pixel
) {
1072 par
->pixconf
= PIXCONF8
;
1075 par
->blit_bpp
= BPP8
;
1078 if (var
->green
.length
== 5)
1079 par
->pixconf
= PIXCONF15
;
1081 par
->pixconf
= PIXCONF16
;
1084 par
->blit_bpp
= BPP16
;
1087 par
->pixconf
= PIXCONF24
;
1090 par
->blit_bpp
= BPP24
;
1093 par
->pixconf
= PIXCONF32
;
1096 par
->blit_bpp
= 3 << 24;
1099 if (var
->nonstd
&& var
->bits_per_pixel
!= 8)
1100 par
->pixconf
|= 1 << 27;
1102 i810_calc_dclk(var
->pixclock
, &par
->regs
.M
,
1103 &par
->regs
.N
, &par
->regs
.P
);
1104 i810fb_encode_registers(var
, par
, xres
, yres
);
1106 par
->watermark
= i810_get_watermark(var
, par
);
1107 par
->pitch
= get_line_length(par
, vxres
, var
->bits_per_pixel
);
1111 * i810fb_getcolreg - gets red, green and blue values of the hardware DAC
1116 * @transp: transparency (alpha)
1117 * @info: pointer to fb_info
1120 * Gets the red, green and blue values of the hardware DAC as pointed by @regno
1121 * and writes them to @red, @green and @blue respectively
1123 static int i810fb_getcolreg(u8 regno
, u8
*red
, u8
*green
, u8
*blue
,
1124 u8
*transp
, struct fb_info
*info
)
1126 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1127 u8
*mmio
= par
->mmio_start_virtual
, temp
;
1129 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
1130 if ((info
->var
.green
.length
== 5 && regno
> 31) ||
1131 (info
->var
.green
.length
== 6 && regno
> 63))
1135 temp
= i810_readb(PIXCONF1
, mmio
);
1136 i810_writeb(PIXCONF1
, mmio
, temp
& ~EXTENDED_PALETTE
);
1138 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
&&
1139 info
->var
.green
.length
== 5)
1140 i810_read_dac(regno
* 8, red
, green
, blue
, mmio
);
1142 else if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
&&
1143 info
->var
.green
.length
== 6) {
1146 i810_read_dac(regno
* 8, red
, &tmp
, blue
, mmio
);
1147 i810_read_dac(regno
* 4, &tmp
, green
, &tmp
, mmio
);
1150 i810_read_dac(regno
, red
, green
, blue
, mmio
);
1153 i810_writeb(PIXCONF1
, mmio
, temp
);
1158 /******************************************************************
1159 * Framebuffer device-specific hooks *
1160 ******************************************************************/
1162 static int i810fb_open(struct fb_info
*info
, int user
)
1164 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1165 u32 count
= atomic_read(&par
->use_count
);
1168 memset(&par
->state
, 0, sizeof(struct vgastate
));
1169 par
->state
.flags
= VGA_SAVE_CMAP
;
1170 par
->state
.vgabase
= (caddr_t
) par
->mmio_start_virtual
;
1171 save_vga(&par
->state
);
1173 i810_save_vga_state(par
);
1176 atomic_inc(&par
->use_count
);
1181 static int i810fb_release(struct fb_info
*info
, int user
)
1183 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1186 count
= atomic_read(&par
->use_count
);
1191 i810_restore_vga_state(par
);
1192 restore_vga(&par
->state
);
1195 atomic_dec(&par
->use_count
);
1201 static int i810fb_setcolreg(unsigned regno
, unsigned red
, unsigned green
,
1202 unsigned blue
, unsigned transp
,
1203 struct fb_info
*info
)
1205 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1206 u8
*mmio
= par
->mmio_start_virtual
, temp
;
1209 if (regno
> 255) return 1;
1211 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
1212 if ((info
->var
.green
.length
== 5 && regno
> 31) ||
1213 (info
->var
.green
.length
== 6 && regno
> 63))
1217 if (info
->var
.grayscale
)
1218 red
= green
= blue
= (19595 * red
+ 38470 * green
+
1221 temp
= i810_readb(PIXCONF1
, mmio
);
1222 i810_writeb(PIXCONF1
, mmio
, temp
& ~EXTENDED_PALETTE
);
1224 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
&&
1225 info
->var
.green
.length
== 5) {
1226 for (i
= 0; i
< 8; i
++)
1227 i810_write_dac((u8
) (regno
* 8) + i
, (u8
) red
,
1228 (u8
) green
, (u8
) blue
, mmio
);
1229 } else if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
&&
1230 info
->var
.green
.length
== 6) {
1234 for (i
= 0; i
< 8; i
++)
1235 i810_write_dac((u8
) (regno
* 8) + i
,
1236 (u8
) red
, (u8
) green
,
1239 i810_read_dac((u8
) (regno
*4), &r
, &g
, &b
, mmio
);
1240 for (i
= 0; i
< 4; i
++)
1241 i810_write_dac((u8
) (regno
*4) + i
, r
, (u8
) green
,
1243 } else if (info
->fix
.visual
== FB_VISUAL_PSEUDOCOLOR
) {
1244 i810_write_dac((u8
) regno
, (u8
) red
, (u8
) green
,
1248 i810_writeb(PIXCONF1
, mmio
, temp
);
1251 switch (info
->var
.bits_per_pixel
) {
1253 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
) {
1254 if (info
->var
.green
.length
== 5)
1255 ((u32
*)info
->pseudo_palette
)[regno
] =
1256 (regno
<< 10) | (regno
<< 5) |
1259 ((u32
*)info
->pseudo_palette
)[regno
] =
1260 (regno
<< 11) | (regno
<< 5) |
1263 if (info
->var
.green
.length
== 5) {
1265 ((u32
*)info
->pseudo_palette
)[regno
] =
1266 ((red
& 0xf800) >> 1) |
1267 ((green
& 0xf800) >> 6) |
1268 ((blue
& 0xf800) >> 11);
1271 ((u32
*)info
->pseudo_palette
)[regno
] =
1273 ((green
& 0xf800) >> 5) |
1274 ((blue
& 0xf800) >> 11);
1278 case 24: /* RGB 888 */
1279 case 32: /* RGBA 8888 */
1280 if (info
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
1281 ((u32
*)info
->pseudo_palette
)[regno
] =
1282 (regno
<< 16) | (regno
<< 8) |
1285 ((u32
*)info
->pseudo_palette
)[regno
] =
1286 ((red
& 0xff00) << 8) |
1288 ((blue
& 0xff00) >> 8);
1295 static int i810fb_pan_display(struct fb_var_screeninfo
*var
,
1296 struct fb_info
*info
)
1298 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1301 total
= var
->xoffset
* par
->depth
+
1302 var
->yoffset
* info
->fix
.line_length
;
1303 i810fb_load_front(total
, info
);
1308 static int i810fb_blank (int blank_mode
, struct fb_info
*info
)
1310 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1311 u8
*mmio
= par
->mmio_start_virtual
;
1312 int mode
= 0, pwr
, scr_off
= 0;
1314 pwr
= i810_readl(PWR_CLKC
, mmio
);
1316 switch(blank_mode
) {
1317 case VESA_NO_BLANKING
:
1322 case VESA_VSYNC_SUSPEND
:
1327 case VESA_HSYNC_SUSPEND
:
1332 case VESA_POWERDOWN
:
1340 i810_screen_off(mmio
, scr_off
);
1341 i810_writel(HVSYNC
, mmio
, mode
);
1342 i810_writel(PWR_CLKC
, mmio
, pwr
);
1346 static int i810fb_set_par(struct fb_info
*info
)
1348 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1350 decode_var(&info
->var
, par
);
1351 i810_load_regs(par
);
1352 i810_init_cursor(par
);
1354 encode_fix(&info
->fix
, info
);
1356 if (info
->var
.accel_flags
&& !(par
->dev_flags
& LOCKUP
)) {
1357 info
->flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_YPAN
|
1358 FBINFO_HWACCEL_COPYAREA
| FBINFO_HWACCEL_FILLRECT
|
1359 FBINFO_HWACCEL_IMAGEBLIT
;
1360 info
->pixmap
.scan_align
= 2;
1362 info
->pixmap
.scan_align
= 1;
1363 info
->flags
= FBINFO_DEFAULT
| FBINFO_HWACCEL_YPAN
;
1368 static int i810fb_check_var(struct fb_var_screeninfo
*var
,
1369 struct fb_info
*info
)
1374 var
->vmode
&= ~FB_VMODE_MASK
;
1375 var
->vmode
|= FB_VMODE_NONINTERLACED
;
1377 if (var
->vmode
& FB_VMODE_DOUBLE
) {
1378 var
->vmode
&= ~FB_VMODE_MASK
;
1379 var
->vmode
|= FB_VMODE_NONINTERLACED
;
1382 i810_round_off(var
);
1383 if ((err
= i810_check_params(var
, info
)))
1386 i810fb_fill_var_timings(var
);
1387 set_color_bitfields(var
);
1391 static int i810fb_cursor(struct fb_info
*info
, struct fb_cursor
*cursor
)
1393 struct i810fb_par
*par
= (struct i810fb_par
*)info
->par
;
1394 u8
*mmio
= par
->mmio_start_virtual
;
1396 if (!info
->var
.accel_flags
|| par
->dev_flags
& LOCKUP
)
1397 return soft_cursor(info
, cursor
);
1399 if (cursor
->image
.width
> 64 || cursor
->image
.height
> 64)
1402 if ((i810_readl(CURBASE
, mmio
) & 0xf) != par
->cursor_heap
.physical
) {
1403 i810_init_cursor(par
);
1404 cursor
->set
|= FB_CUR_SETALL
;
1407 i810_enable_cursor(mmio
, OFF
);
1409 if (cursor
->set
& FB_CUR_SETHOT
)
1410 info
->cursor
.hot
= cursor
->hot
;
1412 if (cursor
->set
& FB_CUR_SETPOS
) {
1415 info
->cursor
.image
.dx
= cursor
->image
.dx
;
1416 info
->cursor
.image
.dy
= cursor
->image
.dy
;
1417 tmp
= (info
->cursor
.image
.dx
- info
->var
.xoffset
) & 0xffff;
1418 tmp
|= (info
->cursor
.image
.dy
- info
->var
.yoffset
) << 16;
1419 i810_writel(CURPOS
, mmio
, tmp
);
1422 if (cursor
->set
& FB_CUR_SETSIZE
) {
1423 i810_reset_cursor_image(par
);
1424 info
->cursor
.image
.height
= cursor
->image
.height
;
1425 info
->cursor
.image
.width
= cursor
->image
.width
;
1428 if (cursor
->set
& FB_CUR_SETCMAP
) {
1429 i810_load_cursor_colors(cursor
->image
.fg_color
,
1430 cursor
->image
.bg_color
,
1432 info
->cursor
.image
.fg_color
= cursor
->image
.fg_color
;
1433 info
->cursor
.image
.bg_color
= cursor
->image
.bg_color
;
1437 if (cursor
->set
& (FB_CUR_SETSHAPE
)) {
1438 int size
= ((info
->cursor
.image
.width
+ 7) >> 3) *
1439 info
->cursor
.image
.height
;
1441 u8
*data
= kmalloc(64 * 8, GFP_KERNEL
);
1445 info
->cursor
.image
.data
= cursor
->image
.data
;
1447 switch (info
->cursor
.rop
) {
1449 for (i
= 0; i
< size
; i
++)
1450 data
[i
] = info
->cursor
.image
.data
[i
] ^ info
->cursor
.mask
[i
];
1454 for (i
= 0; i
< size
; i
++)
1455 data
[i
] = info
->cursor
.image
.data
[i
] & info
->cursor
.mask
[i
];
1458 i810_load_cursor_image(info
->cursor
.image
.width
,
1459 info
->cursor
.image
.height
, data
,
1464 if (info
->cursor
.enable
)
1465 i810_enable_cursor(mmio
, ON
);
1470 static struct fb_ops i810fb_ops __devinitdata
= {
1471 .owner
= THIS_MODULE
,
1472 .fb_open
= i810fb_open
,
1473 .fb_release
= i810fb_release
,
1474 .fb_check_var
= i810fb_check_var
,
1475 .fb_set_par
= i810fb_set_par
,
1476 .fb_setcolreg
= i810fb_setcolreg
,
1477 .fb_blank
= i810fb_blank
,
1478 .fb_pan_display
= i810fb_pan_display
,
1479 .fb_fillrect
= i810fb_fillrect
,
1480 .fb_copyarea
= i810fb_copyarea
,
1481 .fb_imageblit
= i810fb_imageblit
,
1482 .fb_cursor
= i810fb_cursor
,
1483 .fb_sync
= i810fb_sync
,
1486 /***********************************************************************
1487 * Power Management *
1488 ***********************************************************************/
1489 static int i810fb_suspend(struct pci_dev
*dev
, u32 state
)
1491 struct fb_info
*info
= pci_get_drvdata(dev
);
1492 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1493 int blank
= 0, prev_state
= par
->cur_state
;
1495 if (state
== prev_state
)
1498 par
->cur_state
= state
;
1502 blank
= VESA_VSYNC_SUSPEND
;
1505 blank
= VESA_HSYNC_SUSPEND
;
1508 blank
= VESA_POWERDOWN
;
1513 info
->fbops
->fb_blank(blank
, info
);
1516 par
->drm_agp
->unbind_memory(par
->i810_gtt
.i810_fb_memory
);
1517 par
->drm_agp
->unbind_memory(par
->i810_gtt
.i810_cursor_memory
);
1518 pci_disable_device(dev
);
1520 pci_save_state(dev
, par
->pci_state
);
1521 pci_set_power_state(dev
, state
);
1526 static int i810fb_resume(struct pci_dev
*dev
)
1528 struct fb_info
*info
= pci_get_drvdata(dev
);
1529 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1531 if (par
->cur_state
== 0)
1534 pci_restore_state(dev
, par
->pci_state
);
1535 pci_set_power_state(dev
, 0);
1536 pci_enable_device(dev
);
1537 par
->drm_agp
->bind_memory(par
->i810_gtt
.i810_fb_memory
,
1539 par
->drm_agp
->bind_memory(par
->i810_gtt
.i810_cursor_memory
,
1540 par
->cursor_heap
.offset
);
1542 info
->fbops
->fb_blank(VESA_NO_BLANKING
, info
);
1548 /***********************************************************************
1549 * AGP resource allocation *
1550 ***********************************************************************/
1552 static void __devinit
i810_fix_pointers(struct i810fb_par
*par
)
1554 par
->fb
.physical
= par
->aperture
.physical
+(par
->fb
.offset
<< 12);
1555 par
->fb
.virtual = par
->aperture
.virtual+(par
->fb
.offset
<< 12);
1556 par
->iring
.physical
= par
->aperture
.physical
+
1557 (par
->iring
.offset
<< 12);
1558 par
->iring
.virtual = par
->aperture
.virtual +
1559 (par
->iring
.offset
<< 12);
1560 par
->cursor_heap
.virtual = par
->aperture
.virtual+
1561 (par
->cursor_heap
.offset
<< 12);
1564 static void __devinit
i810_fix_offsets(struct i810fb_par
*par
)
1566 if (vram
+ 1 > par
->aperture
.size
>> 20)
1567 vram
= (par
->aperture
.size
>> 20) - 1;
1568 if (v_offset_default
> (par
->aperture
.size
>> 20))
1569 v_offset_default
= (par
->aperture
.size
>> 20);
1570 if (vram
+ v_offset_default
+ 1 > par
->aperture
.size
>> 20)
1571 v_offset_default
= (par
->aperture
.size
>> 20) - (vram
+ 1);
1573 par
->fb
.size
= vram
<< 20;
1574 par
->fb
.offset
= v_offset_default
<< 20;
1575 par
->fb
.offset
>>= 12;
1577 par
->iring
.offset
= par
->fb
.offset
+ (par
->fb
.size
>> 12);
1578 par
->iring
.size
= RINGBUFFER_SIZE
;
1580 par
->cursor_heap
.offset
= par
->iring
.offset
+ (RINGBUFFER_SIZE
>> 12);
1581 par
->cursor_heap
.size
= 4096;
1584 static int __devinit
i810_alloc_agp_mem(struct fb_info
*info
)
1586 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1589 i810_fix_offsets(par
);
1590 size
= par
->fb
.size
+ par
->iring
.size
;
1592 par
->drm_agp
= (drm_agp_t
*) inter_module_get("drm_agp");
1593 if (!par
->drm_agp
) {
1594 printk("i810fb: cannot acquire agp\n");
1597 par
->drm_agp
->acquire();
1599 if (!(par
->i810_gtt
.i810_fb_memory
=
1600 par
->drm_agp
->allocate_memory(size
>> 12, AGP_NORMAL_MEMORY
))) {
1601 printk("i810fb_alloc_fbmem: can't allocate framebuffer "
1603 par
->drm_agp
->release();
1606 if (par
->drm_agp
->bind_memory(par
->i810_gtt
.i810_fb_memory
,
1608 printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
1609 par
->drm_agp
->release();
1613 if (!(par
->i810_gtt
.i810_cursor_memory
=
1614 par
->drm_agp
->allocate_memory(par
->cursor_heap
.size
>> 12,
1615 AGP_PHYSICAL_MEMORY
))) {
1616 printk("i810fb_alloc_cursormem: can't allocate"
1618 par
->drm_agp
->release();
1621 if (par
->drm_agp
->bind_memory(par
->i810_gtt
.i810_cursor_memory
,
1622 par
->cursor_heap
.offset
)) {
1623 printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
1624 par
->drm_agp
->release();
1628 par
->cursor_heap
.physical
= par
->i810_gtt
.i810_cursor_memory
->physical
;
1630 i810_fix_pointers(par
);
1632 par
->drm_agp
->release();
1637 /***************************************************************
1639 ***************************************************************/
1642 * i810_init_monspecs
1643 * @info: pointer to device specific info structure
1646 * Sets the the user monitor's horizontal and vertical
1649 static void __devinit
i810_init_monspecs(struct fb_info
*info
)
1655 if (!info
->monspecs
.hfmax
)
1656 info
->monspecs
.hfmax
= hsync2
;
1657 if (!info
->monspecs
.hfmin
)
1658 info
->monspecs
.hfmin
= hsync1
;
1659 if (hsync2
< hsync1
)
1660 info
->monspecs
.hfmin
= hsync2
;
1666 if (IS_DVT
&& vsync1
< 60)
1668 if (!info
->monspecs
.vfmax
)
1669 info
->monspecs
.vfmax
= vsync2
;
1670 if (!info
->monspecs
.vfmin
)
1671 info
->monspecs
.vfmin
= vsync1
;
1672 if (vsync2
< vsync1
)
1673 info
->monspecs
.vfmin
= vsync2
;
1677 * i810_init_defaults - initializes default values to use
1678 * @par: pointer to i810fb_par structure
1679 * @info: pointer to current fb_info structure
1681 static void __devinit
i810_init_defaults(struct i810fb_par
*par
,
1682 struct fb_info
*info
)
1685 v_offset_default
= voffset
;
1686 else if (par
->aperture
.size
> 32 * 1024 * 1024)
1687 v_offset_default
= 16;
1689 v_offset_default
= 8;
1695 par
->dev_flags
|= HAS_ACCELERATION
;
1698 par
->dev_flags
|= ALWAYS_SYNC
;
1704 vyres
= (vram
<< 20)/(xres
*bpp
>> 3);
1706 par
->i810fb_ops
= i810fb_ops
;
1707 info
->var
.xres
= xres
;
1708 info
->var
.yres
= yres
;
1709 info
->var
.yres_virtual
= vyres
;
1710 info
->var
.bits_per_pixel
= bpp
;
1713 info
->var
.nonstd
= 1;
1715 if (par
->dev_flags
& HAS_ACCELERATION
)
1716 info
->var
.accel_flags
= 1;
1718 i810_init_monspecs(info
);
1722 * i810_init_device - initialize device
1723 * @par: pointer to i810fb_par structure
1725 static void __devinit
i810_init_device(struct i810fb_par
*par
)
1727 u8 reg
, *mmio
= par
->mmio_start_virtual
;
1729 if (mtrr
) set_mtrr(par
);
1731 i810_init_cursor(par
);
1733 /* mvo: enable external vga-connector (for laptops) */
1735 i810_writel(HVSYNC
, mmio
, 0);
1736 i810_writel(PWR_CLKC
, mmio
, 3);
1739 pci_read_config_byte(par
->dev
, 0x50, ®
);
1741 par
->mem_freq
= (reg
) ? 133 : 100;
1745 static int __devinit
1746 i810_allocate_pci_resource(struct i810fb_par
*par
,
1747 const struct pci_device_id
*entry
)
1751 if ((err
= pci_enable_device(par
->dev
))) {
1752 printk("i810fb_init: cannot enable device\n");
1755 par
->res_flags
|= PCI_DEVICE_ENABLED
;
1757 if (pci_resource_len(par
->dev
, 0) > 512 * 1024) {
1758 par
->aperture
.physical
= pci_resource_start(par
->dev
, 0);
1759 par
->aperture
.size
= pci_resource_len(par
->dev
, 0);
1760 par
->mmio_start_phys
= pci_resource_start(par
->dev
, 1);
1762 par
->aperture
.physical
= pci_resource_start(par
->dev
, 1);
1763 par
->aperture
.size
= pci_resource_len(par
->dev
, 1);
1764 par
->mmio_start_phys
= pci_resource_start(par
->dev
, 0);
1766 if (!par
->aperture
.size
) {
1767 printk("i810fb_init: device is disabled\n");
1771 if (!request_mem_region(par
->aperture
.physical
,
1773 i810_pci_list
[entry
->driver_data
])) {
1774 printk("i810fb_init: cannot request framebuffer region\n");
1777 par
->res_flags
|= FRAMEBUFFER_REQ
;
1779 par
->aperture
.virtual = ioremap_nocache(par
->aperture
.physical
,
1780 par
->aperture
.size
);
1781 if (!par
->aperture
.virtual) {
1782 printk("i810fb_init: cannot remap framebuffer region\n");
1786 if (!request_mem_region(par
->mmio_start_phys
,
1788 i810_pci_list
[entry
->driver_data
])) {
1789 printk("i810fb_init: cannot request mmio region\n");
1792 par
->res_flags
|= MMIO_REQ
;
1794 par
->mmio_start_virtual
= ioremap_nocache(par
->mmio_start_phys
,
1796 if (!par
->mmio_start_virtual
) {
1797 printk("i810fb_init: cannot remap mmio region\n");
1804 int __init
i810fb_setup(char *options
)
1806 char *this_opt
, *suffix
= NULL
;
1808 if (!options
|| !*options
)
1811 while ((this_opt
= strsep(&options
, ",")) != NULL
) {
1812 if (!strncmp(this_opt
, "mtrr", 4))
1814 else if (!strncmp(this_opt
, "accel", 5))
1816 else if (!strncmp(this_opt
, "ext_vga", 7))
1818 else if (!strncmp(this_opt
, "sync", 4))
1820 else if (!strncmp(this_opt
, "vram:", 5))
1821 vram
= (simple_strtoul(this_opt
+5, NULL
, 0));
1822 else if (!strncmp(this_opt
, "voffset:", 8))
1823 voffset
= (simple_strtoul(this_opt
+8, NULL
, 0));
1824 else if (!strncmp(this_opt
, "xres:", 5))
1825 xres
= simple_strtoul(this_opt
+5, NULL
, 0);
1826 else if (!strncmp(this_opt
, "yres:", 5))
1827 yres
= simple_strtoul(this_opt
+5, NULL
, 0);
1828 else if (!strncmp(this_opt
, "vyres:", 6))
1829 vyres
= simple_strtoul(this_opt
+6, NULL
, 0);
1830 else if (!strncmp(this_opt
, "bpp:", 4))
1831 bpp
= simple_strtoul(this_opt
+4, NULL
, 0);
1832 else if (!strncmp(this_opt
, "hsync1:", 7)) {
1833 hsync1
= simple_strtoul(this_opt
+7, &suffix
, 0);
1834 if (strncmp(suffix
, "H", 1))
1836 } else if (!strncmp(this_opt
, "hsync2:", 7)) {
1837 hsync2
= simple_strtoul(this_opt
+7, &suffix
, 0);
1838 if (strncmp(suffix
, "H", 1))
1840 } else if (!strncmp(this_opt
, "vsync1:", 7))
1841 vsync1
= simple_strtoul(this_opt
+7, NULL
, 0);
1842 else if (!strncmp(this_opt
, "vsync2:", 7))
1843 vsync2
= simple_strtoul(this_opt
+7, NULL
, 0);
1844 else if (!strncmp(this_opt
, "dcolor", 6))
1850 static int __devinit
i810fb_init_pci (struct pci_dev
*dev
,
1851 const struct pci_device_id
*entry
)
1853 struct fb_info
*info
;
1854 struct i810fb_par
*par
= NULL
;
1855 int i
, err
= -1, vfreq
, hfreq
, pixclock
;
1858 if (!(info
= kmalloc(sizeof(struct fb_info
), GFP_KERNEL
))) {
1859 i810fb_release_resource(info
, par
);
1862 memset(info
, 0, sizeof(struct fb_info
));
1864 if(!(par
= kmalloc(sizeof(struct i810fb_par
), GFP_KERNEL
))) {
1865 i810fb_release_resource(info
, par
);
1868 memset(par
, 0, sizeof(struct i810fb_par
));
1873 if (!(info
->pixmap
.addr
= kmalloc(64*1024, GFP_KERNEL
))) {
1874 i810fb_release_resource(info
, par
);
1877 memset(info
->pixmap
.addr
, 0, 64*1024);
1878 info
->pixmap
.size
= 64*1024;
1879 info
->pixmap
.buf_align
= 8;
1880 info
->pixmap
.flags
= FB_PIXMAP_SYSTEM
;
1882 if ((err
= i810_allocate_pci_resource(par
, entry
))) {
1883 i810fb_release_resource(info
, par
);
1887 i810_init_defaults(par
, info
);
1889 if ((err
= i810_alloc_agp_mem(info
))) {
1890 i810fb_release_resource(info
, par
);
1894 i810_init_device(par
);
1896 info
->screen_base
= par
->fb
.virtual;
1897 info
->fbops
= &par
->i810fb_ops
;
1898 info
->pseudo_palette
= par
->pseudo_palette
;
1899 fb_alloc_cmap(&info
->cmap
, 256, 0);
1901 if ((err
= info
->fbops
->fb_check_var(&info
->var
, info
))) {
1902 i810fb_release_resource(info
, par
);
1905 encode_fix(&info
->fix
, info
);
1907 i810fb_init_ringbuffer(info
);
1908 err
= register_framebuffer(info
);
1910 i810fb_release_resource(info
, par
);
1911 printk("i810fb_init: cannot register framebuffer device\n");
1915 pci_set_drvdata(dev
, info
);
1916 pixclock
= 1000000000/(info
->var
.pixclock
);
1918 hfreq
= pixclock
/(info
->var
.xres
+ info
->var
.left_margin
+
1919 info
->var
.hsync_len
+ info
->var
.right_margin
);
1920 vfreq
= hfreq
/(info
->var
.yres
+ info
->var
.upper_margin
+
1921 info
->var
.vsync_len
+ info
->var
.lower_margin
);
1923 printk("I810FB: fb%d : %s v%d.%d.%d%s\n"
1924 "I810FB: Video RAM : %dK\n"
1925 "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n"
1926 "I810FB: Mode : %dx%d-%dbpp@%dHz\n",
1928 i810_pci_list
[entry
->driver_data
],
1929 VERSION_MAJOR
, VERSION_MINOR
, VERSION_TEENIE
, BRANCH_VERSION
,
1930 (int) par
->fb
.size
>>10, info
->monspecs
.hfmin
/1000,
1931 info
->monspecs
.hfmax
/1000, info
->monspecs
.vfmin
,
1932 info
->monspecs
.vfmax
, info
->var
.xres
,
1933 info
->var
.yres
, info
->var
.bits_per_pixel
, vfreq
);
1937 /***************************************************************
1938 * De-initialization *
1939 ***************************************************************/
1941 static void i810fb_release_resource(struct fb_info
*info
,
1942 struct i810fb_par
*par
)
1947 drm_agp_t
*agp
= par
->drm_agp
;
1948 struct gtt_data
*gtt
= &par
->i810_gtt
;
1950 if (par
->i810_gtt
.i810_cursor_memory
)
1951 agp
->free_memory(gtt
->i810_cursor_memory
);
1952 if (par
->i810_gtt
.i810_fb_memory
)
1953 agp
->free_memory(gtt
->i810_fb_memory
);
1955 inter_module_put("drm_agp");
1956 par
->drm_agp
= NULL
;
1959 if (par
->mmio_start_virtual
)
1960 iounmap(par
->mmio_start_virtual
);
1961 if (par
->aperture
.virtual)
1962 iounmap(par
->aperture
.virtual);
1964 if (par
->res_flags
& FRAMEBUFFER_REQ
)
1965 release_mem_region(par
->aperture
.physical
,
1966 par
->aperture
.size
);
1967 if (par
->res_flags
& MMIO_REQ
)
1968 release_mem_region(par
->mmio_start_phys
, MMIO_SIZE
);
1970 if (par
->res_flags
& PCI_DEVICE_ENABLED
)
1971 pci_disable_device(par
->dev
);
1978 static void __exit
i810fb_remove_pci(struct pci_dev
*dev
)
1980 struct fb_info
*info
= pci_get_drvdata(dev
);
1981 struct i810fb_par
*par
= (struct i810fb_par
*) info
->par
;
1983 unregister_framebuffer(info
);
1984 i810fb_release_resource(info
, par
);
1985 pci_set_drvdata(dev
, NULL
);
1986 printk("cleanup_module: unloaded i810 framebuffer device\n");
1990 int __init
i810fb_init(void)
1992 char *option
= NULL
;
1994 if (fb_get_options("i810fb", &option
))
1996 i810fb_setup(option
);
1998 if (pci_register_driver(&i810fb_driver
) > 0)
2000 pci_unregister_driver(&i810fb_driver
);
2005 /*********************************************************************
2007 *********************************************************************/
2011 int __init
i810fb_init(void)
2016 if (pci_register_driver(&i810fb_driver
) > 0)
2018 pci_unregister_driver(&i810fb_driver
);
2022 MODULE_PARM(vram
, "i");
2023 MODULE_PARM_DESC(vram
, "System RAM to allocate to framebuffer in MiB"
2025 MODULE_PARM(voffset
, "i");
2026 MODULE_PARM_DESC(voffset
, "at what offset to place start of framebuffer "
2027 "memory (0 to maximum aperture size), in MiB (default = 48)");
2028 MODULE_PARM(bpp
, "i");
2029 MODULE_PARM_DESC(bpp
, "Color depth for display in bits per pixel"
2031 MODULE_PARM(xres
, "i");
2032 MODULE_PARM_DESC(xres
, "Horizontal resolution in pixels (default = 640)");
2033 MODULE_PARM(yres
, "i");
2034 MODULE_PARM_DESC(yres
, "Vertical resolution in scanlines (default = 480)");
2035 MODULE_PARM(vyres
, "i");
2036 MODULE_PARM_DESC(vyres
, "Virtual vertical resolution in scanlines"
2037 " (default = 480)");
2038 MODULE_PARM(hsync1
, "i");
2039 MODULE_PARM_DESC(hsync1
, "Minimum horizontal frequency of monitor in KHz"
2041 MODULE_PARM(hsync2
, "i");
2042 MODULE_PARM_DESC(hsync2
, "Maximum horizontal frequency of monitor in KHz"
2044 MODULE_PARM(vsync1
, "i");
2045 MODULE_PARM_DESC(vsync1
, "Minimum vertical frequency of monitor in Hz"
2047 MODULE_PARM(vsync2
, "i");
2048 MODULE_PARM_DESC(vsync2
, "Maximum vertical frequency of monitor in Hz"
2050 MODULE_PARM(accel
, "i");
2051 MODULE_PARM_DESC(accel
, "Use Acceleration (BLIT) engine (default = 0)");
2052 MODULE_PARM(mtrr
, "i");
2053 MODULE_PARM_DESC(mtrr
, "Use MTRR (default = 0)");
2054 MODULE_PARM(ext_vga
, "i");
2055 MODULE_PARM_DESC(ext_vga
, "Enable external VGA connector (default = 0)");
2056 MODULE_PARM(sync
, "i");
2057 MODULE_PARM_DESC(sync
, "wait for accel engine to finish drawing"
2059 MODULE_PARM(dcolor
, "i");
2060 MODULE_PARM_DESC(dcolor
, "use DirectColor visuals"
2061 " (default = 0 = TrueColor)");
2063 MODULE_AUTHOR("Tony A. Daplas");
2064 MODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and"
2065 " compatible cards");
2066 MODULE_LICENSE("GPL");
2068 static void __exit
i810fb_exit(void)
2070 pci_unregister_driver(&i810fb_driver
);
2072 module_exit(i810fb_exit
);
2076 module_init(i810fb_init
);