1 /* all driver need this */
2 #ifdef HAVE_XORG_CONFIG_H
3 #include <xorg-config.h>
9 #include "xf86_OSproc.h"
12 #include "xf86PciInfo.h"
21 /* kernel header doesn't work with -ansi */
22 # include "asm/page.h" /* #define for PAGE_* */
24 # define PAGE_MASK (~(getpagesize() - 1))
29 #include <X11/extensions/dpms.h>
33 #define PAGE_MASK (~(getpagesize() - 1))
36 # define TRACE_ENTER(str) ErrorF("fbdevHW: " str " %d\n",pScrn->scrnIndex)
38 # define TRACE_ENTER(str)
41 /* -------------------------------------------------------------------- */
43 static MODULESETUPPROTO(fbdevhwSetup
);
45 static XF86ModuleVersionInfo fbdevHWVersRec
=
59 _X_EXPORT XF86ModuleData fbdevhwModuleData
= {
66 fbdevhwSetup(pointer module
, pointer opts
, int *errmaj
, int *errmin
)
70 /* Check that we're being loaded on a Linux system */
71 LoaderGetOS(&osname
, NULL
, NULL
, NULL
);
72 if (!osname
|| strcmp(osname
, "linux") != 0) {
87 #include <sys/ioctl.h>
93 /* -------------------------------------------------------------------- */
94 /* our private data, and two functions to allocate/free this */
96 #define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr
97 #define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p)))
99 static int fbdevHWPrivateIndex
= -1;
102 /* framebuffer device: filename (/dev/fb*), handle, more */
106 unsigned int fbmem_len
;
109 unsigned int mmio_len
;
111 /* current hardware state */
112 struct fb_fix_screeninfo fix
;
113 struct fb_var_screeninfo var
;
115 /* saved video mode */
116 struct fb_var_screeninfo saved_var
;
118 /* FIXME: unused??? [geert] */
119 struct fb_cmap saved_cmap
;
120 unsigned short *saved_red
;
121 unsigned short *saved_green
;
122 unsigned short *saved_blue
;
124 /* buildin video mode */
125 DisplayModeRec buildin
;
127 } fbdevHWRec
, *fbdevHWPtr
;
130 fbdevHWGetRec(ScrnInfoPtr pScrn
)
134 if (fbdevHWPrivateIndex
< 0)
135 fbdevHWPrivateIndex
= xf86AllocateScrnInfoPrivateIndex();
137 if (FBDEVHWPTR(pScrn
) != NULL
)
140 fPtr
= FBDEVHWPTRLVAL(pScrn
) = xnfcalloc(sizeof(fbdevHWRec
), 1);
145 fbdevHWFreeRec(ScrnInfoPtr pScrn
)
147 if (fbdevHWPrivateIndex
< 0)
149 if (FBDEVHWPTR(pScrn
) == NULL
)
151 xfree(FBDEVHWPTR(pScrn
));
152 FBDEVHWPTRLVAL(pScrn
) = NULL
;
155 /* -------------------------------------------------------------------- */
156 /* some helpers for printing debug informations */
160 print_fbdev_mode(char *txt
, struct fb_var_screeninfo
*var
)
162 ErrorF( "fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n",
164 var
->xres
, var
->right_margin
, var
->hsync_len
, var
->left_margin
,
165 var
->yres
, var
->lower_margin
, var
->vsync_len
, var
->upper_margin
,
167 var
->red
.length
, var
->green
.length
, var
->blue
.length
);
171 print_xfree_mode(char *txt
, DisplayModePtr mode
)
173 ErrorF( "xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n",
175 mode
->HDisplay
, mode
->HSyncStart
, mode
->HSyncEnd
, mode
->HTotal
,
176 mode
->VDisplay
, mode
->VSyncStart
, mode
->VSyncEnd
, mode
->VTotal
);
180 /* -------------------------------------------------------------------- */
181 /* Convert timings between the XFree and the Frame Buffer Device */
184 xfree2fbdev_fblayout(ScrnInfoPtr pScrn
, struct fb_var_screeninfo
*var
)
186 var
->xres_virtual
= pScrn
->displayWidth
? pScrn
->displayWidth
:
188 var
->yres_virtual
= pScrn
->virtualY
;
189 var
->bits_per_pixel
= pScrn
->bitsPerPixel
;
190 if (pScrn
->defaultVisual
== TrueColor
||
191 pScrn
->defaultVisual
== DirectColor
) {
192 var
->red
.length
= pScrn
->weight
.red
;
193 var
->green
.length
= pScrn
->weight
.green
;
194 var
->blue
.length
= pScrn
->weight
.blue
;
197 var
->green
.length
= 8;
198 var
->blue
.length
= 8;
203 xfree2fbdev_timing(DisplayModePtr mode
, struct fb_var_screeninfo
*var
)
205 var
->xres
= mode
->HDisplay
;
206 var
->yres
= mode
->VDisplay
;
207 if (var
->xres_virtual
< var
->xres
)
208 var
->xres_virtual
= var
->xres
;
209 if (var
->yres_virtual
< var
->yres
)
210 var
->yres_virtual
= var
->yres
;
211 var
->xoffset
= var
->yoffset
= 0;
212 var
->pixclock
= mode
->Clock
? 1000000000/mode
->Clock
: 0;
213 var
->right_margin
= mode
->HSyncStart
-mode
->HDisplay
;
214 var
->hsync_len
= mode
->HSyncEnd
-mode
->HSyncStart
;
215 var
->left_margin
= mode
->HTotal
-mode
->HSyncEnd
;
216 var
->lower_margin
= mode
->VSyncStart
-mode
->VDisplay
;
217 var
->vsync_len
= mode
->VSyncEnd
-mode
->VSyncStart
;
218 var
->upper_margin
= mode
->VTotal
-mode
->VSyncEnd
;
220 if (mode
->Flags
& V_PHSYNC
)
221 var
->sync
|= FB_SYNC_HOR_HIGH_ACT
;
222 if (mode
->Flags
& V_PVSYNC
)
223 var
->sync
|= FB_SYNC_VERT_HIGH_ACT
;
224 if (mode
->Flags
& V_PCSYNC
)
225 var
->sync
|= FB_SYNC_COMP_HIGH_ACT
;
226 #if 1 /* Badly needed for PAL/NTSC on Amiga (amifb)!! [geert] */
227 if (mode
->Flags
& V_BCAST
)
228 var
->sync
|= FB_SYNC_BROADCAST
;
230 if (mode
->Flags
& V_INTERLACE
)
231 var
->vmode
= FB_VMODE_INTERLACED
;
232 else if (mode
->Flags
& V_DBLSCAN
)
233 var
->vmode
= FB_VMODE_DOUBLE
;
235 var
->vmode
= FB_VMODE_NONINTERLACED
;
239 fbdev_modes_equal(struct fb_var_screeninfo
*set
, struct fb_var_screeninfo
*req
)
241 return (set
->xres_virtual
>= req
->xres_virtual
&&
242 set
->yres_virtual
>= req
->yres_virtual
&&
243 set
->bits_per_pixel
== req
->bits_per_pixel
&&
244 set
->red
.length
== req
->red
.length
&&
245 set
->green
.length
== req
->green
.length
&&
246 set
->blue
.length
== req
->blue
.length
&&
247 set
->xres
== req
->xres
&& set
->yres
== req
->yres
&&
248 set
->pixclock
== req
->pixclock
&&
249 set
->right_margin
== req
->right_margin
&&
250 set
->hsync_len
== req
->hsync_len
&&
251 set
->left_margin
== req
->left_margin
&&
252 set
->lower_margin
== req
->lower_margin
&&
253 set
->vsync_len
== req
->vsync_len
&&
254 set
->upper_margin
== req
->upper_margin
&&
255 set
->sync
== req
->sync
&& set
->vmode
== req
->vmode
);
259 fbdev2xfree_timing(struct fb_var_screeninfo
*var
, DisplayModePtr mode
)
261 mode
->Clock
= var
->pixclock
? 1000000000/var
->pixclock
: 28000000;
262 mode
->HDisplay
= var
->xres
;
263 mode
->HSyncStart
= mode
->HDisplay
+var
->right_margin
;
264 mode
->HSyncEnd
= mode
->HSyncStart
+var
->hsync_len
;
265 mode
->HTotal
= mode
->HSyncEnd
+var
->left_margin
;
266 mode
->VDisplay
= var
->yres
;
267 mode
->VSyncStart
= mode
->VDisplay
+var
->lower_margin
;
268 mode
->VSyncEnd
= mode
->VSyncStart
+var
->vsync_len
;
269 mode
->VTotal
= mode
->VSyncEnd
+var
->upper_margin
;
271 mode
->Flags
|= var
->sync
& FB_SYNC_HOR_HIGH_ACT
? V_PHSYNC
: V_NHSYNC
;
272 mode
->Flags
|= var
->sync
& FB_SYNC_VERT_HIGH_ACT
? V_PVSYNC
: V_NVSYNC
;
273 mode
->Flags
|= var
->sync
& FB_SYNC_COMP_HIGH_ACT
? V_PCSYNC
: V_NCSYNC
;
274 #if 1 /* Badly needed for PAL/NTSC on Amiga (amifb)!! [geert] */
275 if (var
->sync
& FB_SYNC_BROADCAST
)
276 mode
->Flags
|= V_BCAST
;
278 if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_INTERLACED
)
279 mode
->Flags
|= V_INTERLACE
;
280 else if ((var
->vmode
& FB_VMODE_MASK
) == FB_VMODE_DOUBLE
)
281 mode
->Flags
|= V_DBLSCAN
;
282 mode
->SynthClock
= mode
->Clock
;
283 mode
->CrtcHDisplay
= mode
->HDisplay
;
284 mode
->CrtcHSyncStart
= mode
->HSyncStart
;
285 mode
->CrtcHSyncEnd
= mode
->HSyncEnd
;
286 mode
->CrtcHTotal
= mode
->HTotal
;
287 mode
->CrtcVDisplay
= mode
->VDisplay
;
288 mode
->CrtcVSyncStart
= mode
->VSyncStart
;
289 mode
->CrtcVSyncEnd
= mode
->VSyncEnd
;
290 mode
->CrtcVTotal
= mode
->VTotal
;
291 mode
->CrtcHAdjusted
= FALSE
;
292 mode
->CrtcVAdjusted
= FALSE
;
296 /* -------------------------------------------------------------------- */
297 /* open correct framebuffer device */
299 /* try to find the framebuffer device for a given PCI device */
301 fbdev_open_pci(pciVideoPtr pPci
, char **namep
)
303 struct fb_fix_screeninfo fix
;
306 memType res_start
, res_end
;
308 for (i
= 0; i
< 8; i
++) {
309 sprintf(filename
,"/dev/fb%d",i
);
310 if (-1 == (fd
= open(filename
,O_RDWR
,0))) {
311 xf86DrvMsg(-1, X_WARNING
,
312 "open %s: %s\n", filename
, strerror(errno
));
315 if (-1 == ioctl(fd
,FBIOGET_FSCREENINFO
,(void*)&fix
)) {
319 for (j
= 0; j
< 6; j
++) {
320 res_start
= pPci
->memBase
[j
];
321 res_end
= res_start
+pPci
->size
[j
];
322 if ((0 != fix
.smem_len
&&
323 (memType
) fix
.smem_start
>= res_start
&&
324 (memType
) fix
.smem_start
< res_end
) ||
325 (0 != fix
.mmio_len
&&
326 (memType
) fix
.mmio_start
>= res_start
&&
327 (memType
) fix
.mmio_start
< res_end
))
335 *namep
= xnfalloc(16);
336 strncpy(*namep
,fix
.id
,16);
342 xf86DrvMsg(-1, X_ERROR
,
343 "Unable to find a valid framebuffer device\n");
349 fbdev_open(int scrnIndex
, char *dev
, char** namep
)
351 struct fb_fix_screeninfo fix
;
354 /* try argument (from XF86Config) first */
356 fd
= open(dev
,O_RDWR
,0);
358 /* second: environment variable */
359 dev
= getenv("FRAMEBUFFER");
360 if ((NULL
== dev
) || ((fd
= open(dev
,O_RDWR
,0)) == -1)) {
361 /* last try: default device */
363 fd
= open(dev
,O_RDWR
,0);
368 xf86DrvMsg(scrnIndex
, X_ERROR
,
369 "open %s: %s\n", dev
, strerror(errno
));
374 if (-1 == ioctl(fd
,FBIOGET_FSCREENINFO
,(void*)(&fix
))) {
376 xf86DrvMsg(scrnIndex
, X_ERROR
,
377 "FBIOGET_FSCREENINFO: %s\n", strerror(errno
));
380 *namep
= xnfalloc(16);
381 strncpy(*namep
,fix
.id
,16);
387 /* -------------------------------------------------------------------- */
390 fbdevHWProbe(pciVideoPtr pPci
, char *device
,char **namep
)
395 fd
= fbdev_open_pci(pPci
,namep
);
397 fd
= fbdev_open(-1,device
,namep
);
406 fbdevHWInit(ScrnInfoPtr pScrn
, pciVideoPtr pPci
, char *device
)
412 fbdevHWGetRec(pScrn
);
413 fPtr
= FBDEVHWPTR(pScrn
);
417 fPtr
->fd
= fbdev_open_pci(pPci
,NULL
);
419 fPtr
->fd
= fbdev_open(pScrn
->scrnIndex
,device
,NULL
);
420 if (-1 == fPtr
->fd
) {
421 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
422 "Failed to open framebuffer device, consult warnings"
423 " and/or errors above for possible reasons\n"
424 "\t(you may have to look at the server log to see"
429 /* get current fb device settings */
430 if (-1 == ioctl(fPtr
->fd
,FBIOGET_FSCREENINFO
,(void*)(&fPtr
->fix
))) {
431 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
432 "ioctl FBIOGET_FSCREENINFO: %s\n",
436 if (-1 == ioctl(fPtr
->fd
,FBIOGET_VSCREENINFO
,(void*)(&fPtr
->var
))) {
437 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
438 "ioctl FBIOGET_VSCREENINFO: %s\n",
443 /* we can use the current settings as "buildin mode" */
444 fbdev2xfree_timing(&fPtr
->var
, &fPtr
->buildin
);
445 fPtr
->buildin
.name
= "current";
446 fPtr
->buildin
.next
= &fPtr
->buildin
;
447 fPtr
->buildin
.prev
= &fPtr
->buildin
;
448 fPtr
->buildin
.type
|= M_T_BUILTIN
;
454 fbdevHWGetName(ScrnInfoPtr pScrn
)
456 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
461 fbdevHWGetDepth(ScrnInfoPtr pScrn
, int *fbbpp
)
463 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
466 *fbbpp
= fPtr
->var
.bits_per_pixel
;
468 if (fPtr
->fix
.visual
== FB_VISUAL_TRUECOLOR
||
469 fPtr
->fix
.visual
== FB_VISUAL_DIRECTCOLOR
)
470 return fPtr
->var
.red
.length
+fPtr
->var
.green
.length
+
471 fPtr
->var
.blue
.length
;
473 return fPtr
->var
.bits_per_pixel
;
477 fbdevHWGetLineLength(ScrnInfoPtr pScrn
)
479 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
481 if (fPtr
->fix
.line_length
)
482 return fPtr
->fix
.line_length
;
484 return fPtr
->var
.xres_virtual
*fPtr
->var
.bits_per_pixel
/8;
488 fbdevHWGetType(ScrnInfoPtr pScrn
)
490 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
491 return fPtr
->fix
.type
;
495 fbdevHWGetVidmem(ScrnInfoPtr pScrn
)
497 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
498 return fPtr
->fix
.smem_len
;
502 fbdevHWSetMode(ScrnInfoPtr pScrn
, DisplayModePtr mode
, Bool check
)
504 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
505 struct fb_var_screeninfo req_var
= fPtr
->var
, set_var
;
507 TRACE_ENTER("SetMode");
509 xfree2fbdev_fblayout(pScrn
, &req_var
);
510 xfree2fbdev_timing(mode
, &req_var
);
513 print_xfree_mode("init", mode
);
514 print_fbdev_mode("init", &req_var
);
520 set_var
.activate
= FB_ACTIVATE_TEST
;
522 if (0 != ioctl(fPtr
->fd
, FBIOPUT_VSCREENINFO
, (void*)(&set_var
))) {
523 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
524 "FBIOPUT_VSCREENINFO: %s\n", strerror(errno
));
528 if (!fbdev_modes_equal(&set_var
, &req_var
)) {
530 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
531 "FBIOPUT_VSCREENINFO succeeded but modified "
534 print_fbdev_mode("returned", &set_var
);
546 fbdevHWSetVideoModes(ScrnInfoPtr pScrn
)
549 DisplayModePtr mode
,this,last
= pScrn
->modes
;
551 TRACE_ENTER("VerifyModes");
552 if (NULL
== pScrn
->display
->modes
)
555 pScrn
->virtualX
= pScrn
->display
->virtualX
;
556 pScrn
->virtualY
= pScrn
->display
->virtualY
;
558 for (modename
= pScrn
->display
->modes
; *modename
!= NULL
; modename
++) {
559 for (mode
= pScrn
->monitor
->Modes
; mode
!= NULL
; mode
= mode
->next
)
560 if (0 == strcmp(mode
->name
,*modename
))
563 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
564 "\tmode \"%s\" not found\n", *modename
);
568 if (!fbdevHWSetMode(pScrn
, mode
, TRUE
)) {
569 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
570 "\tmode \"%s\" test failed\n", *modename
);
573 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
574 "\tmode \"%s\" ok\n", *modename
);
576 if (pScrn
->virtualX
< mode
->HDisplay
)
577 pScrn
->virtualX
= mode
->HDisplay
;
578 if (pScrn
->virtualY
< mode
->VDisplay
)
579 pScrn
->virtualY
= mode
->VDisplay
;
581 if (NULL
== pScrn
->modes
) {
582 pScrn
->modes
= xnfalloc(sizeof(DisplayModeRec
));
584 memcpy(this,mode
,sizeof(DisplayModeRec
));
588 this = xnfalloc(sizeof(DisplayModeRec
));
589 memcpy(this,mode
,sizeof(DisplayModeRec
));
590 this->next
= pScrn
->modes
;
593 pScrn
->modes
->prev
= this;
600 fbdevHWGetBuildinMode(ScrnInfoPtr pScrn
)
602 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
603 return &fPtr
->buildin
;
607 fbdevHWUseBuildinMode(ScrnInfoPtr pScrn
)
609 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
611 TRACE_ENTER("UseBuildinMode");
612 pScrn
->modes
= &fPtr
->buildin
;
613 pScrn
->virtualX
= pScrn
->display
->virtualX
;
614 pScrn
->virtualY
= pScrn
->display
->virtualY
;
615 if (pScrn
->virtualX
< fPtr
->buildin
.HDisplay
)
616 pScrn
->virtualX
= fPtr
->buildin
.HDisplay
;
617 if (pScrn
->virtualY
< fPtr
->buildin
.VDisplay
)
618 pScrn
->virtualY
= fPtr
->buildin
.VDisplay
;
621 /* -------------------------------------------------------------------- */
624 calculateFbmem_len(fbdevHWPtr fPtr
)
626 fPtr
->fboff
= (unsigned long) fPtr
->fix
.smem_start
& ~PAGE_MASK
;
627 fPtr
->fbmem_len
= (fPtr
->fboff
+fPtr
->fix
.smem_len
+~PAGE_MASK
) &
633 fbdevHWMapVidmem(ScrnInfoPtr pScrn
)
635 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
637 TRACE_ENTER("MapVidmem");
638 if (NULL
== fPtr
->fbmem
) {
639 calculateFbmem_len(fPtr
);
640 fPtr
->fbmem
= mmap(NULL
, fPtr
->fbmem_len
, PROT_READ
| PROT_WRITE
,
641 MAP_SHARED
, fPtr
->fd
, 0);
642 if (-1 == (long)fPtr
->fbmem
) {
643 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
644 "mmap fbmem: %s\n", strerror(errno
));
647 /* Perhaps we'd better add fboff to fbmem and return 0 in
648 fbdevHWLinearOffset()? Of course we then need to mask
649 fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as
653 pScrn
->memPhysBase
= (unsigned long)fPtr
->fix
.smem_start
& (unsigned long)(PAGE_MASK
);
654 pScrn
->fbOffset
= (unsigned long)fPtr
->fix
.smem_start
& (unsigned long)(~PAGE_MASK
);
659 fbdevHWLinearOffset(ScrnInfoPtr pScrn
)
661 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
663 TRACE_ENTER("LinearOffset");
668 fbdevHWUnmapVidmem(ScrnInfoPtr pScrn
)
670 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
672 TRACE_ENTER("UnmapVidmem");
673 if (NULL
!= fPtr
->fbmem
) {
674 if (-1 == munmap(fPtr
->fbmem
, fPtr
->fbmem_len
))
675 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
676 "munmap fbmem: %s\n", strerror(errno
));
683 fbdevHWMapMMIO(ScrnInfoPtr pScrn
)
685 unsigned int mmio_off
;
687 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
689 TRACE_ENTER("MapMMIO");
690 if (NULL
== fPtr
->mmio
) {
691 /* tell the kernel not to use accels to speed up console scrolling */
692 fPtr
->var
.accel_flags
= 0;
693 if (0 != ioctl(fPtr
->fd
,FBIOPUT_VSCREENINFO
,(void*)(&fPtr
->var
))) {
694 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
695 "FBIOPUT_VSCREENINFO: %s\n", strerror(errno
));
698 mmio_off
= (unsigned long) fPtr
->fix
.mmio_start
& ~PAGE_MASK
;
699 fPtr
->mmio_len
= (mmio_off
+fPtr
->fix
.mmio_len
+~PAGE_MASK
) &
701 if (NULL
== fPtr
->fbmem
)
702 calculateFbmem_len(fPtr
);
703 fPtr
->mmio
= mmap(NULL
, fPtr
->mmio_len
, PROT_READ
| PROT_WRITE
,
704 MAP_SHARED
, fPtr
->fd
, fPtr
->fbmem_len
);
705 if (-1 == (long)fPtr
->mmio
) {
706 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
707 "mmap mmio: %s\n", strerror(errno
));
710 fPtr
->mmio
+= mmio_off
;
716 fbdevHWUnmapMMIO(ScrnInfoPtr pScrn
)
718 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
720 TRACE_ENTER("UnmapMMIO");
721 if (NULL
!= fPtr
->mmio
) {
722 if (-1 == munmap((void *)((unsigned long)fPtr
->mmio
& PAGE_MASK
), fPtr
->mmio_len
))
723 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
724 "munmap mmio: %s\n", strerror(errno
));
726 /* FIXME: restore var.accel_flags [geert] */
731 /* -------------------------------------------------------------------- */
734 fbdevHWModeInit(ScrnInfoPtr pScrn
, DisplayModePtr mode
)
736 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
738 pScrn
->vtSema
= TRUE
;
741 if (!fbdevHWSetMode(pScrn
, mode
, FALSE
))
745 if (0 != ioctl(fPtr
->fd
,FBIOGET_FSCREENINFO
,(void*)(&fPtr
->fix
))) {
746 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
747 "FBIOGET_FSCREENINFO: %s\n", strerror(errno
));
750 if (0 != ioctl(fPtr
->fd
,FBIOGET_VSCREENINFO
,(void*)(&fPtr
->var
))) {
751 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
752 "FBIOGET_VSCREENINFO: %s\n", strerror(errno
));
756 if (pScrn
->defaultVisual
== TrueColor
||
757 pScrn
->defaultVisual
== DirectColor
) {
758 /* XXX: This is a hack, but it should be a NOP for all the setups that
759 * worked before and actually seems to fix some others...
761 pScrn
->offset
.red
= fPtr
->var
.red
.offset
;
762 pScrn
->offset
.green
= fPtr
->var
.green
.offset
;
763 pScrn
->offset
.blue
= fPtr
->var
.blue
.offset
;
764 pScrn
->mask
.red
= ((1 << fPtr
->var
.red
.length
) - 1) << fPtr
->var
.red
.offset
;
765 pScrn
->mask
.green
= ((1 << fPtr
->var
.green
.length
) - 1) << fPtr
->var
.green
.offset
;
766 pScrn
->mask
.blue
= ((1 << fPtr
->var
.blue
.length
) - 1) << fPtr
->var
.blue
.offset
;
772 /* -------------------------------------------------------------------- */
773 /* video mode save/restore */
777 fbdevHWSave(ScrnInfoPtr pScrn
)
779 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
782 if (0 != ioctl(fPtr
->fd
,FBIOGET_VSCREENINFO
,(void*)(&fPtr
->saved_var
)))
783 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
784 "FBIOGET_VSCREENINFO: %s\n", strerror(errno
));
788 fbdevHWRestore(ScrnInfoPtr pScrn
)
790 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
792 TRACE_ENTER("Restore");
793 if (0 != ioctl(fPtr
->fd
,FBIOPUT_VSCREENINFO
,(void*)(&fPtr
->saved_var
)))
794 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
795 "FBIOPUT_VSCREENINFO: %s\n", strerror(errno
));
798 /* -------------------------------------------------------------------- */
799 /* callback for xf86HandleColormaps */
802 fbdevHWLoadPalette(ScrnInfoPtr pScrn
, int numColors
, int *indices
,
803 LOCO
*colors
, VisualPtr pVisual
)
805 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
807 unsigned short red
,green
,blue
;
810 TRACE_ENTER("LoadPalette");
816 for (i
= 0; i
< numColors
; i
++) {
817 cmap
.start
= indices
[i
];
818 red
= (colors
[indices
[i
]].red
<< 8) |
819 colors
[indices
[i
]].red
;
820 green
= (colors
[indices
[i
]].green
<< 8) |
821 colors
[indices
[i
]].green
;
822 blue
= (colors
[indices
[i
]].blue
<< 8) |
823 colors
[indices
[i
]].blue
;
824 if (-1 == ioctl(fPtr
->fd
,FBIOPUTCMAP
,(void*)&cmap
))
825 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
826 "FBIOPUTCMAP: %s\n", strerror(errno
));
830 /* -------------------------------------------------------------------- */
831 /* these can be hooked directly into ScrnInfoRec */
834 fbdevHWValidMode(int scrnIndex
, DisplayModePtr mode
, Bool verbose
, int flags
)
836 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
838 TRACE_ENTER("ValidMode");
840 if (!fbdevHWSetMode(pScrn
, mode
, TRUE
))
847 fbdevHWSwitchMode(int scrnIndex
, DisplayModePtr mode
, int flags
)
849 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
851 TRACE_ENTER("SwitchMode");
853 if (!fbdevHWSetMode(pScrn
, mode
, FALSE
))
860 fbdevHWAdjustFrame(int scrnIndex
, int x
, int y
, int flags
)
862 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
863 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
865 TRACE_ENTER("AdjustFrame");
866 if ( x
< 0 || x
+ fPtr
->var
.xres
> fPtr
->var
.xres_virtual
||
867 y
< 0 || y
+ fPtr
->var
.yres
> fPtr
->var
.yres_virtual
)
870 fPtr
->var
.xoffset
= x
;
871 fPtr
->var
.yoffset
= y
;
872 if (-1 == ioctl(fPtr
->fd
,FBIOPAN_DISPLAY
,(void*)&fPtr
->var
))
873 xf86DrvMsgVerb(scrnIndex
, X_WARNING
, 5,
874 "FBIOPAN_DISPLAY: %s\n", strerror(errno
));
878 fbdevHWEnterVT(int scrnIndex
, int flags
)
880 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
882 TRACE_ENTER("EnterVT");
883 if (!fbdevHWModeInit(pScrn
, pScrn
->currentMode
))
885 fbdevHWAdjustFrame(scrnIndex
, pScrn
->frameX0
, pScrn
->frameY0
, 0);
890 fbdevHWLeaveVT(int scrnIndex
, int flags
)
892 ScrnInfoPtr pScrn
= xf86Screens
[scrnIndex
];
894 TRACE_ENTER("LeaveVT");
895 fbdevHWRestore(pScrn
);
899 fbdevHWDPMSSet(ScrnInfoPtr pScrn
, int mode
, int flags
)
901 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
902 unsigned long fbmode
;
904 TRACE_ENTER("DPMSSet");
912 case DPMSModeStandby
:
915 case DPMSModeSuspend
:
925 if (-1 == ioctl(fPtr
->fd
, FBIOBLANK
, (void *)fbmode
))
926 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
927 "FBIOBLANK: %s\n", strerror(errno
));
931 fbdevHWSaveScreen(ScreenPtr pScreen
, int mode
)
933 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
934 fbdevHWPtr fPtr
= FBDEVHWPTR(pScrn
);
935 unsigned long unblank
;
937 TRACE_ENTER("HWSaveScreen");
941 unblank
= xf86IsUnblank(mode
);
943 if (-1 == ioctl(fPtr
->fd
, FBIOBLANK
, (void *)(1-unblank
))) {
944 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
945 "FBIOBLANK: %s\n", strerror(errno
));
953 fbdevHWSwitchModeWeak(void) { return fbdevHWSwitchMode
; }
955 xf86AdjustFrameProc
*
956 fbdevHWAdjustFrameWeak(void) { return fbdevHWAdjustFrame
; }
959 fbdevHWEnterVTWeak(void) { return fbdevHWEnterVT
; }
962 fbdevHWLeaveVTWeak(void) { return fbdevHWLeaveVT
; }
965 fbdevHWValidModeWeak(void) { return fbdevHWValidMode
; }
968 fbdevHWDPMSSetWeak(void) { return fbdevHWDPMSSet
; }
970 xf86LoadPaletteProc
*
971 fbdevHWLoadPaletteWeak(void) { return fbdevHWLoadPalette
; }
974 fbdevHWSaveScreenWeak(void) { return fbdevHWSaveScreen
; }