Screenshot instructions:
Windows
Mac
Red Hat Linux
Ubuntu
Click URL instructions:
Right-click on ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)
You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
(1) |
Apr
(104) |
May
(81) |
Jun
(248) |
Jul
(133) |
Aug
(33) |
Sep
(53) |
Oct
(82) |
Nov
(166) |
Dec
(71) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(121) |
Feb
(42) |
Mar
(39) |
Apr
(84) |
May
(87) |
Jun
(58) |
Jul
(97) |
Aug
(130) |
Sep
(32) |
Oct
(139) |
Nov
(108) |
Dec
(216) |
2003 |
Jan
(299) |
Feb
(136) |
Mar
(392) |
Apr
(141) |
May
(137) |
Jun
(107) |
Jul
(94) |
Aug
(262) |
Sep
(300) |
Oct
(216) |
Nov
(72) |
Dec
(94) |
2004 |
Jan
(174) |
Feb
(192) |
Mar
(215) |
Apr
(314) |
May
(319) |
Jun
(293) |
Jul
(205) |
Aug
(161) |
Sep
(192) |
Oct
(226) |
Nov
(308) |
Dec
(89) |
2005 |
Jan
(127) |
Feb
(269) |
Mar
(588) |
Apr
(106) |
May
(77) |
Jun
(77) |
Jul
(161) |
Aug
(239) |
Sep
(86) |
Oct
(112) |
Nov
(153) |
Dec
(145) |
2006 |
Jan
(87) |
Feb
(57) |
Mar
(129) |
Apr
(109) |
May
(102) |
Jun
(232) |
Jul
(97) |
Aug
(69) |
Sep
(67) |
Oct
(69) |
Nov
(214) |
Dec
(82) |
2007 |
Jan
(133) |
Feb
(307) |
Mar
(121) |
Apr
(171) |
May
(229) |
Jun
(156) |
Jul
(185) |
Aug
(160) |
Sep
(122) |
Oct
(130) |
Nov
(78) |
Dec
(27) |
2008 |
Jan
(105) |
Feb
(137) |
Mar
(146) |
Apr
(148) |
May
(239) |
Jun
(208) |
Jul
(157) |
Aug
(244) |
Sep
(119) |
Oct
(125) |
Nov
(189) |
Dec
(225) |
2009 |
Jan
(157) |
Feb
(139) |
Mar
(106) |
Apr
(130) |
May
(246) |
Jun
(189) |
Jul
(128) |
Aug
(127) |
Sep
(88) |
Oct
(86) |
Nov
(216) |
Dec
(9) |
2010 |
Jan
(5) |
Feb
|
Mar
(11) |
Apr
(31) |
May
(3) |
Jun
|
Jul
(7) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2012 |
Jan
|
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2013 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
1
(2) |
2
(1) |
3
(1) |
4
|
5
(2) |
6
(3) |
7
(1) |
8
(1) |
9
(1) |
10
(2) |
11
(1) |
12
(3) |
13
(2) |
14
(23) |
15
(1) |
16
(5) |
17
(5) |
18
(9) |
19
(3) |
20
(2) |
21
(6) |
22
(21) |
23
(16) |
24
(10) |
25
(9) |
26
(3) |
27
(12) |
28
(6) |
29
(7) |
30
(8) |
|
From: Sottek, Matthew J <matthew.j.sottek@in...> - 2001-11-27 20:12:06
|
>Well at present true. Actually I have been thinking about this >problem. Plus someone talked about this a few days ago on the list. >I personally have run inot the the problem of data write size >restrictions. For me it was the Epson 1385 framebuffer. It only >allows 16 bit accesses to the framebuffer. So if I do a raw cat >I get strips down my screen. Lets not forget that use can't use >memset on PPC on a framebuffer. So I agree we need to have fbdev >functions for access to the framebuffer and they should >be made avaliable to userland. The question is where to place >these macros? I've though of several use cases that make the current way of doing things just unworkable. #1 Banked memory. The whole reason I got involved in this was to complete a stolen memory driver for the i810. It only has banked memory in this mode and just can't work with the way things are. #2 Network console? What happens if you want to write a driver that is actually a networked console display? There is no framebuffer locally so you can't access if without driver interfaces. >So for fb_read and fb_write we need to copy the userland data into >a temporary buffer and then use fb_memset to actually draw the image. No, I was thinking that the functions below would be of this type #define COPY_TO_USER 0x00000001 #define MEMCPY 0x00000002 void *fb_put(u8 *data, u32 srcx, u32 srcy, u32 width, u32 height, u32 destx, u32 desty, u32 flags) The driver would check flags and either memcpy or copy_to_user. We probably need an fb_copy_to_user to handle byte swapping on multiplatform drivers. So no intermediate copy. That would be too slow. >Yes. Remember tho it only does a rectangle of one color. We also >nedd fb_write functions. I think you misinterpreted one of my functions....plus I left one out. fb_put (Set a chunk of the framebuffer from the data provided. The data comes fro userland or kernelland) fb_set (The a chunk of the framebuffer to a single value) fb_get (Get a chunk of data fro the framebuffer to the place requested. It can be userland or kernelland) fb_copy (aka blit, screen_to_screen) >Oh my. I really have to think about this. For now lets just >cleanup what we have. This is hard for me to swallow since "what we have" cannot possibly work for what I'm trying to do. It will only get worse if mmap goes away. I am writing up all the concepts I have floating around in my head and I'll post it when I'm done. I have to believe that fixing all the major issues is easier than trying to fix small parts. -Matt |
From: James Simmons <jsimmons@tr...> - 2001-11-27 19:18:38
|
> >Set the fb_fix fields for mmio and smem to zero. As for internally with > >the new api you don't need to use the screen_base field. > >Just ignore it. > > After further review (correct me If I am wrong James) it seems that > screen base (a kernel virtual address to the framebuffer) is needed > for the fb_read and fb_write functions. It was suggested that > there isn't a way around this. Well at present true. Actually I have been thinking about this problem. Plus someone talked about this a few days ago on the list. I personally have run inot the the problem of data write size restrictions. For me it was the Epson 1385 framebuffer. It only allows 16 bit accesses to the framebuffer. So if I do a raw cat I get strips down my screen. Lets not forget that use can't use memset on PPC on a framebuffer. So I agree we need to have fbdev functions for access to the framebuffer and they should be made avaliable to userland. The question is where to place these macros? So for fb_read and fb_write we need to copy the userland data into a temporary buffer and then use fb_memset to actually draw the image. > fb_put: Put data from somewhere into the framebuffer. This is called > imageblit in the new API. This should have a parameter to tell you > to use copy_from_user() or memcpy() Yeap. > fb_get: Get data from the framebuffer and put it in a provided pointer. > This should have a flag to tell you to use copy_to_user() or > memcpy() See what I said above. We should also consider the endian of the buffers to. > fb_set: Set a region of the frambuffer with the value provided. This > is called fillrect(?) in the new api. Yes. Remember tho it only does a rectangle of one color. We also nedd fb_write functions. > I have thought of a compromise that should be very easy for most > drivers to do, and will allow us to keep the driver private stuff > hidden. [snip]... Oh my. I really have to think about this. For now lets just cleanup what we have. |
From: Petr Vandrovec <VANDROVE@vc...> - 2001-11-27 19:03:45
|
On 27 Nov 01 at 10:19, James Simmons wrote: > > Do not forget that current API is atomic, with doing it in multiple > > steps you can get nasty surprises (as resolution and resolution_virt > > depends one on another, either changing one changes also another one, > > or some modes are not accessible without first modifying resolution_virt), > > besides not being atomic... > > Not really. If you have a accelerated driver and a userland process open > /dev/fb and changes the video mode the driver could be in the middle of a > draw operation. So teh fbdev layer lacks any really type of locking. We > could add a spinlock or a semaphore but it is more complex then that. The > accel engine could be busy for sometime. So we have to wait until it is > idle. So a clever way of locking has to be done. matroxfb uses spinlock around accelerator, and ioctl is serialized by big kernel lock. But my atomicity requirement is not this. It is that request for 'xres=1024,yres=768,depth=24,vxres=2048,vyres=100000' should be refused completely, instead of switching to 1024x768-24 with vxres=2048, and then realizing that vyres=100000 is incompatible with currently installed memory. And when current mode is 512x384-32, and request is for 'xres=1024,yres=768,depth=8', it should switch at once, and not step by step, saying that there is not enough memory for 1024x768-32 (because of it went through 1024x384-32, 1024x768-32, 1024x768-8)... But I think that there is consensus on this one. Petr Vandrovec vandrove@... |
From: James Simmons <jsimmons@tr...> - 2001-11-27 18:58:14
|
> perhaps a better way of implimenting this can happen? surely removing mmap is > not the way to go. I have wrestled with this as well. I haven't thought of a better solution myself yet. |
From: James Simmons <jsimmons@tr...> - 2001-11-27 18:19:34
|
> Do not forget that current API is atomic, with doing it in multiple > steps you can get nasty surprises (as resolution and resolution_virt > depends one on another, either changing one changes also another one, > or some modes are not accessible without first modifying resolution_virt), > besides not being atomic... Not really. If you have a accelerated driver and a userland process open /dev/fb and changes the video mode the driver could be in the middle of a draw operation. So teh fbdev layer lacks any really type of locking. We could add a spinlock or a semaphore but it is more complex then that. The accel engine could be busy for sometime. So we have to wait until it is idle. So a clever way of locking has to be done. > And AFAIK Al Viro (main ioctl killer) does not require that every current > fb_*_info field should have its own file. From his posts I understand > that he is completely satisfied with just some text-based extensible API, > so > ( > echo "mode=1024x768-16@...,outputfmt=NTSC,vxres=2048,xoffset=141" >&0 > read a > echo $a > ) <> /dev/fb0/control' > would be enough for him... As there is already couple of comma separated > list parsers in the kernel (mount options, kernel cmdline), I think that > it is preferred format - in simplest form you write one line in, and > get one line back... Yeap. That is basically what he wants. |
From: Jani Monoses <jani@as...> - 2001-11-27 14:11:19
|
Hi I would appreciate if any of the knowledgable people on this list could spare a few minutes and look through this fb driver I wrote for trident blade chips for any stupidities regarding API usage.Especially the init function (tridentfb_init) There are a few things (I think not hw related) that are annoying: * when I insmod it the console is cleared with white(maybe that's OK I haven't seen other modular fb's?) * it oopses in fbcon_setup when initial depth=32,because apparently p->dispsw == NULL in macro fontwidthvalid.Other bpp's work OK and I don't see what I have done differently...If I switch to 32bpp afterwards all's well. * when in Midnight Commander's backgound console (a pty) acceleration is slow.you can actually see menus redrawn in make menuconfig.Without mc it's about twice as fast as vesafb *is hwsitch->detect() needed? I intend to port this to the new API once it is tested Thanks in advance Jani. Two eyes bad,more eyes good! /* * Frame buffer driver for Trident Blade3D series * * Copyright 2001 - Jani Monoses <jani@...> * * $Id: trident.c,v 1.46 2001/11/27 14:47:35 jani Exp $ * * CREDITS:(in order of appearance) * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video * Special thanks ;) to Mattia Crivellini <tia@...> * much inspired by the XFree86 4.1.0 Trident driver sources by Alan Hourihane * the FreeVGA project * * NOTES: * Only tested on Compaq Presario 12XL300 with CyberBladei1 and Flat Panel or * external monitor * with 8bb 16bpp 32bpp 640x480 and 800x600 combinations. * It should work on Image3D cards as well except acceleration. * No monitors were harmed during the writing of this driver. * TODO: * timing value tweaking so it looks good on every monitor in every mode * text acceleration for the Image series * PCI ids * DPMS stuff * */ #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/tty.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/selection.h> #include <video/fbcon.h> #include <video/fbcon-cfb8.h> #include <video/fbcon-cfb16.h> #include <video/fbcon-cfb24.h> #include <video/fbcon-cfb32.h> #include "trident_regs.h" #define TRIDENTFB_DEBUG 0 #if TRIDENTFB_DEBUG #define debug(f,a...) printk("%s:" f, __FUNCTION__ , ## a) #else #define debug(f,a...) #endif #define Mb (1024*1024) struct tridentfb_par { struct fb_var_screeninfo var; int bpp; int hres; int vres; int multiplex; int linelength; int vclk; //in MHz int vtotal; int vdispend; int vsyncstart; int vsyncend; int vblankstart; int vblankend; int htotal; int hdispend; int hsyncstart; int hsyncend; int hblankstart; int hblankend; }; struct tridentfb_info { struct fb_info_gen gen; unsigned int fbmem_virt; //framebuffer virtual memory address unsigned int fbmem; //framebuffer physical memory address unsigned int memsize; //size of fbmem unsigned int io; //io space address unsigned int io_virt; //iospace virtual memory address struct tridentfb_par currentmode; unsigned short cmap_cfb16[16]; unsigned short cmap_cfb15[16]; unsigned int cmap_cfb32[16]; unsigned int frequency; }; static struct fb_ops tridentfb_ops; static struct tridentfb_info fb_info; static struct display disp; static struct {unsigned char red,green,blue,pad; } palette[256]; static struct fb_var_screeninfo default_var; static char * tridentfb_name = "Trident"; /* default values for boot/module parameters */ static char * mode = "800x600"; static int depth = 8; static int noaccel = 0; static int center = 0; MODULE_PARM(depth,"i"); MODULE_PARM(center,"i"); MODULE_PARM(noaccel,"i"); MODULE_PARM(mode,"s"); #define CRT 0x3D0 //CRTC registers offset for color display #ifndef TRIDENT_MMIO #define TRIDENT_MMIO 1 #endif #if TRIDENT_MMIO #define t_outb(val,reg) writeb(val,fb_info.io_virt + reg) #define t_inb(reg) readb(fb_info.io_virt + reg) #else #define t_outb(val,reg) outb(val,reg) #define t_inb(reg) inb(reg) #endif /* * text acceleration */ static struct accel_switch { void (*init_accel)(int,int); void (*wait_engine)(void); void (*fill_rect)(int,int,int,int,int); void (*copy_rect)(int,int,int,int,int,int); } *acc; #define writemmr(r,v) writel(v, fb_info.io_virt + r) #define readmmr(r) readl(fb_info.io_virt + r) #define point(x,y) ((y)<<16|(x)) #define STA 0x2120 #define CMD 0x2144 #define ROP 0x2148 #define CLR 0x2160 #define SR1 0x2100 #define SR2 0x2104 #define DR1 0x2108 #define DR2 0x210C #define REPL(x) x = x | x<<16 #define ROP_S 0xCC static void blade_init_accel(int pitch,int bpp) { int v1 = (pitch>>3)<<20; int tmp = 0,v2; switch (bpp) { case 8:tmp = 0;break; case 15:tmp = 5;break; case 16:tmp = 1;break; case 24: case 32:tmp = 2;break; } v2 = v1 | (tmp<<29); writemmr(0x21C0,v2); writemmr(0x21C4,v2); writemmr(0x21B8,v2); writemmr(0x21BC,v2); writemmr(0x21D0,v1); writemmr(0x21D4,v1); writemmr(0x21C8,v1); writemmr(0x21CC,v1); writemmr(0x216C,0); } static void blade_wait_engine(void) { while (readmmr(STA) & 0xFA800000) schedule_timeout(1*HZ/1000); //1.0 msecs } static void blade_fill_rect(int x,int y,int w,int h,int c) { blade_wait_engine(); writemmr(CLR,c); writemmr(ROP,ROP_S); writemmr(CMD,0x20000000|1<<19|1<<4|2<<2); writemmr(DR1,point(x,y)); writemmr(DR2,point(x+w-1,y+h-1)); blade_wait_engine(); } static void blade_copy_rect(int x1,int y1,int x2,int y2,int w,int h) { int s1,s2,d1,d2; int direction = 2; s1 = point(x1,y1); s2 = point(x1+w-1,y1+h-1); d1 = point(x2,y2); d2 = point(x2+w-1,y2+h-1); if ((y1 > y2) || ((y1 == y2) && (x1 >x2))) direction = 0; blade_wait_engine(); writemmr(ROP,ROP_S); writemmr(CMD,0xE0000000|1<<19|1<<4|1<<2|direction); writemmr(SR1,direction?s2:s1); writemmr(SR2,direction?s1:s2); writemmr(DR1,direction?d2:d1); writemmr(DR2,direction?d1:d2); blade_wait_engine(); } static struct accel_switch accel_blade = { blade_init_accel, blade_wait_engine, blade_fill_rect, blade_copy_rect, }; static void image_init_accel(int pitch,int bpp) { int tmp = 0; switch (bpp) { case 8:tmp = 0;break; case 15:tmp = 5;break; case 16:tmp = 1;break; case 24: case 32:tmp = 2;break; } writemmr(0x2120, 0xF0000000); writemmr(0x2120, 0x40000000|tmp); writemmr(0x2120, 0x80000000); writemmr(0x2144, 0x00000000); writemmr(0x2148, 0x00000000); writemmr(0x2150, 0x00000000); writemmr(0x2154, 0x00000000); writemmr(0x2120, 0x60000000 |(pitch<<16) |pitch); writemmr(0x216C, 0x00000000); writemmr(0x2170, 0x00000000); writemmr(0x217C, 0x00000000); writemmr(0x2120, 0x10000000); writemmr(0x2130, (2047 << 16) | 2047); } static void image_wait_engine(void) { while (readmmr(0x2164) & 0xF0000000) schedule_timeout(1*HZ/1000); //1.0 msecs } static void image_fill_rect(int x,int y,int w,int h,int c) { writemmr(0x2120,0x80000000); writemmr(0x2120,0x90000000|ROP_S); writemmr(0x2144,c); writemmr(DR1,point(x,y)); writemmr(DR2,point(x+w-1,y+h-1)); writemmr(0x2124,0x80000000|3<<22|1<<10|1<<9); } static void image_copy_rect(int x1,int y1,int x2,int y2,int w,int h) { int s1,s2,d1,d2; int direction = 2; s1 = point(x1,y1); s2 = point(x1+w-1,y1+h-1); d1 = point(x2,y2); d2 = point(x2+w-1,y2+h-1); if ((y1 > y2) || ((y1 == y2) && (x1 >x2))) direction = 0; writemmr(0x2120,0x80000000); writemmr(0x2120,0x90000000|ROP_S); writemmr(SR1,direction?s2:s1); writemmr(SR2,direction?s1:s2); writemmr(DR1,direction?d2:d1); writemmr(DR2,direction?d1:d2); writemmr(0x2124,0x80000000|1<<22|1<<10|1<<7|direction); } static struct accel_switch accel_image = { image_init_accel, image_wait_engine, image_fill_rect, image_copy_rect, }; static void trident_bmove (struct display *p, int sy, int sx, int dy, int dx, int height, int width) { sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p); sy *= fontheight(p); dy *= fontheight(p); height *= fontheight(p); acc->copy_rect(sx,sy,dx,dy,width,height); } #ifdef FBCON_HAS_CFB8 static void trident_8bpp_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { int c; c = attr_bgcol_ec(p,conp) & 0xff; c |= c<<8; c |= c<<16; sx *= fontwidth(p); sy *= fontheight(p); width *= fontwidth(p); height *= fontheight(p); acc->fill_rect(sx,sy,width,height,c); } static struct display_switch trident_8bpp = { setup: fbcon_cfb8_setup, bmove: trident_bmove, clear: trident_8bpp_clear, putc: fbcon_cfb8_putc, putcs: fbcon_cfb8_putcs, revc: fbcon_cfb8_revc, clear_margins: fbcon_cfb8_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif #ifdef FBCON_HAS_CFB16 static void trident_16bpp_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { int c; c = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)]; c = c | c<<16; sx *= fontwidth(p); sy *= fontheight(p); width *= fontwidth(p); height *= fontheight(p); acc->fill_rect(sx,sy,width,height,c); } static struct display_switch trident_16bpp = { setup: fbcon_cfb16_setup, bmove: trident_bmove, clear: trident_16bpp_clear, putc: fbcon_cfb16_putc, putcs: fbcon_cfb16_putcs, revc: fbcon_cfb16_revc, clear_margins: fbcon_cfb16_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif #ifdef FBCON_HAS_CFB32 static void trident_32bpp_clear (struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { int c; c = ((u32*)p->dispsw_data)[attr_bgcol_ec(p,conp)]; sx *= fontwidth(p); sy *= fontheight(p); width *= fontwidth(p); height *= fontheight(p); acc->fill_rect(sx,sy,width,height,c); } static struct display_switch trident_32bpp = { setup: fbcon_cfb32_setup, bmove: trident_bmove, clear: trident_32bpp_clear, putc: fbcon_cfb32_putc, putcs: fbcon_cfb32_putcs, revc: fbcon_cfb32_revc, clear_margins: fbcon_cfb32_clear_margins, fontwidthmask: FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16) }; #endif /* read memory mapped register */ static inline unsigned char read3X4(int reg) { writeb(reg, fb_info.io_virt + CRT + 4); return readb(fb_info.io_virt + CRT + 5); } /* write memory mapped register */ static inline void write3X4(int reg, unsigned char val) { writeb(reg, fb_info.io_virt + CRT + 4); writeb(val, fb_info.io_virt + CRT + 5); } /* read register */ static inline unsigned char read3C4(int reg) { t_outb(reg, 0x3C4); return t_inb(0x3C5); } /* write register */ static inline void write3C4(int reg, unsigned char val) { t_outb(reg, 0x3C4); t_outb(val, 0x3C5); } /* read register */ static inline unsigned char read3CE(int reg) { t_outb(reg, 0x3CE); return t_inb(0x3CF); } /* write attribute controller register */ static inline void writeAttr(int reg, unsigned char val) { readb(fb_info.io_virt + CRT + 0xA); //flip-flop to index t_outb(reg, 0x3C0); t_outb(val, 0x3C0); } /* read attribute controller register */ static inline unsigned char readAttr(int reg) { readb(fb_info.io_virt + CRT + 0xA); //flip-flop to index t_outb(reg, 0x3C0); return t_inb(0x3C1); } /* write register */ static inline void write3CE(int reg, unsigned char val) { t_outb(reg, 0x3CE); t_outb(val, 0x3CF); } #define unprotect_all() write3C4(Protection, 0x92);unprotect() #define unprotect() write3C4(NewMode1,0xC2) #define new_mode() read3C4(OldOrNew) #define bios_mode(mode) write3CE(BiosMode, mode) #define bios_reg(reg) write3CE(BiosReg, reg) #define enable_mmio() outb(PCIReg, 0x3D4); \ outb(inb(0x3D5) | 0x01, 0x3D5) #define disable_mmio() write3X4(PCIReg,read3X4(PCIReg) & ~1) /* enable/disable writes to CRTC registers */ #define crtc_lock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) | 0x80) #define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) static void set_lwidth(int width) { write3X4(Offset, width & 0xFF); write3X4(AddColReg, (read3X4(AddColReg) & 0xCF) | ((width & 0x300) >>4)); } /* For resolutions smaller than FP resolution stretch */ static void screen_stretch(void) { write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 1); write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 1); } /* For resolutions smaller than FP resolution center */ static void screen_center(void) { bios_reg(0); // no stretch write3CE(VertStretch,(read3CE(VertStretch) & 0x7C) | 0x80); write3CE(HorStretch,(read3CE(HorStretch) & 0x7C) | 0x80); } /* Address of first shown pixel in display memory */ static void set_screen_start(int base) { unprotect_all(); write3X4(StartAddrLow, base & 0xFF); write3X4(StartAddrHigh, (base & 0xFF00) >>8); write3X4(CRTCModuleTest, (read3X4(CRTCModuleTest) & 0xDF) | ((base & 0x10000) >>11)); write3X4(CRTHiOrd, (read3X4(CRTHiOrd) & 0xF8) | (base & 0xE0000) >> 17); } /* VCLK handling */ #define power(x) (1<<x) #define calc_freq(n,m,k) ((NTSC * (n+8))/((m+2)*power(k))) static void set_vclk(int freq) { int m,n,k; int f,fi,d,di; unsigned char lo=0,hi=0; d = 20; for(k = 2;k>=0;k--) for(m = 0;m<63;m++) for(n = 0;n<128;n++) { fi = calc_freq(n,m,k); if ((di = abs(fi - freq)) < d) { d = di; f = fi; lo = n; hi = (k<<6) | m; } } write3C4(ClockHigh,hi); write3C4(ClockLow,lo); } static void set_number_of_lines(int lines) { int tmp = read3CE(CyberEnhance) & 0x8F; if (lines > 768) tmp |= 0x30; else if (lines > 600) tmp |= 0x20; else if (lines > 480) tmp |= 0x10; write3CE(CyberEnhance, tmp); } static unsigned int get_memsize(void) { unsigned char tmp; tmp = read3X4(SPR) & 0x0F; switch (tmp) { case 3:return 1 * Mb; case 7:return 2 * Mb; case 15:return 4 * Mb; case 4:return 8 * Mb; default:return 0; } } static void trident_detect(void) { } /* Fill in fix */ static int trident_encode_fix(struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info) { struct tridentfb_info * i = (struct tridentfb_info *)info; struct tridentfb_par * p = (struct tridentfb_par *)par; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,tridentfb_name); fix->smem_start = i->fbmem; fix->smem_len = i->memsize; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = p->bpp==8 ? FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_DIRECTCOLOR; fix->xpanstep = fix->ywrapstep = 0; fix->ypanstep = 1; fix->line_length = p->linelength; fix->mmio_start = 0; fix->mmio_len = 0; fix->accel = FB_ACCEL_NONE; return 0; } /* Fill in par from var */ static int trident_decode_var(const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info) { struct tridentfb_par * p = (struct tridentfb_par *)par; // struct tridentfb_info * i = (struct tridentfb_info *)info; /* * Get the video params out of 'var'. If a value doesn't fit, round it up, * if it's too big, return -EINVAL. * * Suggestion: Round up in the following order: bits_per_pixel, xres, * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, * bitfields, horizontal timing, vertical timing. */ p->var = *var; p->bpp = var->bits_per_pixel; if (p->bpp == 24 ) p->bpp = 32; p->linelength = var->xres_virtual * p->bpp/8; switch (p->bpp) { case 8: p->var.red.offset = 0; p->var.green.offset = 0; p->var.blue.offset = 0; p->var.red.length = 6; p->var.green.length = 6; p->var.blue.length = 6; break; case 16: p->var.red.offset = 11; p->var.green.offset = 5; p->var.blue.offset = 0; p->var.red.length = 5; p->var.green.length = 6; p->var.blue.length = 5; break; case 32: p->var.red.offset = 16; p->var.green.offset = 8; p->var.blue.offset = 0; p->var.red.length = 8; p->var.green.length = 8; p->var.blue.length = 8; break; default: printk("Wrong bpp\n"); return -EINVAL; } /* convert from picoseconds to MHz */ p->vclk = 1000000/var->pixclock; if (p->bpp == 32) p->vclk *=2; p->hres = var->xres; p->vres = var->yres; /* Compute horizontal and vertical VGA CRTC timing values */ p->htotal = (p->hres + var->left_margin + var->right_margin + var->hsync_len)/8 - 10; p->hdispend = p->hres/8 - 1; p->hsyncstart = (p->hres + var->right_margin)/8; p->hsyncend = var->hsync_len/8; p->hblankstart = p->hdispend + 1; p->hblankend = p->htotal + 5; p->vtotal = p->vres + var->upper_margin + var->lower_margin + var->vsync_len - 2; p->vdispend = p->vres - 1; p->vsyncstart = p->vres + var->lower_margin; p->vsyncend = var->vsync_len; p->vblankstart = p->vres; p->vblankend = p->vtotal +2; return 0; } /* Fill in var from info */ static int trident_encode_var(struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info) { struct tridentfb_par * p = (struct tridentfb_par *)par; *var = p->var; var->bits_per_pixel = p->bpp; return 0; } /* Fill in par from hardware */ static void trident_get_par(void *par, struct fb_info_gen *info) { struct tridentfb_par * p = (struct tridentfb_par *)par; struct tridentfb_info * i = (struct tridentfb_info *)info; *p = i->currentmode; } static int trident_pan_display(const struct fb_var_screeninfo *, struct fb_info_gen *); /* Set the hardware from par */ static void trident_set_par(const void *par, struct fb_info_gen *info) { struct tridentfb_par * p = (struct tridentfb_par *)par; struct tridentfb_info * i = (struct tridentfb_info *)info; unsigned char tmp; i->currentmode = *p; unprotect_all(); crtc_unlock(); enable_mmio(); if (p->hres < 800) { t_outb(0xEB,0x3C2); //misc output reg write3CE(CyberControl,0x81); if (center || p->bpp==32) // if (center) screen_center(); else screen_stretch(); } else { t_outb(0x2B,0x3C2); //misc output reg write3CE(CyberControl,8); //disable H and V shadow regs (X and BIOS value) } #if 0 if (p->hres == 800) write3CE(CyberControl,8); //disable H and V shadow regs (X and BIOS value) else //write3CE(CyberControl,0x87); // write3CE(CyberControl,0x81); // #endif /* vertical timing values */ write3X4(CRTVTotal, p->vtotal & 0xFF); write3X4(CRTVDispEnd, p->vdispend & 0xFF); write3X4(CRTVSyncStart, p->vsyncstart & 0xFF); write3X4(CRTVSyncEnd, (p->vsyncend & 0x0F)); write3X4(CRTVBlankStart, p->vblankstart & 0xFF); write3X4(CRTVBlankEnd, 0/*p->vblankend & 0xFF*/); /* horizontal timing values */ write3X4(CRTHTotal, p->htotal & 0xFF); write3X4(CRTHDispEnd, p->hdispend & 0xFF); write3X4(CRTHSyncStart, p->hsyncstart & 0xFF); write3X4(CRTHSyncEnd, (p->hsyncend & 0x1F) | ((p->hblankend & 0x20)<<2)); write3X4(CRTHBlankStart, p->hblankstart & 0xFF); write3X4(CRTHBlankEnd, 0/*(p->hblankend & 0x1F)*/); /* higher bits of vertical timing values */ tmp = 0x10; if (p->vtotal & 0x100) tmp |= 0x01; if (p->vdispend & 0x100) tmp |= 0x02; if (p->vsyncstart & 0x100) tmp |= 0x04; if (p->vblankstart & 0x100) tmp |= 0x08; if (p->vtotal & 0x200) tmp |= 0x20; if (p->vdispend & 0x200) tmp |= 0x40; if (p->vsyncstart & 0x200) tmp |= 0x80; write3X4(CRTOverflow, tmp); tmp = read3X4(CRTHiOrd) | 0x08; //line compare bit 10 if (p->vtotal & 0x400) tmp |= 0x80; if (p->vblankstart & 0x400) tmp |= 0x40; if (p->vsyncstart & 0x400) tmp |= 0x20; if (p->vdispend & 0x400) tmp |= 0x10; write3X4(CRTHiOrd, tmp); write3X4(HorizOverflow, 0); //no such great xres yet to need bit 9 //cursor stuff for (tmp = 0xA;tmp<0x10;tmp++) write3X4(tmp,0); tmp = 0x40; if (p->vblankstart & 0x200) tmp |= 0x20; write3X4(CRTMaxScanLine, tmp); write3X4(CRTLineCompare,0xff); write3X4(CRTPRowScan,0); write3X4(CRTModeControl,0xc3); write3X4(LinearAddReg,0x20); //enable linear addressing write3X4(CRTCModuleTest,0x80); //enable access extended memory write3X4(GraphEngReg, 0x80); //enable GE for text acceleration acc->init_accel(p->hres,p->bpp); switch (p->bpp) { case 8:tmp=0;break; case 15: case 16:tmp=5;break; case 24: /* tmp=0x29;break; */ /* seems like 24bpp is same as 32bpp when using vesafb */ case 32:tmp=9;break; } write3X4(PixelBusReg, tmp); write3X4(InterfaceSel, 0x5B); //32bit internal data path write3X4(DRAMControl, 0x30); //both IO,linear enable write3X4(Performance, 0xBF); // write3X4(PCIReg,0x7); //MMIO & PCI read and write burst enable set_vclk(p->vclk); write3C4(0,3); write3C4(1,1); //set char clock 8 dots wide write3C4(2,0x0f); //enable 4 maps because needed in chain4 mode write3C4(3,0); write3C4(4,0x0e); //memory mode enable bitmaps ?? //Graphics engine settings write3CE(MiscExtFunc,(p->bpp==32)?0x1A:0x12); //divide clock by 2 if 32bpp write3CE(0x5,0x40); //no CGA compat,allow 256 col WTF??? write3CE(0x6,0x05); //graphics mode write3CE(0x7,0x0f); //planes? writeAttr(0x10,0x41); //graphics mode and support 256 color modes writeAttr(0x12,0xf); //planes writeAttr(0x13,0); //horizontal pel panning //colors for(tmp = 0;tmp <0x10;tmp++) writeAttr(tmp,tmp); readb(fb_info.io_virt + CRT + 0xA); //flip-flop to index t_outb(0x20, 0x3C0); //enable attr switch (p->bpp) { case 8: tmp = 0;break; //256 colors case 15: tmp = 0x10;break; case 16: tmp = 0x30;break; //hicolor case 24: //truecolor case 32: tmp = 0xD0;break; } t_inb(0x3C8); t_inb(0x3C6); t_inb(0x3C6); t_inb(0x3C6); t_inb(0x3C6); t_outb(tmp,0x3C6); t_inb(0x3C8); set_number_of_lines(p->vres); set_lwidth(p->hres*p->bpp/(4*16)); //text_accel = p->var.accel_flags & ACCELF_TEXT; trident_pan_display(&p->var,info); } static int trident_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info) { /* * Read a single color register and split it into colors/transparent. * The return values must have a 16 bit magnitude. * Return != 0 for invalid regno. */ // struct tridentfb_info * i = (struct tridentfb_info *)info; if (regno >255 ) { printk("regno > 255\n"); return -EINVAL; } *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = 0; return 0; } static int trident_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { /* * Set a single color register. The values supplied have a 16 bit * magnitude. * Return != 0 for invalid regno. */ struct tridentfb_info * i = (struct tridentfb_info *)info; int bpp = i->currentmode.bpp; unsigned char r,g,b; if (bpp==8) { r = red&0xff; g = green&0xff; b = blue&0xff; t_outb(regno,0x3C8); t_outb(r,0x3C9); t_outb(g,0x3C9); t_outb(b,0x3C9); } if (regno < 16) { palette[regno].red = red; palette[regno].green = green; palette[regno].blue = blue; } if (bpp == 16) /* RGB 565 */ i->cmap_cfb16[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); else if (bpp == 15) /* RGB 555 */ i->cmap_cfb15[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); else if (bpp == 32) /* ARGB 8888 */ i->cmap_cfb32[regno] = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xff00) >> 8); return 0; } static int trident_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info) { unsigned int offset; struct tridentfb_info * i = (struct tridentfb_info *)info; offset = (var->xoffset + (var->yoffset * var->xres)) * var->bits_per_pixel/32; i->currentmode.var.xoffset = var->xoffset; i->currentmode.var.yoffset = var->yoffset; set_screen_start(offset); return 0; } /* Later */ static int trident_blank(int blank_mode, struct fb_info_gen *info) { return 0; } /* Set display switch used by console */ static void trident_set_disp(const void *par, struct display *disp, struct fb_info_gen *info) { struct tridentfb_info * i = (struct tridentfb_info *)info; struct tridentfb_par * p = (struct tridentfb_par *)par; disp->screen_base = (char *)i->fbmem_virt; #ifdef FBCON_HAS_CFB8 if (p->bpp == 8 ) { if (p->var.accel_flags & FB_ACCELF_TEXT) disp->dispsw = &trident_8bpp; else disp->dispsw = &fbcon_cfb8; } else #endif #ifdef FBCON_HAS_CFB16 if (p->bpp == 16) { if (p->var.accel_flags & FB_ACCELF_TEXT) disp->dispsw = &trident_16bpp; else disp->dispsw = &fbcon_cfb16; disp->dispsw_data =i->cmap_cfb16; /* console palette */ } else #endif #ifdef FBCON_HAS_CFB32 if (p->bpp == 32) { if (p->var.accel_flags & FB_ACCELF_TEXT) disp->dispsw = &trident_32bpp; else disp->dispsw = &fbcon_cfb32; disp->dispsw_data =i->cmap_cfb32; /* console palette */ } else #endif disp->dispsw = &fbcon_dummy; } static struct fbgen_hwswitch trident_hwswitch = { trident_detect, trident_encode_fix, trident_decode_var, trident_encode_var, trident_get_par, trident_set_par, trident_getcolreg, trident_setcolreg, trident_pan_display, trident_blank, trident_set_disp }; /* PCI IDS temporarily here */ #define CYBERBLADEi1 0x8520 #define CYBER9397DVD 0x939A #define CYBER9525DVD 0x9525 #define IMAGE 0 #define BLADE 1 #define is_image() (family == IMAGE) #define is_blade() (family == BLADE) static struct almost_supported_board { int pci_id; int family; struct accel_switch * acc; } asb[] = { {CYBERBLADEi1,BLADE,&accel_blade}, {CYBER9525DVD,IMAGE,&accel_image}, }; static int asb_count = sizeof(asb)/sizeof(asb[1]); static int family; int __init tridentfb_init(void) { int i,j; struct pci_dev * board; for (i = 0;i<asb_count;i++) { if ((board = pci_find_device(PCI_VENDOR_ID_TRIDENT, asb[i].pci_id, NULL))) { family = asb[i].family; acc = asb[i].acc; goto on; } } return -1; on: fb_info.frequency = NTSC; /* MMIO */ fb_info.io = pci_resource_start(board,1); #if 0 if (!request_region(fb_info.io, TRIDENT_IOSIZE, "tridentfb")) { return -1; }; #endif fb_info.io_virt = (unsigned int)ioremap_nocache(fb_info.io, TRIDENT_IOSIZE); if (!fb_info.io_virt) { release_region(fb_info.io, TRIDENT_IOSIZE); return -1; } /* Framebuffer memory */ fb_info.fbmem = pci_resource_start(board,0); fb_info.memsize = get_memsize(); #if 0 if (!request_mem_region(fb_info.fbmem, fb_info.memsize, "tridentfb")) { return -1; } #endif fb_info.fbmem_virt = (unsigned int)ioremap_nocache(fb_info.fbmem, fb_info.memsize); if (!fb_info.fbmem_virt) { release_mem_region(fb_info.fbmem, fb_info.memsize); return -1; } debug("Trident board found : mem = %X,io = %X, mem_v = %X, io_v = %X\n", fb_info.fbmem, fb_info.io, fb_info.fbmem_virt, fb_info.io_virt); fb_info.gen.parsize = sizeof (struct tridentfb_par); fb_info.gen.fbhw = &trident_hwswitch; strcpy(fb_info.gen.info.modename, "Trident"); fb_info.gen.info.changevar = NULL; fb_info.gen.info.node = -1; fb_info.gen.info.fbops = &tridentfb_ops; fb_info.gen.info.disp = &disp; fb_info.gen.info.switch_con = &fbgen_switch; fb_info.gen.info.updatevar = &fbgen_update_var; fb_info.gen.info.blank = &fbgen_blank; fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT; fb_info.gen.info.fontname[0] = '\0'; /* set palette */ for(i=0;i<16;i++) { j = color_table[i]; palette[i].red = default_red[j]; palette[i].green = default_grn[j]; palette[i].blue = default_blu[j]; } unprotect_all(); /* This should give a reasonable default video mode */ //define this until get a modular modedb.Temporary. #if STANDALONE #define fb_find_mode tr_find_mode #endif i = fb_find_mode(&default_var,&fb_info.gen.info,mode,NULL,0,NULL,depth); /* Set to 1 to try accel on 9397DVD */ #define IMAGE_ACCEL 0 if (!noaccel #if !IMAGE_ACCEL && is_blade() #endif ) default_var.accel_flags |= FB_ACCELF_TEXT; trident_decode_var(&default_var, &fb_info.currentmode, &fb_info.gen); fbgen_get_var(&disp.var, -1, &fb_info.gen.info); default_var.activate |= FB_ACTIVATE_NOW; fbgen_do_set_var(&default_var, 1, &fb_info.gen); fbgen_set_disp(-1, &fb_info.gen); fbgen_install_cmap(0, &fb_info.gen); if (register_framebuffer(&fb_info.gen.info) < 0) { printk("Could not register Trident framebuffer\n"); return -EINVAL; } printk(KERN_INFO "fb%d: %s frame buffer device %dx%d-%dbpp\n", GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,default_var.xres, default_var.yres,default_var.bits_per_pixel); return 0; } void __exit tridentfb_exit(void) { unregister_framebuffer(&fb_info.gen.info); iounmap((void *)(fb_info.io_virt)); iounmap((void *)fb_info.fbmem_virt); } /* * Parse user speficied options (`video=tridentfb:') * example: * video=tridentfb:800x600,depth=16,noaccel */ int __init tridentfb_setup(char *options) { char * opt; if (!options || !*options) return 0; printk("trident_setup : %s\n",options); for(opt = strtok(options,",");opt;opt = strtok(NULL,",")){ if (!opt) continue; printk("%s\n",opt); if (!strcmp(opt,"noaccel")) noaccel = 1; else if (!strcmp(opt,"depth=")) depth = simple_strtoul(opt+6,NULL,0); else if (!strcmp(opt,"center")) center = 1; else mode = opt; } return 0; } #if 0 static int tridentfb_open(struct fb_info *fb,int user) { return 1; } static int tridentfb_release(struct fb_info *fb,int user) { return 0; } #endif static struct fb_ops tridentfb_ops = { #if 0 owner:THIS_MODULE, fb_open:tridentfb_open, fb_release:tridentfb_release, #endif fb_get_fix:fbgen_get_fix, fb_get_var:fbgen_get_var, fb_set_var:fbgen_set_var, fb_get_cmap:fbgen_get_cmap, fb_set_cmap:fbgen_set_cmap, fb_pan_display:fbgen_pan_display, }; module_init(tridentfb_init); module_exit(tridentfb_exit); MODULE_AUTHOR("Jani Monoses <jani@...>"); MODULE_LICENSE("GPL"); |
From: <cwright@so...> - 2001-11-27 05:30:44
|
> > Linus dreams of a network transparentancy. I also like that idea. So the > > two things he wants to see go away are mmap and ioctl functionality. In sorry to jump in. i missed this eariler i guess. How can removing something useful like mmap be good? in the name of network transparency perhaps, but it has many uses. I don't know of any other way this type of functionality could be implimented without taking a huge speed hit. (mmapedbuffer[offset] memory write versus read/write/seek wrapper) perhaps a better way of implimenting this can happen? surely removing mmap is not the way to go. I agree that network transparency is a good thing, but perhaps expect applications to check for an mmap failure, and then use read/write fallbacks as necessary. or, (new trend), a local dev fs that indicates devices that are mmap friendly or somethign equally insane. sorry for the rant, i may be completely wrong. chris |
From: Sottek, Matthew J <matthew.j.sottek@in...> - 2001-11-27 01:06:38
|
>Set the fb_fix fields for mmio and smem to zero. As for internally with >the new api you don't need to use the screen_base field. >Just ignore it. After further review (correct me If I am wrong James) it seems that screen base (a kernel virtual address to the framebuffer) is needed for the fb_read and fb_write functions. It was suggested that there isn't a way around this. I have to differ. It seems that in order to make writing a fb driver easy, sometimes the fb interface layer pretends it is a driver and makes direct access to the device. This is another case where this just isn't the right thing to do for everyone. You have to allow for a driver to be created that does ALL the driver work itself. I think the base set of fb interfaces should include: fb_put: Put data from somewhere into the framebuffer. This is called imageblit in the new API. This should have a parameter to tell you to use copy_from_user() or memcpy() fb_get: Get data from the framebuffer and put it in a provided pointer. This should have a flag to tell you to use copy_to_user() or memcpy() fb_set: Set a region of the frambuffer with the value provided. This is called fillrect(?) in the new api. I have thought of a compromise that should be very easy for most drivers to do, and will allow us to keep the driver private stuff hidden. void init_generic_ops(&my_fb_info,fb_base,fb_size,fb_pitch); void destroy_generic_ops(&my_fb_info); This stores the base,size,pitch information in a hidden data structure that is used for all generic function implementations. This structure could be static to the generic ops code or could be passed around in some context structure, but shouldn't be directly accessible by drivers. Here is some example code: /* fb_private.h */ struct fb_generic { u8 *fb_base; u32 size; u32 pitch; anything else? } struct fb_context { struct fb_generic generic; other stuff? } fb_context *fb_get_context(u32 node); /* fb_private.c */ static struct fb_context[MAX_FRAMEBUFFERS]; fb_context *fb_get_context(u32 node) { return &fb_context[node]; } /* fb_generic.c */ #include <fb_private.h> void init_generic_ops(struct fb_info *info,u8 *fb_base, u32 size, u32 pitch) { struct fb_context *context = fb_get_context(fb_info->node); context->generic.fb_base = fb_base; context->generic.fb_size = fb_size; context->generic.fb_pitch = fb_pitch; } /* somewhere in fbmem.c */ ... Break down the read into an offset and size. ... if(!fb->fb_read) { struct fb_context *context = fb_get_context(info->node); generic_fb_read(offset, size, &context->generic, COPY_TO_USER); } else { fb->fb_read(offset, size, info->par, COPY_TO_USER); } The only thing a driver would have to do is leave the fb_put,fb_set, fb_get == NULL and call init_generic_ops() whenever their framebuffer changes size, pitch or location. Then, once we have a context, we can hide anything in there that should not be seen by the driver or the kernel (outside the fb interface) or users. -Matt |
From: Sottek, Matthew J <matthew.j.sottek@in...> - 2001-11-26 16:57:49
|
>> With modedb it wouldn't be that much of a big step. >But then we need to keep the mode database in memory. I think that >belongs in userspace. I struggle with this too. On one hand no one wants to put tables in nonswappable kernel memory. On the other hand, if the tables are in user space, you loose the ability of the kernel to provide a "safe" mode setting interface. The only way to guarantee that no user can set an unsafe mode is to negotiate the mode between the driver and the display device at the kernel level and then prohibit any unsafe modes. This is why I advocate that each driver have it's own modes table, which can be built from a standard set, or from the drivers own needs. In this way the size of the table is minimized to just those that are being used by the driver. so NOT this: mode_t my_modes = standard_modes_table; but more like this: mode_t my_modes = filter_standard_modes(&some_criteria); and then the standard modes table is freed after init. __initdata takes care of that right? Of course, drivers needn't use the mode tables at all if they have some better way of coming up with the modes they will support without getting into the "too many permutations to test" scenario. In the driver I'm working on I have separated "mode" from "timings". mode == The framebuffer mode. depth,pitch,size this is the stuff that alters rendering. timings == Display setup. The display width, height, margins and offsets. Timings can be set independent of the mode without flushing out the rendering pipeline (physically or virtually speaking), no need to blank the screen or refresh the data in the framebuffer. Modes cannot be set without setting the timings too since it is likely that the new mode will require a different set of timings. Keeping these two separate makes the code clean, and keeps the tables smaller. i.e. (modes + timings) < (modes * timings) -Matt |
From: Geert Uytterhoeven <geert@li...> - 2001-11-26 10:01:50
|
On Sat, 24 Nov 2001, James Simmons wrote: > > > Yes. For example floating point support in the kernel. I'd like to know > > > how you'll persuade driver to know that '640x480-YUV422@...' should be > > > NTSC 800x525 interlaced picture, and how you'll center picture on screen > > > then? Where do you specify virtual xres and yres? > > > > > Your overthinking it. For one, as long as modes are in a consistent format, > > it's easy for anyone to parse. And since people are already used to the > > "640x480-16@..." style format, what's the big deal? > > With modedb it wouldn't be that much of a big step. But then we need to keep the mode database in memory. I think that belongs in userspace. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@... In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds |
From: Petr Vandrovec <vandrove@vc...> - 2001-11-26 02:31:49
|
On Sat, Nov 24, 2001 at 10:29:36PM -0800, James Simmons wrote: > > As far as virtual xres and yres.. keep in mind this is a virtual filesystem.. > > if your driver or subsystem has additional needs, you can simply register a > > new entry to deal with virtual resolution.. If you want a place for virtual > > resolution.. something like: > > > > /dev/gfx/card0/frame0/resolution_virt > > > > should suffice just fine. (Name pending). > > Okay I see people got confussed over the ASCII thing. Yes Linus wants > ioctls to go away. There have been huge ioctl clashes in the past. Plus > Linus dreams of a network transparentancy. I also like that idea. So the > two things he wants to see go away are mmap and ioctl functionality. In > its place you create a file to represent the functionality of the device > and that you can read and write data to so its behavior changes. This data > can be binary or ASCII. It just has to be passed in via read and write. Do not forget that current API is atomic, with doing it in multiple steps you can get nasty surprises (as resolution and resolution_virt depends one on another, either changing one changes also another one, or some modes are not accessible without first modifying resolution_virt), besides not being atomic... And AFAIK Al Viro (main ioctl killer) does not require that every current fb_*_info field should have its own file. From his posts I understand that he is completely satisfied with just some text-based extensible API, so ( echo "mode=1024x768-16@...,outputfmt=NTSC,vxres=2048,xoffset=141" >&0 read a echo $a ) <> /dev/fb0/control' would be enough for him... As there is already couple of comma separated list parsers in the kernel (mount options, kernel cmdline), I think that it is preferred format - in simplest form you write one line in, and get one line back... Best regards, Petr Vandrovec vandrove@... |
From: Michel <michdaen@ii...> - 2001-11-25 12:20:35
|
On Fri, 2001-11-23 at 21:20, Carl Perry wrote: > video=3Dvesafb:800x600 > video=3Dvesafb:800x600-24@... > video=3Dvesafb:800x600-16@... vesafb doesn't work like that, see linux/Documentation/fb/vesafb.txt. --=20 Earthling Michel D=E4nzer (MrCooper)/ Debian GNU/Linux (powerpc) developer XFree86 and DRI project member / CS student, Free Software enthusiast |
From: James Simmons <jsimmons@tr...> - 2001-11-25 06:29:50
|
> > Yes. For example floating point support in the kernel. I'd like to know > > how you'll persuade driver to know that '640x480-YUV422@...' should be > > NTSC 800x525 interlaced picture, and how you'll center picture on screen > > then? Where do you specify virtual xres and yres? > > > Your overthinking it. For one, as long as modes are in a consistent format, > it's easy for anyone to parse. And since people are already used to the > "640x480-16@..." style format, what's the big deal? With modedb it wouldn't be that much of a big step. > As far as virtual xres and yres.. keep in mind this is a virtual filesystem.. > if your driver or subsystem has additional needs, you can simply register a > new entry to deal with virtual resolution.. If you want a place for virtual > resolution.. something like: > > /dev/gfx/card0/frame0/resolution_virt > > should suffice just fine. (Name pending). Okay I see people got confussed over the ASCII thing. Yes Linus wants ioctls to go away. There have been huge ioctl clashes in the past. Plus Linus dreams of a network transparentancy. I also like that idea. So the two things he wants to see go away are mmap and ioctl functionality. In its place you create a file to represent the functionality of the device and that you can read and write data to so its behavior changes. This data can be binary or ASCII. It just has to be passed in via read and write. |
From: James Simmons <jsimmons@tr...> - 2001-11-25 05:51:21
|
> No I wasn't talking about anything that complex. I just don't want > userland or anyone outside my driver using the pointers I am required > to provide. I'm just going to set them all to zero, and whatever falls > over needs to be fixed. Set the fb_fix fields for mmio and smem to zero. As for internally with the new api you don't need to use the screen_base field. Just ignore it. > It isn't like the > kernel gives you full access but will kill you if you do something > wrong, there is no interface to allow you to do something wrong in > the first place. > > I think the kgi does more of what you are talking about here. No KGI works just the way you described DRI does. KGI uses a metadata system to render graphics commands. Basically you can create data packets of what you want done and send it out. The kernel interpets the data and executes it safely. Well okay KGI takes it a step further than DRI. The method I described is the way IRIX handles it on SGI systems. |
From: James Simmons <jsimmons@tr...> - 2001-11-25 05:42:57
|
> I agree that EDID needs to be supported, but the data structures could > be a slight superset of EDID. All the matters is that the information > isn't lost. EDID is certainly a good example of what needs to be > represented by whatever the final data structure is. Agree. I just want to make sure we can support platforms with their own vanilla thing. You just never know. > I also advocate the ability to populate the EDID data structure from > user-space, which _could_ include a specific set of timings. That was what fbmon.c was supposed to do. Never got around to it. Now that 2.5.X is here we can start banging away at it. > Why would I want to make a human readable interface? Because linus wants ioctls to go away in 2.5.X. > Most high end features are going to > remain device specific and should only be used via a userspace library. No doubt about that. I have only ever advocated resource management between processes, not programming hardware in the kernel. Hm. I don't know how Linus expects me to figure out a ASCII only interface to graphics hardware. Anyways that is way down the road. |
From: Paul Mundt <lethal@ChaoticDreams.ORG> - 2001-11-25 05:40:35
|
On Sun, Nov 25, 2001 at 02:34:33AM +0100, Petr Vandrovec wrote: > Are you sure that this is really needed? You are not inventing API for ne= xt > 20 years. You are inventing API now, for current products. You can change > API anytime in future, and API will definitely change, as it already > changed in the past. Also EDID is so universal that you can express > almost everything using that, and also do not forget that there exist > bidirectional channel (DDC2B+/DDC2AB) between videocard and monitor, and > that this bidirectional communication may be required for proper operation > (i.e. enabling) of USB/IEEE1394 ports built into monitor. > =20 VBE DDC is something else to consider as well.. > > /dev/gfx/card0/frame0/resolution > > /endian > > /frame > > =09 > > To change the resolution of a framebuffer we can do a=20 > >=20 > > cat "640x480-16@..." > /dev/gfx/card0/frame0/resolution. =20 > >=20 > > As you can see with this new design we have alot more flexiablity. Lots= of > > other nice features but this is down the road. >=20 > Yes. For example floating point support in the kernel. I'd like to know= =20 > how you'll persuade driver to know that '640x480-YUV422@...' should be= =20 > NTSC 800x525 interlaced picture, and how you'll center picture on screen > then? Where do you specify virtual xres and yres? > =20 Your overthinking it. For one, as long as modes are in a consistent format, it's easy for anyone to parse. And since people are already used to the "640x480-16@..." style format, what's the big deal? As far as virtual xres and yres.. keep in mind this is a virtual filesystem= .. if your driver or subsystem has additional needs, you can simply register a new entry to deal with virtual resolution.. If you want a place for virtual resolution.. something like: /dev/gfx/card0/frame0/resolution_virt should suffice just fine. (Name pending). Regards, --=20 Paul Mundt <lethal@...> |
From: James Simmons <jsimmons@tr...> - 2001-11-25 05:30:46
|
> Are you sure that this is really needed? You are not inventing API for next > 20 years. You are inventing API now, for current products. You can change > API anytime in future, and API will definitely change, as it already > changed in the past. Also EDID is so universal that you can express > almost everything using that, and also do not forget that there exist > bidirectional channel (DDC2B+/DDC2AB) between videocard and monitor, and > that this bidirectional communication may be required for proper operation > (i.e. enabling) of USB/IEEE1394 ports built into monitor. As pointed out their should exist a supset that EDID is apart of. I don't want to run into a issues of some platform using something else that works just as well. I like to think functionality. This kind of thinking will go further. > And our monitors will do plop and disappear? We are using 12 years old > monitors for some tasks, and we'll not throw them away before they'll > physically stop functioning. The reality is if you write the drivers correctly you can have drivers that do the timing for you. Yes you would have to supply the data for the monitor attached before. Their exist receipes for this. > Yes. For example floating point support in the kernel. I'd like to know > how you'll persuade driver to know that '640x480-YUV422@...' should be > NTSC 800x525 interlaced picture, and how you'll center picture on screen > then? Where do you specify virtual xres and yres? Don't shot me. Linus has pointed out that ioctls are to go away in 2.5.X. > > Agree. This will change. Plus the gfx interface I mention above wil be my > > attempt to combine DRI and fbdev. > > There are drivers which support text modes - and if your new API will not > support them... well, you'll have to create another API. Wrong. You create another console driver. Take a look at the STI console code for the PARISC platform. A excellent example. Core code which has a fbdev driver on top for graphcis modes and a sticon for using a text mode from the ROM. Using fbdev for text modes is way to much overhead. Using struct consw only is much lighter in weight. The aim here is to remove bloat. Plus the console code will be removed from all low level drivers period. The embedded industry demands it. I know since I work in it. In the console project we have NVIDIA text console driver. For matrox you could have a matroxcon. Very simple and very sweet. > It is something else. You can have two CRTCs (== two /dev/fb*), four > outputs (analog VGA #1, analog VGA #2, digital FP #1 and TVOut #1) of > which 2 or 3 can be active at one time, and a scaler which can insert > third picture into one of outputs... API should at least provide > universal way for enumerating device outputs and finding dependencies > between /dev/fb* (i.e. /dev/fb0 shares memory with /dev/fb1, and > /dev/fb2 shares memory and outputs with /dev/fb3). The struct xxx_par represents the hardware state. This encompesses the entire board. So you would place everthing in there. struct fb_info represents one framebuffer and its properties. Thats all. Very simple and very clean. |
From: Matt Sottek <mattsottek@ho...> - 2001-11-25 04:58:36
|
>Are you sure that this is really needed? You are not inventing API >for next 20 years. You are inventing API now, for current products. >You can change API anytime in future, and API will definitely >change, as it already changed in the past. Also EDID is so >universal that you can express almost everything using that, and >also do not forget that there exist bidirectional channel >(DDC2B+/DDC2AB) between videocard and monitor, and that this >bidirectional communication may be required for proper operation >(i.e. enabling) of USB/IEEE1394 ports built into monitor. I agree that EDID needs to be supported, but the data structures could be a slight superset of EDID. All the matters is that the information isn't lost. EDID is certainly a good example of what needs to be represented by whatever the final data structure is. >> > * The user api needs to move away from timings all together. >> > The user should be able to select a refresh rate from a provided >> > list (negotiated between monitor and driver). It won't be long >> > before timings are no longer used in hardware, and the only thing >> > left to adjust will be refresh. >And our monitors will do plop and disappear? We are using 12 years old >monitors for some tasks, and we'll not throw them away before they'll >physically stop functioning. I wasn't saying that at all. I am just talking about the user visible api. User applications don't need to concern themselves with timings. The driver should be able to do the right thing with historical VESA timing sets, timing algorithms, and EDID like information. Timings should just be hidden from the user. I also advocate the ability to populate the EDID data structure from user-space, which _could_ include a specific set of timings. Think of this scenario. A Monitor with no EDID, the driver probably has to assume a standard VGA monitor that can do only 60hz at say 10x7. The user would have to have the ability to override the monitor specs and provide a timing range or specific timing sets. The driver, which should be giving priority to the timings from the Monitor, would then choose the user supplied timings. But, for the average case where the default timings are fine or the monitor provided EDID information. The whole thing "just works" without the user knowing anything more than the resolution depth and possibly refresh. >> /dev/gfx/card0/frame0/resolution >> /endian >> /frame >> > To change the resolution of a framebuffer we can do a >> > cat "640x480-16@..." > /dev/gfx/card0/frame0/resolution. >> > As you can see with this new design we have alot more flexiablity. Lots of >> other nice features but this is down the road. >Yes. For example floating point support in the kernel. I'd like to know >how you'll persuade driver to know that '<EMAIL: PROTECTED>' should be >NTSC 800x525 interlaced picture, and how you'll center picture on >screen then? Where do you specify virtual xres and yres? I'm with Petr here. If this is the interface for mode setting you've got problems. Why would I want to make a human readable interface? So an application can convert the parameters it wants to ascii to pass them to the kernel who then parses and decodes an ascii command packet to get the data back? What benefit is this? Ascii interfaces are great for OUTPUT, and even then, only if the data is useful in a shell. I don't think the complex set of interactions that are involved in negotiating a set of timings and the framebuffer mode are a good fit for a single directional ascii interface. Plus this is a slippery slope, are you planning on using this type interface for cursor position? Certainly I would prefer an optimized ioctl path over a text based one for anything that happens on a regular basis. I can see having the gfx filesystem for things that can be done in a shell. cat /dev/gfx/something/fb > screenshot.tiff seems reasonable. cat /dev/gfx/something/mode is reasonable too, but only for human reading. No application should be required to parse the ascii output just to get the resolution/depth/acceleration information. If that were the case you'd have to make a library to do it, since surely all the fb applications wouldn't want to write their own parser... and if you were going to write a library why wouldn't you just use an ioctl which could do it without going kernel:data->kernel:ascii->user:ascii->user:data > API should at least provide >universal way for enumerating device outputs and finding dependencies >between /dev/fb* (i.e. /dev/fb0 shares memory with /dev/fb1, and >/dev/fb2 shares memory and outputs with /dev/fb3). You are correct, there is probably a clean interface to be had in the case I mentioned. I was simply observing that currently if any driver ever needed a variable of any kind it was stuffed in "fix" or "var" or "display" which are now all hopelessly full of garbage that is meaningless in 90% of the use cases for those structures. A reset is needed and this time don't make a set of bits or a well defined ioctl or a variable for every little feature. Most high end features are going to remain device specific and should only be used via a userspace library. Think openGL. you can't have all 3d apps calling directly down to a triangle function that is different for each set of hardware, and you can't make the kernel do the work to convert between a standard API and the hardware implementation. The solution is to just export a device specific API from the kernel and make the standard API (opengl) in userland. -Matt |
From: Petr Vandrovec <vandrove@vc...> - 2001-11-25 02:01:02
|
On Sat, Nov 24, 2001 at 08:52:09AM -0800, James Simmons wrote: > > something special that I can support. To aid in code reuse you > > should just provide a function that parses EDID data into an > > edid data structure (Something like this was discussed a few > > day ago) > > Most defintely. That was what fbmon.c was for. Unfortunely I never had the > time to work on it. Now that 2.5.0 is out I'm going to figure something > out. I did see the patch sent out and I'm going to start with that. I just > like to make monitor stuff EDID independent. I don't want to be stuck with > this api for the next 20 years especially when the technology will change. Are you sure that this is really needed? You are not inventing API for next 20 years. You are inventing API now, for current products. You can change API anytime in future, and API will definitely change, as it already changed in the past. Also EDID is so universal that you can express almost everything using that, and also do not forget that there exist bidirectional channel (DDC2B+/DDC2AB) between videocard and monitor, and that this bidirectional communication may be required for proper operation (i.e. enabling) of USB/IEEE1394 ports built into monitor. > > * The user api needs to move away from timings all together. > > The user should be able to select a refresh rate from a provided > > list (negotiated between monitor and driver). It won't be long > > before timings are no longer used in hardware, and the only thing > > left to adjust will be refresh. And our monitors will do plop and disappear? We are using 12 years old monitors for some tasks, and we'll not throw them away before they'll physically stop functioning. > /dev/gfx/card0/frame0/resolution > /endian > /frame > > To change the resolution of a framebuffer we can do a > > cat "640x480-16@..." > /dev/gfx/card0/frame0/resolution. > > As you can see with this new design we have alot more flexiablity. Lots of > other nice features but this is down the road. Yes. For example floating point support in the kernel. I'd like to know how you'll persuade driver to know that '640x480-YUV422@...' should be NTSC 800x525 interlaced picture, and how you'll center picture on screen then? Where do you specify virtual xres and yres? > > graphics driver and isn't appealing as a base driver to expand > > on. > > Agree. This will change. Plus the gfx interface I mention above wil be my > attempt to combine DRI and fbdev. There are drivers which support text modes - and if your new API will not support them... well, you'll have to create another API. > > #3 Don't try to wrap everything in a hardware independent API. Some > > hardware is going to support things that others don't. Take for > > instance "mirroring". The i810 can do this on the CRT + a TV or > > FP depending on what is connected. But the modes that can be > > supported are very limited and mucking up a mode API with this > > This is what struct fb_info.par is for. It is the hardware dependent > structure in struct fb_info. If you have more than one frmaebuffer on the > graphics card then you have 2 struct fb_info that share the same par. Now > if one attempts to set the graphics mode that both can't support at the > same time since they share the same par they will know before hand. That > is what fb_check_var is for. It is something else. You can have two CRTCs (== two /dev/fb*), four outputs (analog VGA #1, analog VGA #2, digital FP #1 and TVOut #1) of which 2 or 3 can be active at one time, and a scaler which can insert third picture into one of outputs... API should at least provide universal way for enumerating device outputs and finding dependencies between /dev/fb* (i.e. /dev/fb0 shares memory with /dev/fb1, and /dev/fb2 shares memory and outputs with /dev/fb3). Best regards, Petr Vandrovec vandrove@... |
From: Matt Sottek <mattsottek@ho...> - 2001-11-25 01:04:02
|
> > No doubt, as you state, there are applications that would need the > > physical framebuffer address. The problem is that when you just leave > > a pointer laying around in a public data structure there is no way > > for a user application to know when the pointer is valid and when it > > is not. If a unsuspecting TV capture card tried to use my physical > > address without knowing that I only have 64k banks the whole system > > would come down hard. > > Ah. You are talking about having a real RRM (rendering resource manager). > When a process open /dev/fb or DRI it should be registered with the RRM. > Then when someone does something global like change the graphics > resolution the RRM sends a signal to all the processes that are using the > graphics card resources. As for the 64k bank sitution you can use VM > tricks to make it appeard linear to userland. If you something really > bizarre then you add something on the order of: > No I wasn't talking about anything that complex. I just don't want userland or anyone outside my driver using the pointers I am required to provide. I'm just going to set them all to zero, and whatever falls over needs to be fixed. > > MMio is a very different animal. Most mmio regions are not safe for > > untrusted userspace binaries to access. This is why such access is > > limited to root. Further there is no generic use for these mmio regions, > > only a userspace driver would know what to do with them. Certainly a > > userspace driver and kernelspace driver that are working together should > > be able to work out a way to share the locations they need without > > leaving them lay around in public. > > It doesn't have to be root. DRI allows normal clients to use the MMIO > regions. The key is that you have a RRM that is the guardian angel. If a > process does the naughty you kill it and reset the accel engine. > No it doesn't. The DRM only allows clients to map regions that are safe. This doesn't include the mmio registers for most cards. The drm provides safe interfaces to do dma and dispatch commands. It doesn't just let clients touch the registers. For instance on i810 you can map a dma buffer into the client but in order to dispatch a command the kernel unmaps the buffer from the client writes the instruction to the dma buffer and then dispatched the buffer. It isn't safe on i810 to allow the client full access even to the dma buffers. It isn't like the kernel gives you full access but will kill you if you do something wrong, there is no interface to allow you to do something wrong in the first place. I think the kgi does more of what you are talking about here. -Matt |
From: James Simmons <jsimmons@tr...> - 2001-11-24 18:20:31
|
I broke the patche up into a few patches. Basically I have added a new generic framebuffer system (fbgen2.c). To convert to this new gen layer you need to do a few things. 1) Get ride of your struct fb_info_xxx { ...excess junk ... struct fb_info *info; .. more excess junk... } Instead use a struct xxx_par { /* All driver specific data. */ } statci struct xxx_par default_par; struct fb_info info; xxxfb_init() { .... info.par = default_par; .... } Trust me. This will make for a much cleaner more transparent system. I have done several drivers this way. In this design par is only avaliable to the local driver. The upper fbdev and fbcon code doesn't know about it. 2) New function pointers have been added into struct fb_ops. They are int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info) The above function validates a graphics resolution. It does NOT alter the hardware state in xxx_par. int (*fb_set_par)(struct fb_info *info); This above function sets the hardware state according to the new var which is placed into struct fb_info in the upper layers. So all you have to pass into this function is info. Par which is always the current hardware state so it is always in info. int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info); This is to kill the stupidity of passing around the function pointer to setcolreg to fb_set_cmap. Since we use the cmap field in struct fb_info this makes the need for fb_get_cmap go away :-). Also the info->palette crap can finally go away. Here is the patch and code to fbgen2.c. Please review it as I plan to send it to Linus with Geert's blessing. /* * linux/drivers/video/fbgen2.c -- Generic routines for frame buffer devices * * Created 27 June 2001 by "Crazy" James Simmons <jsimmons@...> * * 2001 - Documented with DocBook * - Brad Douglas <brad@...> * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. */ #include <linux/module.h> #include <linux/string.h> #include <linux/tty.h> #include <linux/fb.h> #include <linux/slab.h> #include <asm/uaccess.h> #include <asm/io.h> #include <video/fbcon.h> /** * fbgen_set_disp - set generic display * @con: virtual console number * @info: generic frame buffer info structure * * Sets a display on virtual console @con for device @info. * */ void fbgen2_set_disp(int con, struct fb_info *info) { struct display *display; if (con >= 0) display = &fb_display[con]; else display = info->disp; /* used during initialization */ display->screen_base = info->screen_base; display->var = info->var; display->visual = info->fix.visual; display->type = info->fix.type; display->type_aux = info->fix.type_aux; display->ypanstep = info->fix.ypanstep; display->ywrapstep = info->fix.ywrapstep; display->line_length = info->fix.line_length; if (info->blank || info->fix.visual == FB_VISUAL_PSEUDOCOLOR || info->fix.visual == FB_VISUAL_DIRECTCOLOR) display->can_soft_blank = 1; else display->can_soft_blank = 0; #if 0 /* FIXME: generic inverse is not supported yet */ display->inverse = (info->fix.visual==FB_VISUAL_MONO01 ? !inverse : inverse); #else display->inverse = info->fix.visual == FB_VISUAL_MONO01; #endif switch (info->var.bits_per_pixel) { #ifdef FBCON_HAS_CFB4 case 4: display->dispsw = &fbcon_cfb4; break; #endif #ifdef FBCON_HAS_CFB8 case 8: display->dispsw = &fbcon_cfb8; break; #endif #ifdef FBCON_HAS_CFB16 case 12: case 16: display->dispsw = &fbcon_cfb16; display->dispsw_data = info->pseudo_palette; break; #endif #ifdef FBCON_HAS_CFB32 case 32: display->dispsw = &fbcon_cfb32; display->dispsw_data = info->pseudo_palette; break; #endif default: display->dispsw = &fbcon_dummy; break; } } /* ---- `Generic' versions of the frame buffer device operations ----------- */ /** * fbgen_get_fix - get fixed part of display * @fix: fb_fix_screeninfo structure * @con: virtual console number * @info: frame buffer info structure * * Get the fixed information part of the display and place it * into @fix for virtual console @con on device @info. * * Returns negative errno on error, or zero on success. * */ int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { *fix = info->fix; return 0; } /** * fbgen_get_var - get user defined part of display * @var: fb_var_screeninfo structure * @con: virtual console number * @info: frame buffer info structure * * Get the user defined part of the display and place it into @var * for virtual console @con on device @info. * * Returns negative errno on error, or zero for success. * */ int fbgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { if (con == info->currcon) var = &info->var; else var = &fb_display[con].var; return 0; } /** * fbgen_set_var - set the user defined part of display * @var: fb_var_screeninfo user defined part of the display * @con: virtual console number * @info: frame buffer info structure * * Set the user defined part of the display as dictated by @var * for virtual console @con on device @info. * * Returns negative errno on error, or zero for success. * */ int fbgen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { struct fb_bitfield oldred, oldgreen, oldblue, oldalpha; int oldbpp, err; if (memcmp(&info->var, var, sizeof(var)) || con < 0) { if ((err = info->fbops->fb_check_var(var, info))) return err; if (var->activate & FB_ACTIVATE_ALL) info->disp->var = *var; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { oldbpp = info->var.bits_per_pixel; oldred = info->var.red; oldblue = info->var.blue; oldgreen = info->var.green; oldalpha = info->var.transp; if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); info->var = *var; fbgen2_set_disp(con, info); if (info->changevar) (*info->changevar)(con); if (oldbpp != var->bits_per_pixel || memcmp(&oldred,&info->var.red,sizeof(oldred)) || memcmp(&oldgreen,&info->var.green,sizeof(oldgreen)) || memcmp(&oldblue, &info->var.blue, sizeof(oldblue)) || memcmp(&oldalpha,&info->var.transp,sizeof(oldalpha))){ if ((err = fb_alloc_cmap(&info->cmap, 0, 0))) return err; fb_set_cmap(&info->cmap, 1, info->fbops->fb_setcolreg, info); } } var->activate = 0; } return 0; } /** * fbgen_get_cmap - get the colormap * @cmap: frame buffer colormap structure * @kspc: boolean, 0 copy local, 1 put_user() function * @con: virtual console number * @info: frame buffer info structure * * Gets the colormap for virtual console @con and places it into * @cmap for device @info. * * Returns negative errno on error, or zero for success. * */ int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { struct fb_cmap *dcmap; if (con == info->currcon) dcmap = &info->cmap; else dcmap = &fb_display[con].cmap; fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2); return 0; } /** * fbgen_set_cmap - set the colormap * @cmap: frame buffer colormap structure * @kspc: boolean, 0 copy local, 1 get_user() function * @con: virtual console number * @info: frame buffer info structure * * Sets the colormap @cmap for virtual console @con on * device @info. * * Returns negative errno on error, or zero for success. * */ int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { struct fb_cmap *dcmap; int err = 0; if (con == info->currcon) dcmap = &info->cmap; else dcmap = &fb_display[con].cmap; /* no colormap allocated? */ if (!dcmap->len) err = fb_alloc_cmap(dcmap, 256, 0); if (!err && con == info->currcon) err = fb_set_cmap(cmap, kspc, info->fbops->fb_setcolreg, info); if (!err) fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); return err; } /** * fbgen_update_var - update user defined part of display * @con: virtual console number * @info: frame buffer info structure * * Updates the user defined part of the display ('var' * structure) on virtual console @con for device @info. * This function is called by fbcon.c. * * Returns negative errno on error, or zero for success. * */ int fbgen_update_var(int con, struct fb_info *info) { int err = 0; if (info->fbops->fb_pan_display) err = info->fbops->fb_pan_display(&fb_display[con].var,con,info); return err; } /** * fbgen_switch - switch to a different virtual console. * @con: virtual console number * @info: frame buffer info structure * * Switch to virtuall console @con on device @info. * * Returns zero. * */ int fbgen_switch(int con, struct fb_info *info) { struct display *disp; struct fb_cmap *cmap; if (con == info->currcon) return 0; if (info->currcon >= 0) { disp = fb_display + info->currcon; /* * Save the old colormap and video mode. */ disp->var = info->var; if (disp->cmap.len) fb_copy_cmap(&info->cmap, &disp->cmap, 0); } info->currcon = con; disp = fb_display + con; if (disp->cmap.len) cmap = &disp->cmap; else cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); fb_copy_cmap(cmap, &info->cmap, 0); info->var = disp->var; info->var.activate = FB_ACTIVATE_NOW; fbgen_set_var(&info->var, con, info); return 0; } --- linux-2.5.0/include/linux/fb.h Fri Nov 23 23:01:48 2001 +++ linux/include/linux/fb.h Sat Nov 24 11:02:04 2001 @@ -283,6 +283,13 @@ /* set colormap */ int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info); + /* checks var and creates a par based on it */ + int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); + /* set the video mode according to par */ + int (*fb_set_par)(struct fb_info *info); + /* set color register */ + int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, struct fb_info *info); /* pan display (optional) */ int (*fb_pan_display)(struct fb_var_screeninfo *var, int con, struct fb_info *info); @@ -323,6 +330,7 @@ void *pseudo_palette; /* Fake palette of 16 colors and the cursor's color for non palette mode */ + int currcon; /* Current console for fbdev */ /* From here on everything is device dependent */ void *par; }; @@ -400,6 +408,7 @@ extern int fbgen_switch(int con, struct fb_info *info); extern void fbgen_blank(int blank, struct fb_info *info); +extern void fbgen2_set_disp(int con, struct fb_info *info); /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); |
From: James Simmons <jsimmons@tr...> - 2001-11-24 17:58:53
|
> > Tried it out. It didn't work for mach 64 card I have. It is really old. I > > have a 210888GX00 with a spectra DAC 2146886000. So it didn't detect it > > :-( > > That's normal. Support for Mach64GX is very limited due to the many choices of > external DACs and clockchips. You could add support for the spectra DAC, > though. I pan to. Especially since I want to port that driver over to the new api now that 2.5.X is out. |
From: James Simmons <jsimmons@tr...> - 2001-11-24 17:42:03
|
> >Yes, that's what I did for atyfb (experimental 565 patch which doesn't work > >very well yet :-( > > Ok, well, it doesn't quite work yet but I suspect some X brokenness here. > > I'll got that fixed in both radeonfb and aty128fb this week-end hopefully. Can you pass along the fix to me. I recently rewrote the aty128fb driver for 2.5.X for the new api. I like to intergrate that fix into the driver. |
From: James Simmons <jsimmons@tr...> - 2001-11-24 17:24:50
|
> DMA is not useable outside of the DRI anyway for now, or do you know of any > userland app doing this ? Nope. Do to the lack of docs on programming the api you haven't seen anything done. > I guess you need to have root access to the fbdev or something such to be able > to do dma, not sure though. No root!!! If the RRM is design right you don't need root. Well except for the master node (SGI terminology) that controls the global state. For example root would only change the resolution since this can affect every client using the accel engine. Even that I think doesn't have to be root. > Anyway, even X is not able to do DMA outside of the DRI setup. I would have > liked it when writing Xv support for the permedia3 chip. That sucks :-( |
From: James Simmons <jsimmons@tr...> - 2001-11-24 17:21:14
|
> >> Currently mmio and fb pointers are in a PUBLIC data structure, a data > >> structure that is defined for everyone using the fb interfaces, both > >> kernel side and user side. > > >That is so you can do things like use the physical memory address of > >the framebuffer to display a image from a TV card into it. > > No doubt, as you state, there are applications that would need the > physical framebuffer address. The problem is that when you just leave > a pointer laying around in a public data structure there is no way > for a user application to know when the pointer is valid and when it > is not. If a unsuspecting TV capture card tried to use my physical > address without knowing that I only have 64k banks the whole system > would come down hard. Ah. You are talking about having a real RRM (rendering resource manager). When a process open /dev/fb or DRI it should be registered with the RRM. Then when someone does something global like change the graphics resolution the RRM sends a signal to all the processes that are using the graphics card resources. As for the 64k bank sitution you can use VM tricks to make it appeard linear to userland. If you something really bizarre then you add something on the order of: #define FB_AUX_TEXT_MDA 0 /* Monochrome text */ #define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ #define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */ #define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 This tells userland youhave something weird so watch out. > memory of some type for dma command buffers. Most chips cannot safely > give you full access to such memory areas. The sysmem_start and > sysmem_length seem to cover the whole graphics region, not just the > visible framebuffer. This is likely not safe. Then the driver is broken. This wouldn't be a first :-( > Mmap IS a driver interface. I can do all kind of tricks in the driver to > make sure a user who mmaps the framebuffer only gets access to what they > are supposed to. In my stolen memory driver I have zero-page fault > handlers to map and unmap regions while changing memory banks on the > fly. Nice tricks. > I can't do this when the kernel dereferences a kernel-virtual > address as is done in the logo code. There is no page fault handler for > me to catch. Don't worry this will go away in 2.5.X. The virtual poniter will remain for cards that need it, lacking any kind of acceleration. Since most cards are acclerated, even most embedded chips, the virtual pointer becomes optional. That is the key point. It is optional. That pointer then is only accessed in the software emulated accel functions that are needed. > MMio is a very different animal. Most mmio regions are not safe for > untrusted userspace binaries to access. This is why such access is > limited to root. Further there is no generic use for these mmio regions, > only a userspace driver would know what to do with them. Certainly a > userspace driver and kernelspace driver that are working together should > be able to work out a way to share the locations they need without > leaving them lay around in public. It doesn't have to be root. DRI allows normal clients to use the MMIO regions. The key is that you have a RRM that is the guardian angel. If a process does the naughty you kill it and reset the accel engine. > I would really like to get as many people looking at the whole fb > interface with a very critical eye. 2.5.x is the best opportunity we > will have to make drastic changes. We will have a very long time > before 3.0.0(?) to get things in shape. I don't want to settle for > half-done redesign when we could really make a good solid base to > build on for the next several years. I have been working on the fbdev api since janurary 1999. Part of it went in but unfortunely the TTY/console system lacked the power to allow the rest in. Now I have rewritten the console system to handle it. In the process I have realized how I could write wrapper until the TTY/console system gets cleaned up by me. |