Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] framebuffer: new driver for cyberblade/i1 graphics core

This is a framebuffer driver for the Cyberblade/i1 graphics core.

Currently tridenfb claims to support the cyberblade/i1 graphics core. This
is of very limited truth. Even vesafb is faster and provides more working
modes and a much better quality of the video signal. There is a great
number of bugs in tridentfb ... but most often it is impossible to decide
if these bugs are real bugs or if fixing them for the cyberblade/i1 core
would break support for one of the other supported chips.

Tridentfb seems to be unmaintained,and documentation for most of the
supported chips is not available. So "fixing" cyberblade/i1 support inside
of tridentfb was not an option, it would have caused numerous
if(CYBERBLADEi1) else ... cases and would have rendered the code to be
almost unmaintainable.

A first version of this driver was published on 2005-07-31. A fix for a
bug reported by Jochen Hein was integrated as well as some changes
requested by Antonino A. Daplas.

A message has been added to tridentfb to inform current users of tridentfb
to switch to cyblafb if the cyberblade/i1 graphics core is detected.

This patch is one logical change, but because of the included documentation
it is bigger than 70kb. Therefore it is not sent to lkml and
linux-fbdev-devel,

Signed-off-by: Knut Petersen <Knut_Petersen@t-online.de>
Cc: Muli Ben-Yehuda <mulix@mulix.org>
Acked-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Knut Petersen and committed by
Linus Torvalds
9fa68eae 6062bfa1

+2266 -2
+14
Documentation/fb/cyblafb/bugs
··· 1 + Bugs 2 + ==== 3 + 4 + I currently don't know of any bug. Please do send reports to: 5 + - linux-fbdev-devel@lists.sourceforge.net 6 + - Knut_Petersen@t-online.de. 7 + 8 + 9 + Untested features 10 + ================= 11 + 12 + All LCD stuff is untested. If it worked in tridentfb, it should work in 13 + cyblafb. Please test and report the results to Knut_Petersen@t-online.de. 14 +
+7
Documentation/fb/cyblafb/credits
··· 1 + Thanks to 2 + ========= 3 + * Alan Hourihane, for writing the X trident driver 4 + * Jani Monoses, for writing the tridentfb driver 5 + * Antonino A. Daplas, for review of the first published 6 + version of cyblafb and some code 7 + * Jochen Hein, for testing and a helpfull bug report
+17
Documentation/fb/cyblafb/documentation
··· 1 + Available Documentation 2 + ======================= 3 + 4 + Apollo PLE 133 Chipset VT8601A North Bridge Datasheet, Rev. 1.82, October 22, 5 + 2001, available from VIA: 6 + 7 + http://www.viavpsd.com/product/6/15/DS8601A182.pdf 8 + 9 + The datasheet is incomplete, some registers that need to be programmed are not 10 + explained at all and important bits are listed as "reserved". But you really 11 + need the datasheet to understand the code. "p. xxx" comments refer to page 12 + numbers of this document. 13 + 14 + XFree/XOrg drivers are available and of good quality, looking at the code 15 + there is a good idea if the datasheet does not provide enough information 16 + or if the datasheet seems to be wrong. 17 +
+155
Documentation/fb/cyblafb/fb.modes
··· 1 + # 2 + # Sample fb.modes file 3 + # 4 + # Provides an incomplete list of working modes for 5 + # the cyberblade/i1 graphics core. 6 + # 7 + # The value 4294967256 is used instead of -40. Of course, -40 is not 8 + # a really reasonable value, but chip design does not always follow 9 + # logic. Believe me, it's ok, and it's the way the BIOS does it. 10 + # 11 + # fbset requires 4294967256 in fb.modes and -40 as an argument to 12 + # the -t parameter. That's also not too reasonable, and it might change 13 + # in the future or might even be differt for your current version. 14 + # 15 + 16 + mode "640x480-50" 17 + geometry 640 480 640 3756 8 18 + timings 47619 4294967256 24 17 0 216 3 19 + endmode 20 + 21 + mode "640x480-60" 22 + geometry 640 480 640 3756 8 23 + timings 39682 4294967256 24 17 0 216 3 24 + endmode 25 + 26 + mode "640x480-70" 27 + geometry 640 480 640 3756 8 28 + timings 34013 4294967256 24 17 0 216 3 29 + endmode 30 + 31 + mode "640x480-72" 32 + geometry 640 480 640 3756 8 33 + timings 33068 4294967256 24 17 0 216 3 34 + endmode 35 + 36 + mode "640x480-75" 37 + geometry 640 480 640 3756 8 38 + timings 31746 4294967256 24 17 0 216 3 39 + endmode 40 + 41 + mode "640x480-80" 42 + geometry 640 480 640 3756 8 43 + timings 29761 4294967256 24 17 0 216 3 44 + endmode 45 + 46 + mode "640x480-85" 47 + geometry 640 480 640 3756 8 48 + timings 28011 4294967256 24 17 0 216 3 49 + endmode 50 + 51 + mode "800x600-50" 52 + geometry 800 600 800 3221 8 53 + timings 30303 96 24 14 0 136 11 54 + endmode 55 + 56 + mode "800x600-60" 57 + geometry 800 600 800 3221 8 58 + timings 25252 96 24 14 0 136 11 59 + endmode 60 + 61 + mode "800x600-70" 62 + geometry 800 600 800 3221 8 63 + timings 21645 96 24 14 0 136 11 64 + endmode 65 + 66 + mode "800x600-72" 67 + geometry 800 600 800 3221 8 68 + timings 21043 96 24 14 0 136 11 69 + endmode 70 + 71 + mode "800x600-75" 72 + geometry 800 600 800 3221 8 73 + timings 20202 96 24 14 0 136 11 74 + endmode 75 + 76 + mode "800x600-80" 77 + geometry 800 600 800 3221 8 78 + timings 18939 96 24 14 0 136 11 79 + endmode 80 + 81 + mode "800x600-85" 82 + geometry 800 600 800 3221 8 83 + timings 17825 96 24 14 0 136 11 84 + endmode 85 + 86 + mode "1024x768-50" 87 + geometry 1024 768 1024 2815 8 88 + timings 19054 144 24 29 0 120 3 89 + endmode 90 + 91 + mode "1024x768-60" 92 + geometry 1024 768 1024 2815 8 93 + timings 15880 144 24 29 0 120 3 94 + endmode 95 + 96 + mode "1024x768-70" 97 + geometry 1024 768 1024 2815 8 98 + timings 13610 144 24 29 0 120 3 99 + endmode 100 + 101 + mode "1024x768-72" 102 + geometry 1024 768 1024 2815 8 103 + timings 13232 144 24 29 0 120 3 104 + endmode 105 + 106 + mode "1024x768-75" 107 + geometry 1024 768 1024 2815 8 108 + timings 12703 144 24 29 0 120 3 109 + endmode 110 + 111 + mode "1024x768-80" 112 + geometry 1024 768 1024 2815 8 113 + timings 11910 144 24 29 0 120 3 114 + endmode 115 + 116 + mode "1024x768-85" 117 + geometry 1024 768 1024 2815 8 118 + timings 11209 144 24 29 0 120 3 119 + endmode 120 + 121 + mode "1280x1024-50" 122 + geometry 1280 1024 1280 2662 8 123 + timings 11114 232 16 39 0 160 3 124 + endmode 125 + 126 + mode "1280x1024-60" 127 + geometry 1280 1024 1280 2662 8 128 + timings 9262 232 16 39 0 160 3 129 + endmode 130 + 131 + mode "1280x1024-70" 132 + geometry 1280 1024 1280 2662 8 133 + timings 7939 232 16 39 0 160 3 134 + endmode 135 + 136 + mode "1280x1024-72" 137 + geometry 1280 1024 1280 2662 8 138 + timings 7719 232 16 39 0 160 3 139 + endmode 140 + 141 + mode "1280x1024-75" 142 + geometry 1280 1024 1280 2662 8 143 + timings 7410 232 16 39 0 160 3 144 + endmode 145 + 146 + mode "1280x1024-80" 147 + geometry 1280 1024 1280 2662 8 148 + timings 6946 232 16 39 0 160 3 149 + endmode 150 + 151 + mode "1280x1024-85" 152 + geometry 1280 1024 1280 2662 8 153 + timings 6538 232 16 39 0 160 3 154 + endmode 155 +
+80
Documentation/fb/cyblafb/performance
··· 1 + Speed 2 + ===== 3 + 4 + CyBlaFB is much faster than tridentfb and vesafb. Compare the performance data 5 + for mode 1280x1024-[8,16,32]@61 Hz. 6 + 7 + Test 1: Cat a file with 2000 lines of 0 characters. 8 + Test 2: Cat a file with 2000 lines of 80 characters. 9 + Test 3: Cat a file with 2000 lines of 160 characters. 10 + 11 + All values show system time use in seconds, kernel 2.6.12 was used for 12 + the measurements. 2.6.13 is a bit slower, 2.6.14 hopefully will include a 13 + patch that speeds up kernel bitblitting a lot ( > 20%). 14 + 15 + +-----------+-----------------------------------------------------+ 16 + | | not accelerated | 17 + | TRIDENTFB +-----------------+-----------------+-----------------+ 18 + | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | 19 + | | noypan | ypan | noypan | ypan | noypan | ypan | 20 + +-----------+--------+--------+--------+--------+--------+--------+ 21 + | Test 1 | 4.31 | 4.33 | 6.05 | 12.81 | ---- | ---- | 22 + | Test 2 | 67.94 | 5.44 | 123.16 | 14.79 | ---- | ---- | 23 + | Test 3 | 131.36 | 6.55 | 240.12 | 16.76 | ---- | ---- | 24 + +-----------+--------+--------+--------+--------+--------+--------+ 25 + | Comments | | | completely bro- | 26 + | | | | ken, monitor | 27 + | | | | switches off | 28 + +-----------+-----------------+-----------------+-----------------+ 29 + 30 + 31 + +-----------+-----------------------------------------------------+ 32 + | | accelerated | 33 + | TRIDENTFB +-----------------+-----------------+-----------------+ 34 + | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | 35 + | | noypan | ypan | noypan | ypan | noypan | ypan | 36 + +-----------+--------+--------+--------+--------+--------+--------+ 37 + | Test 1 | ---- | ---- | 20.62 | 1.22 | ---- | ---- | 38 + | Test 2 | ---- | ---- | 22.61 | 3.19 | ---- | ---- | 39 + | Test 3 | ---- | ---- | 24.59 | 5.16 | ---- | ---- | 40 + +-----------+--------+--------+--------+--------+--------+--------+ 41 + | Comments | broken, writing | broken, ok only | completely bro- | 42 + | | to wrong places | if bgcolor is | ken, monitor | 43 + | | on screen + bug | black, bug in | switches off | 44 + | | in fillrect() | fillrect() | | 45 + +-----------+-----------------+-----------------+-----------------+ 46 + 47 + 48 + +-----------+-----------------------------------------------------+ 49 + | | not accelerated | 50 + | VESAFB +-----------------+-----------------+-----------------+ 51 + | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | 52 + | | noypan | ypan | noypan | ypan | noypan | ypan | 53 + +-----------+--------+--------+--------+--------+--------+--------+ 54 + | Test 1 | 4.26 | 3.76 | 5.99 | 7.23 | ---- | ---- | 55 + | Test 2 | 65.65 | 4.89 | 120.88 | 9.08 | ---- | ---- | 56 + | Test 3 | 126.91 | 5.94 | 235.77 | 11.03 | ---- | ---- | 57 + +-----------+--------+--------+--------+--------+--------+--------+ 58 + | Comments | vga=0x307 | vga=0x31a | vga=0x31b not | 59 + | | fh=80kHz | fh=80kHz | supported by | 60 + | | fv=75kHz | fv=75kHz | video BIOS and | 61 + | | | | hardware | 62 + +-----------+-----------------+-----------------+-----------------+ 63 + 64 + 65 + +-----------+-----------------------------------------------------+ 66 + | | accelerated | 67 + | CYBLAFB +-----------------+-----------------+-----------------+ 68 + | | 8 bpp | 16 bpp | 32 bpp | 69 + | | noypan | ypan | noypan | ypan | noypan | ypan | 70 + +-----------+--------+--------+--------+--------+--------+--------+ 71 + | Test 1 | 8.02 | 0.23 | 19.04 | 0.61 | 57.12 | 2.74 | 72 + | Test 2 | 8.38 | 0.55 | 19.39 | 0.92 | 57.54 | 3.13 | 73 + | Test 3 | 8.73 | 0.86 | 19.74 | 1.24 | 57.95 | 3.51 | 74 + +-----------+--------+--------+--------+--------+--------+--------+ 75 + | Comments | | | | 76 + | | | | | 77 + | | | | | 78 + | | | | | 79 + +-----------+-----------------+-----------------+-----------------+ 80 +
+32
Documentation/fb/cyblafb/todo
··· 1 + TODO / Missing features 2 + ======================= 3 + 4 + Verify LCD stuff "stretch" and "center" options are 5 + completely untested ... this code needs to be 6 + verified. As I don't have access to such 7 + hardware, please contact me if you are 8 + willing run some tests. 9 + 10 + Interlaced video modes The reason that interleaved 11 + modes are disabled is that I do not know 12 + the meaning of the vertical interlace 13 + parameter. Also the datasheet mentions a 14 + bit d8 of a horizontal interlace parameter, 15 + but nowhere the lower 8 bits. Please help 16 + if you can. 17 + 18 + low-res double scan modes Who needs it? 19 + 20 + accelerated color blitting Who needs it? The console driver does use color 21 + blitting for nothing but drawing the penguine, 22 + everything else is done using color expanding 23 + blitting of 1bpp character bitmaps. 24 + 25 + xpanning Who needs it? 26 + 27 + ioctls Who needs it? 28 + 29 + TV-out Will be done later 30 + 31 + ??? Feel free to contact me if you have any 32 + feature requests
+206
Documentation/fb/cyblafb/usage
··· 1 + CyBlaFB is a framebuffer driver for the Cyberblade/i1 graphics core integrated 2 + into the VIA Apollo PLE133 (aka vt8601) south bridge. It is developed and 3 + tested using a VIA EPIA 5000 board. 4 + 5 + Cyblafb - compiled into the kernel or as a module? 6 + ================================================== 7 + 8 + You might compile cyblafb either as a module or compile it permanently into the 9 + kernel. 10 + 11 + Unless you have a real reason to do so you should not compile both vesafb and 12 + cyblafb permanently into the kernel. It's possible and it helps during the 13 + developement cycle, but it's useless and will at least block some otherwise 14 + usefull memory for ordinary users. 15 + 16 + Selecting Modes 17 + =============== 18 + 19 + Startup Mode 20 + ============ 21 + 22 + First of all, you might use the "vga=???" boot parameter as it is 23 + documented in vesafb.txt and svga.txt. Cyblafb will detect the video 24 + mode selected and will use the geometry and timings found by 25 + inspecting the hardware registers. 26 + 27 + video=cyblafb vga=0x317 28 + 29 + Alternatively you might use a combination of the mode, ref and bpp 30 + parameters. If you compiled the driver into the kernel, add something 31 + like this to the kernel command line: 32 + 33 + video=cyblafb:1280x1024,bpp=16,ref=50 ... 34 + 35 + If you compiled the driver as a module, the same mode would be 36 + selected by the following command: 37 + 38 + modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ... 39 + 40 + None of the modes possible to select as startup modes are affected by 41 + the problems described at the end of the next subsection. 42 + 43 + Mode changes using fbset 44 + ======================== 45 + 46 + You might use fbset to change the video mode, see "man fbset". Cyblafb 47 + generally does assume that you know what you are doing. But it does 48 + some checks, especially those that are needed to prevent you from 49 + damaging your hardware. 50 + 51 + - only 8, 16, 24 and 32 bpp video modes are accepted 52 + - interlaced video modes are not accepted 53 + - double scan video modes are not accepted 54 + - if a flat panel is found, cyblafb does not allow you 55 + to program a resolution higher than the physical 56 + resolution of the flat panel monitor 57 + - cyblafb does not allow xres to differ from xres_virtual 58 + - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp 59 + and (currently) 24 bit modes use a doubled vclk internally, 60 + the dotclock limit as seen by fbset is 115 MHz for those 61 + modes and 230 MHz for 8 and 16 bpp modes. 62 + 63 + Any request that violates the rules given above will be ignored and 64 + fbset will return an error. 65 + 66 + If you program a virtual y resolution higher than the hardware limit, 67 + cyblafb will silently decrease that value to the highest possible 68 + value. 69 + 70 + Attempts to disable acceleration are ignored. 71 + 72 + Some video modes that should work do not work as expected. If you use 73 + the standard fb.modes, fbset 640x480-60 will program that mode, but 74 + you will see a vertical area, about two characters wide, with only 75 + much darker characters than the other characters on the screen. 76 + Cyblafb does allow that mode to be set, as it does not violate the 77 + official specifications. It would need a lot of code to reliably sort 78 + out all invalid modes, playing around with the margin values will 79 + give a valid mode quickly. And if cyblafb would detect such an invalid 80 + mode, should it silently alter the requested values or should it 81 + report an error? Both options have some pros and cons. As stated 82 + above, none of the startup modes are affected, and if you set 83 + verbosity to 1 or higher, cyblafb will print the fbset command that 84 + would be needed to program that mode using fbset. 85 + 86 + 87 + Other Parameters 88 + ================ 89 + 90 + 91 + crt don't autodetect, assume monitor connected to 92 + standard VGA connector 93 + 94 + fp don't autodetect, assume flat panel display 95 + connected to flat panel monitor interface 96 + 97 + nativex inform driver about native x resolution of 98 + flat panel monitor connected to special 99 + interface (should be autodetected) 100 + 101 + stretch stretch image to adapt low resolution modes to 102 + higer resolutions of flat panel monitors 103 + connected to special interface 104 + 105 + center center image to adapt low resolution modes to 106 + higer resolutions of flat panel monitors 107 + connected to special interface 108 + 109 + memsize use if autodetected memsize is wrong ... 110 + should never be necessary 111 + 112 + nopcirr disable PCI read retry 113 + nopciwr disable PCI write retry 114 + nopcirb disable PCI read bursts 115 + nopciwb disable PCI write bursts 116 + 117 + bpp bpp for specified modes 118 + valid values: 8 || 16 || 24 || 32 119 + 120 + ref refresh rate for specified mode 121 + valid values: 50 <= ref <= 85 122 + 123 + mode 640x480 or 800x600 or 1024x768 or 1280x1024 124 + if not specified, the startup mode will be detected 125 + and used, so you might also use the vga=??? parameter 126 + described in vesafb.txt. If you do not specify a mode, 127 + bpp and ref parameters are ignored. 128 + 129 + verbosity 0 is the default, increase to at least 2 for every 130 + bug report! 131 + 132 + vesafb allows cyblafb to be loaded after vesafb has been 133 + loaded. See sections "Module unloading ...". 134 + 135 + 136 + Development hints 137 + ================= 138 + 139 + It's much faster do compile a module and to load the new version after 140 + unloading the old module than to compile a new kernel and to reboot. So if you 141 + try to work on cyblafb, it might be a good idea to use cyblafb as a module. 142 + In real life, fast often means dangerous, and that's also the case here. If 143 + you introduce a serious bug when cyblafb is compiled into the kernel, the 144 + kernel will lock or oops with a high probability before the file system is 145 + mounted, and the danger for your data is low. If you load a broken own version 146 + of cyblafb on a running system, the danger for the integrity of the file 147 + system is much higher as you might need a hard reset afterwards. Decide 148 + yourself. 149 + 150 + Module unloading, the vfb method 151 + ================================ 152 + 153 + If you want to unload/reload cyblafb using the virtual framebuffer, you need 154 + to enable vfb support in the kernel first. After that, load the modules as 155 + shown below: 156 + 157 + modprobe vfb vfb_enable=1 158 + modprobe fbcon 159 + modprobe cyblafb 160 + fbset -fb /dev/fb1 1280x1024-60 -vyres 2662 161 + con2fb /dev/fb1 /dev/tty1 162 + ... 163 + 164 + If you now made some changes to cyblafb and want to reload it, you might do it 165 + as show below: 166 + 167 + con2fb /dev/fb0 /dev/tty1 168 + ... 169 + rmmod cyblafb 170 + modprobe cyblafb 171 + con2fb /dev/fb1 /dev/tty1 172 + ... 173 + 174 + Of course, you might choose another mode, and most certainly you also want to 175 + map some other /dev/tty* to the real framebuffer device. You might also choose 176 + to compile fbcon as a kernel module or place it permanently in the kernel. 177 + 178 + I do not know of any way to unload fbcon, and fbcon will prevent the 179 + framebuffer device loaded first from unloading. [If there is a way, then 180 + please add a description here!] 181 + 182 + Module unloading, the vesafb method 183 + =================================== 184 + 185 + Configure the kernel: 186 + 187 + <*> Support for frame buffer devices 188 + [*] VESA VGA graphics support 189 + <M> Cyberblade/i1 support 190 + 191 + Add e.g. "video=vesafb:ypan vga=0x307" to the kernel parameters. The ypan 192 + parameter is important, choose any vga parameter you like as long as it is 193 + a graphics mode. 194 + 195 + After booting, load cyblafb without any mode and bpp parameter and assign 196 + cyblafb to individual ttys using con2fb, e.g.: 197 + 198 + modprobe cyblafb vesafb=1 199 + con2fb /dev/fb1 /dev/tty1 200 + 201 + Unloading cyblafb works without problems after you assign vesafb to all 202 + ttys again, e.g.: 203 + 204 + con2fb /dev/fb0 /dev/tty1 205 + rmmod cyblafb 206 +
+85
Documentation/fb/cyblafb/whycyblafb
··· 1 + I tried the following framebuffer drivers: 2 + 3 + - TRIDENTFB is full of bugs. Acceleration is broken for Blade3D 4 + graphics cores like the cyberblade/i1. It claims to support a great 5 + number of devices, but documentation for most of these devices is 6 + unfortunately not available. There is _no_ reason to use tridentfb 7 + for cyberblade/i1 + CRT users. VESAFB is faster, and the one 8 + advantage, mode switching, is broken in tridentfb. 9 + 10 + - VESAFB is used by many distributions as a standard. Vesafb does 11 + not support mode switching. VESAFB is a bit faster than the working 12 + configurations of TRIDENTFB, but it is still too slow, even if you 13 + use ypan. 14 + 15 + - EPIAFB (you'll find it on sourceforge) supports the Cyberblade/i1 16 + graphics core, but it still has serious bugs and developement seems 17 + to have stopped. This is the one driver with TV-out support. If you 18 + do need this feature, try epiafb. 19 + 20 + None of these drivers was a real option for me. 21 + 22 + I believe that is unreasonable to change code that announces to support 20 23 + devices if I only have more or less sufficient documentation for exactly one 24 + of these. The risk of breaking device foo while fixing device bar is too high. 25 + 26 + So I decided to start CyBlaFB as a stripped down tridentfb. 27 + 28 + All code specific to other Trident chips has been removed. After that there 29 + were a lot of cosmetic changes to increase the readability of the code. All 30 + register names were changed to those mnemonics used in the datasheet. Function 31 + and macro names were changed if they hindered easy understanding of the code. 32 + 33 + After that I debugged the code and implemented some new features. I'll try to 34 + give a little summary of the main changes: 35 + 36 + - calculation of vertical and horizontal timings was fixed 37 + 38 + - video signal quality has been improved dramatically 39 + 40 + - acceleration: 41 + 42 + - fillrect and copyarea were fixed and reenabled 43 + 44 + - color expanding imageblit was newly implemented, color 45 + imageblit (only used to draw the penguine) still uses the 46 + generic code. 47 + 48 + - init of the acceleration engine was improved and moved to a 49 + place where it really works ... 50 + 51 + - sync function has a timeout now and tries to reset and 52 + reinit the accel engine if necessary 53 + 54 + - fewer slow copyarea calls when doing ypan scrolling by using 55 + undocumented bit d21 of screen start address stored in 56 + CR2B[5]. BIOS does use it also, so this should be safe. 57 + 58 + - cyblafb rejects any attempt to set modes that would cause vclk 59 + values above reasonable 230 MHz. 32bit modes use a clock 60 + multiplicator of 2, so fbset does show the correct values for 61 + pixclock but not for vclk in this case. The fbset limit is 115 MHz 62 + for 32 bpp modes. 63 + 64 + - cyblafb rejects modes known to be broken or unimplemented (all 65 + interlaced modes, all doublescan modes for now) 66 + 67 + - cyblafb now works independant of the video mode in effect at startup 68 + time (tridentfb does not init all needed registers to reasonable 69 + values) 70 + 71 + - switching between video modes does work reliably now 72 + 73 + - the first video mode now is the one selected on startup using the 74 + vga=???? mechanism or any of 75 + - 640x480, 800x600, 1024x768, 1280x1024 76 + - 8, 16, 24 or 32 bpp 77 + - refresh between 50 Hz and 85 Hz, 1 Hz steps (1280x1024-32 78 + is limited to 63Hz) 79 + 80 + - pci retry and pci burst mode are settable (try to disable if you 81 + experience latency problems) 82 + 83 + - built as a module cyblafb might be unloaded and reloaded using 84 + the vfb module and con2vt or might be used together with vesafb 85 +
+6
MAINTAINERS
··· 626 626 W: http://www.arm.linux.org.uk/ 627 627 S: Maintained 628 628 629 + CYBLAFB FRAMEBUFFER DRIVER 630 + P: Knut Petersen 631 + M: Knut_Petersen@t-online.de 632 + L: linux-fbdev-devel@lists.sourceforge.net 633 + S: Maintained 634 + 629 635 CYCLADES 2X SYNC CARD DRIVER 630 636 P: Arnaldo Carvalho de Melo 631 637 M: acme@conectiva.com.br
+30 -1
drivers/video/Kconfig
··· 1177 1177 Please read the <file:Documentation/fb/README-sstfb.txt> for supported 1178 1178 options and other important info support. 1179 1179 1180 + config FB_CYBLA 1181 + tristate "Cyberblade/i1 support" 1182 + depends on FB && PCI 1183 + select FB_CFB_IMAGEBLIT 1184 + select FB_SOFT_CURSOR 1185 + select VIDEO_SELECT 1186 + ---help--- 1187 + This driver is supposed to support the Trident Cyberblade/i1 1188 + graphics core integrated in the VIA VT8601A North Bridge, 1189 + also known as VIA Apollo PLE133. 1190 + 1191 + Status: 1192 + - Developed, tested and working on EPIA 5000 and EPIA 800. 1193 + - Does work reliable on all systems with CRT/LCD connected to 1194 + normal VGA ports. 1195 + - Should work on systems that do use the internal LCD port, but 1196 + this is absolutely not tested. 1197 + 1198 + Character imageblit, copyarea and rectangle fill are hw accelerated, 1199 + ypan scrolling is used by default. 1200 + 1201 + Please do read <file:Documentation/fb/cyblafb/*>. 1202 + 1203 + To compile this driver as a module, choose M here: the 1204 + module will be called cyblafb. 1205 + 1180 1206 config FB_TRIDENT 1181 1207 tristate "Trident support" 1182 1208 depends on FB && PCI ··· 1216 1190 but also on some motherboards. For more information, read 1217 1191 <file:Documentation/fb/tridentfb.txt> 1218 1192 1193 + Cyberblade/i1 support will be removed soon, use the cyblafb driver 1194 + instead. 1195 + 1219 1196 Say Y if you have such a graphics board. 1197 + 1220 1198 1221 1199 To compile this driver as a module, choose M here: the 1222 1200 module will be called tridentfb. ··· 1231 1201 ---help--- 1232 1202 This will compile the Trident frame buffer device with 1233 1203 acceleration functions. 1234 - 1235 1204 1236 1205 config FB_PM3 1237 1206 tristate "Permedia3 support"
+2 -1
drivers/video/Makefile
··· 50 50 obj-$(CONFIG_FB_IMSTT) += imsttfb.o 51 51 obj-$(CONFIG_FB_S3TRIO) += S3triofb.o 52 52 obj-$(CONFIG_FB_FM2) += fm2fb.o 53 - obj-$(CONFIG_FB_TRIDENT) += tridentfb.o 53 + obj-$(CONFIG_FB_CYBLA) += cyblafb.o 54 + obj-$(CONFIG_FB_TRIDENT) += tridentfb.o 54 55 obj-$(CONFIG_FB_STI) += stifb.o 55 56 obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o 56 57 obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
+1456
drivers/video/cyblafb.c
··· 1 + /* 2 + * Frame buffer driver for Trident Cyberblade/i1 graphics core 3 + * 4 + * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de> 5 + * 6 + * CREDITS: 7 + * tridentfb.c by Jani Monoses 8 + * see files above for further credits 9 + * 10 + * TODO: 11 + * 12 + */ 13 + 14 + #define CYBLAFB_DEBUG 0 15 + 16 + #include <linux/config.h> 17 + #include <linux/module.h> 18 + #include <linux/string.h> 19 + #include <linux/fb.h> 20 + #include <linux/init.h> 21 + #include <linux/pci.h> 22 + #include <asm/types.h> 23 + #include <video/cyblafb.h> 24 + 25 + #define VERSION "0.54" 26 + 27 + struct cyblafb_par { 28 + u32 pseudo_pal[16]; 29 + struct fb_ops ops; 30 + }; 31 + 32 + static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { 33 + .id = "CyBla", 34 + .type = FB_TYPE_PACKED_PIXELS, 35 + .ypanstep = 1, 36 + .visual = FB_VISUAL_PSEUDOCOLOR, 37 + .accel = FB_ACCEL_NONE, 38 + }; 39 + 40 + static char *mode __devinitdata = NULL; 41 + static int bpp __devinitdata = 8; 42 + static int ref __devinitdata = 75; 43 + static int fp __devinitdata; 44 + static int crt __devinitdata; 45 + static int memsize __devinitdata; 46 + static int vesafb __devinitdata; 47 + 48 + static int nativex; 49 + static int center; 50 + static int stretch; 51 + static int pciwb = 1; 52 + static int pcirb = 1; 53 + static int pciwr = 1; 54 + static int pcirr = 1; 55 + static int verbosity; 56 + static int displaytype; 57 + 58 + static void __iomem * io_virt; // iospace virtual memory address 59 + 60 + module_param(mode,charp,0); 61 + module_param(bpp,int,0); 62 + module_param(ref,int,0); 63 + module_param(fp,int,0); 64 + module_param(crt,int,0); 65 + module_param(nativex,int,0); 66 + module_param(center,int,0); 67 + module_param(stretch,int,0); 68 + module_param(pciwb,int,0); 69 + module_param(pcirb,int,0); 70 + module_param(pciwr,int,0); 71 + module_param(pcirr,int,0); 72 + module_param(memsize,int,0); 73 + module_param(verbosity,int,0); 74 + module_param(vesafb,int,0); 75 + 76 + //========================================= 77 + // 78 + // Port access macros for memory mapped io 79 + // 80 + //========================================= 81 + 82 + #define out8(r,v) writeb(v,io_virt+r) 83 + #define out32(r,v) writel(v,io_virt+r) 84 + #define in8(r) readb(io_virt+r) 85 + #define in32(r) readl(io_virt+r) 86 + 87 + //====================================== 88 + // 89 + // Hardware access inline functions 90 + // 91 + //====================================== 92 + 93 + static inline unsigned char read3X4(int reg) 94 + { 95 + out8(0x3D4,reg); 96 + return in8(0x3D5); 97 + } 98 + 99 + static inline unsigned char read3C4(int reg) 100 + { 101 + out8(0x3C4,reg); 102 + return in8(0x3C5); 103 + } 104 + 105 + static inline unsigned char read3CE(int reg) 106 + { 107 + out8(0x3CE,reg); 108 + return in8(0x3CF); 109 + } 110 + 111 + static inline void write3X4(int reg,unsigned char val) 112 + { 113 + out8(0x3D4,reg); 114 + out8(0x3D5,val); 115 + } 116 + 117 + static inline void write3C4(int reg,unsigned char val) 118 + { 119 + out8(0x3C4,reg); 120 + out8(0x3C5,val); 121 + } 122 + 123 + static inline void write3CE(int reg,unsigned char val) 124 + { 125 + out8(0x3CE,reg); 126 + out8(0x3CF,val); 127 + } 128 + 129 + static inline void write3C0(int reg,unsigned char val) 130 + { 131 + in8(0x3DA); // read to reset index 132 + out8(0x3C0,reg); 133 + out8(0x3C0,val); 134 + } 135 + 136 + //================================================= 137 + // 138 + // Enable memory mapped io and unprotect registers 139 + // 140 + //================================================= 141 + 142 + static inline void enable_mmio(void) 143 + { 144 + int tmp; 145 + 146 + outb(0x0B,0x3C4); 147 + inb(0x3C5); // Set NEW mode 148 + outb(SR0E,0x3C4); // write enable a lot of extended ports 149 + outb(0x80,0x3C5); 150 + 151 + outb(SR11,0x3C4); // write enable those extended ports that 152 + outb(0x87,0x3C5); // are not affected by SR0E_New 153 + 154 + outb(CR1E,0x3d4); // clear write protect bit for port 0x3c2 155 + tmp=inb(0x3d5) & 0xBF; 156 + outb(CR1E,0x3d4); 157 + outb(tmp,0x3d5); 158 + 159 + outb(CR39,0x3D4); 160 + outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched 161 + } 162 + 163 + //================================================= 164 + // 165 + // Set pixel clock VCLK1 166 + // - multipliers set elswhere 167 + // - freq in units of 0.01 MHz 168 + // 169 + //================================================= 170 + 171 + static void set_vclk(struct cyblafb_par *par, int freq) 172 + { 173 + u32 m,n,k; 174 + int f,fi,d,di; 175 + u8 lo=0,hi=0; 176 + 177 + d = 2000; 178 + k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; 179 + for(m = 0;m<64;m++) 180 + for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 ! 181 + fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12); 182 + if ((di = abs(fi - freq)) < d) { 183 + d = di; 184 + f = fi; 185 + lo = (u8) n; 186 + hi = (u8) ((k<<6) | m); 187 + } 188 + } 189 + write3C4(SR19,hi); 190 + write3C4(SR18,lo); 191 + if(verbosity > 1) 192 + output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", 193 + freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo); 194 + } 195 + 196 + //================================================ 197 + // 198 + // Cyberblade specific Graphics Engine (GE) setup 199 + // 200 + //================================================ 201 + 202 + static void cyblafb_setup_GE(int pitch,int bpp) 203 + { 204 + int base = (pitch>>3)<<20; 205 + 206 + switch (bpp) { 207 + case 8: base |= (0<<29); break; 208 + case 15: base |= (5<<29); break; 209 + case 16: base |= (1<<29); break; 210 + case 24: 211 + case 32: base |= (2<<29); break; 212 + } 213 + 214 + write3X4(CR36,0x90); // reset GE 215 + write3X4(CR36,0x80); // enable GE 216 + 217 + out32(GE24,1<<7); // reset all GE pointers 218 + out32(GE24,0); 219 + 220 + write3X4(CR2D,0x00); // GE Timinigs, no delays 221 + 222 + out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133 223 + out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133 224 + out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133 225 + out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133 226 + out32(GEC8,base); // Source Stride / Buffer Base 0, p 133 227 + out32(GECC,base); // Source Stride / Buffer Base 1, p 133 228 + out32(GED0,base); // Source Stride / Buffer Base 2, p 133 229 + out32(GED4,base); // Source Stride / Buffer Base 3, p 133 230 + out32(GE6C,0); // Pattern and Style, p 129, ok 231 + } 232 + 233 + //===================================================================== 234 + // 235 + // Although this is a .fb_sync function that could be enabled in 236 + // cyblafb_ops, we do not include it there. We sync immediately before 237 + // new GE operations to improve performance. 238 + // 239 + //===================================================================== 240 + 241 + static int cyblafb_sync(struct fb_info *info) 242 + { 243 + int status, i=100000; 244 + while( ((status=in32(GE20)) & 0xFA800000) && i != 0) 245 + i--; 246 + 247 + if (i == 0) { 248 + // The timeout might be caused by disabled mmio. 249 + // Cause: 250 + // - bit CR39 & 1 == 0 upon return, X trident driver bug 251 + // - kdm bug (KD_GRAPHICS not set on first switch) 252 + // - kernel design flaw (it believes in the correctness 253 + // of kdm/X 254 + // So we make sure that mmio is enabled first ... 255 + enable_mmio(); 256 + // show_trace(NULL,&status); 257 + i=1000000; 258 + while( ((status=in32(GE20)) & 0xFA800000) && i != 0) 259 + i--; 260 + if (i == 0) { 261 + output("GE Timeout, status: %x\n",status); 262 + if(status & 0x80000000) 263 + output("Bresenham Engine : Busy\n"); 264 + if(status & 0x40000000) 265 + output("Setup Engine : Busy\n"); 266 + if(status & 0x20000000) 267 + output("SP / DPE : Busy\n"); 268 + if(status & 0x10000000) 269 + output("Memory Interface : Busy\n"); 270 + if(status & 0x08000000) 271 + output("Com Lst Proc : Busy\n"); 272 + if(status & 0x04000000) 273 + output("Block Write : Busy\n"); 274 + if(status & 0x02000000) 275 + output("Command Buffer : Full\n"); 276 + if(status & 0x01000000) 277 + output("RESERVED : Busy\n"); 278 + if(status & 0x00800000) 279 + output("PCI Write Buffer : Busy\n"); 280 + cyblafb_setup_GE(info->var.xres, 281 + info->var.bits_per_pixel); 282 + } 283 + } 284 + 285 + return 0; 286 + } 287 + 288 + //============================== 289 + // 290 + // Cyberblade specific fillrect 291 + // 292 + //============================== 293 + 294 + static void cyblafb_fillrect(struct fb_info * info, 295 + const struct fb_fillrect *fr) 296 + { 297 + int bpp = info->var.bits_per_pixel; 298 + int col; 299 + 300 + switch (bpp) { 301 + default: 302 + case 8: col = fr->color; 303 + col |= col <<8; 304 + col |= col <<16; 305 + break; 306 + case 16: col = ((u32 *)(info->pseudo_palette))[fr->color]; 307 + col |= col <<16; 308 + break; 309 + case 32: col = ((u32 *)(info->pseudo_palette))[fr->color]; 310 + break; 311 + } 312 + 313 + cyblafb_sync(info); 314 + 315 + out32(GE60,col); 316 + out32(GE48,fr->rop ? 0x66:ROP_S); 317 + out32(GE44,0x20000000|1<<19|1<<4|2<<2); 318 + out32(GE08,point(fr->dx,fr->dy)); 319 + out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1)); 320 + 321 + } 322 + 323 + //============================== 324 + // 325 + // Cyberblade specific copyarea 326 + // 327 + //============================== 328 + 329 + static void cyblafb_copyarea(struct fb_info *info, 330 + const struct fb_copyarea *ca) 331 + { 332 + __u32 s1,s2,d1,d2; 333 + int direction; 334 + 335 + s1 = point(ca->sx,ca->sy); 336 + s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1); 337 + d1 = point(ca->dx,ca->dy); 338 + d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1); 339 + if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) 340 + direction = 0; 341 + else 342 + direction = 2; 343 + 344 + cyblafb_sync(info); 345 + 346 + out32(GE44,0xa0000000|1<<19|1<<2|direction); 347 + out32(GE00,direction?s2:s1); 348 + out32(GE04,direction?s1:s2); 349 + out32(GE08,direction?d2:d1); 350 + out32(GE0C,direction?d1:d2); 351 + 352 + } 353 + 354 + //======================================================================= 355 + // 356 + // Cyberblade specific imageblit 357 + // 358 + // Accelerated for the most usual case, blitting 1-bit deep character 359 + // character images. Everything else is passed to the generic imageblit. 360 + // 361 + //======================================================================= 362 + 363 + static void cyblafb_imageblit(struct fb_info *info, 364 + const struct fb_image *image) 365 + { 366 + 367 + u32 fgcol, bgcol; 368 + 369 + int i; 370 + int bpp = info->var.bits_per_pixel; 371 + int index = 0; 372 + int index_end=image->height * image->width / 8; 373 + int width_dds=image->width / 32; 374 + int width_dbs=image->width % 32; 375 + 376 + if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 || 377 + image->width % 8 != 0 || image->width == 0 || image->height == 0) { 378 + cfb_imageblit(info,image); 379 + return; 380 + } 381 + 382 + if (info->fix.visual == FB_VISUAL_TRUECOLOR || 383 + info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 384 + fgcol = ((u32*)(info->pseudo_palette))[image->fg_color]; 385 + bgcol = ((u32*)(info->pseudo_palette))[image->bg_color]; 386 + } else { 387 + fgcol = image->fg_color; 388 + bgcol = image->bg_color; 389 + } 390 + 391 + switch (bpp) { 392 + case 8: 393 + fgcol |= fgcol <<8; fgcol |= fgcol <<16; 394 + bgcol |= bgcol <<8; bgcol |= bgcol <<16; 395 + break; 396 + case 16: 397 + fgcol |= fgcol <<16; 398 + bgcol |= bgcol <<16; 399 + break; 400 + default: 401 + break; 402 + } 403 + 404 + cyblafb_sync(info); 405 + 406 + out32(GE60,fgcol); 407 + out32(GE64,bgcol); 408 + out32(GE44,0xa0000000 | 1<<20 | 1<<19); 409 + out32(GE08,point(image->dx,image->dy)); 410 + out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1)); 411 + 412 + while(index < index_end) { 413 + for(i=0;i<width_dds;i++) { 414 + out32(GE9C,*((u32*) ((u32)image->data + index))); 415 + index+=4; 416 + } 417 + switch(width_dbs) { 418 + case 0: break; 419 + case 8: out32(GE9C,*((u8*)((u32)image->data+index))); 420 + index+=1; 421 + break; 422 + case 16: out32(GE9C,*((u16*)((u32)image->data+index))); 423 + index+=2; 424 + break; 425 + case 24: out32(GE9C,(u32)(*((u16*)((u32)image->data+index))) | 426 + (u32)(*((u8*)((u32)image->data+index+2)))<<16); 427 + index+=3; 428 + break; 429 + } 430 + } 431 + } 432 + 433 + //========================================================== 434 + // 435 + // Check if video mode is acceptable. We change var->??? if 436 + // video mode is slightly off or return error otherwise. 437 + // info->??? must not be changed! 438 + // 439 + //========================================================== 440 + 441 + static int cyblafb_check_var(struct fb_var_screeninfo *var, 442 + struct fb_info *info) 443 + { 444 + int bpp = var->bits_per_pixel; 445 + int s,t,maxvyres; 446 + 447 + // 448 + // we try to support 8, 16, 24 and 32 bpp modes, 449 + // default to 8 450 + // 451 + // there is a 24 bpp mode, but for now we change requests to 32 bpp 452 + // (This is what tridentfb does ... will be changed in the future) 453 + // 454 + // 455 + if ( bpp % 8 != 0 || bpp < 8 || bpp >32) 456 + bpp = 8; 457 + if (bpp == 24 ) 458 + bpp = var->bits_per_pixel = 32; 459 + 460 + // 461 + // interlaced modes are broken, fail if one is requested 462 + // 463 + if (var->vmode & FB_VMODE_INTERLACED) 464 + return -EINVAL; 465 + 466 + // 467 + // fail if requested resolution is higher than physical 468 + // flatpanel resolution 469 + // 470 + if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex) 471 + return -EINVAL; 472 + 473 + // 474 + // xres != xres_virtual is broken, fail if such an 475 + // unusual mode is requested 476 + // 477 + if (var->xres != var->xres_virtual) 478 + return -EINVAL; 479 + 480 + // 481 + // we do not allow vclk to exceed 230 MHz 482 + // 483 + if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000) 484 + return -EINVAL; 485 + 486 + // 487 + // calc max yres_virtual that would fit in memory 488 + // and max yres_virtual that could be used for scrolling 489 + // and use minimum of the results as maxvyres 490 + // 491 + // adjust vyres_virtual to maxvyres if necessary 492 + // fail if requested yres is bigger than maxvyres 493 + // 494 + s = (0x1fffff / (var->xres * bpp/8)) + var->yres; 495 + t = info->fix.smem_len / (var->xres * bpp/8); 496 + maxvyres = t < s ? t : s; 497 + if (maxvyres < var->yres_virtual) 498 + var->yres_virtual=maxvyres; 499 + if (maxvyres < var->yres) 500 + return -EINVAL; 501 + 502 + switch (bpp) { 503 + case 8: 504 + var->red.offset = 0; 505 + var->green.offset = 0; 506 + var->blue.offset = 0; 507 + var->red.length = 6; 508 + var->green.length = 6; 509 + var->blue.length = 6; 510 + break; 511 + case 16: 512 + var->red.offset = 11; 513 + var->green.offset = 5; 514 + var->blue.offset = 0; 515 + var->red.length = 5; 516 + var->green.length = 6; 517 + var->blue.length = 5; 518 + break; 519 + case 32: 520 + var->red.offset = 16; 521 + var->green.offset = 8; 522 + var->blue.offset = 0; 523 + var->red.length = 8; 524 + var->green.length = 8; 525 + var->blue.length = 8; 526 + break; 527 + default: 528 + return -EINVAL; 529 + } 530 + 531 + return 0; 532 + 533 + } 534 + 535 + //===================================================================== 536 + // 537 + // Pan the display 538 + // 539 + // The datasheets defines crt start address to be 20 bits wide and 540 + // to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is 541 + // CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use 542 + // it, so it is also safe to be used here. BTW: datasheet CR0E on page 543 + // 90 really is CR1E, the real CRE is documented on page 72. 544 + // 545 + //===================================================================== 546 + 547 + static int cyblafb_pan_display(struct fb_var_screeninfo *var, 548 + struct fb_info *info) 549 + { 550 + unsigned int offset; 551 + 552 + offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32; 553 + info->var.xoffset = var->xoffset; 554 + info->var.yoffset = var->yoffset; 555 + 556 + write3X4(CR0D,offset & 0xFF); 557 + write3X4(CR0C,(offset & 0xFF00) >> 8); 558 + write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11)); 559 + write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17)); 560 + write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15)); 561 + 562 + return 0; 563 + } 564 + 565 + //============================================ 566 + // 567 + // This will really help in case of a bug ... 568 + // dump most gaphics core registers. 569 + // 570 + //============================================ 571 + 572 + static void regdump(struct cyblafb_par *par) 573 + { 574 + int i; 575 + 576 + if (verbosity < 2) 577 + return; 578 + 579 + printk("\n"); 580 + for(i=0; i<=0xff; i++) { 581 + outb(i,0x3d4); 582 + printk("CR%02x=%02x ",i,inb(0x3d5)); 583 + if (i%16==15) 584 + printk("\n"); 585 + } 586 + 587 + outb(0x30,0x3ce); 588 + outb(inb(0x3cf) | 0x40,0x3cf); 589 + for(i=0; i<=0x1f; i++) { 590 + if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) { 591 + outb(i,0x3d4); 592 + printk("CR%02x=%02x ",i,inb(0x3d5)); 593 + } else 594 + printk("------- "); 595 + if (i%16==15) 596 + printk("\n"); 597 + } 598 + outb(0x30,0x3ce); 599 + outb(inb(0x3cf) & 0xbf,0x3cf); 600 + 601 + printk("\n"); 602 + for(i=0; i<=0x7f; i++) { 603 + outb(i,0x3ce); 604 + printk("GR%02x=%02x ",i,inb(0x3cf)); 605 + if (i%16==15) 606 + printk("\n"); 607 + } 608 + 609 + printk("\n"); 610 + for(i=0; i<=0xff; i++) { 611 + outb(i,0x3c4); 612 + printk("SR%02x=%02x ",i,inb(0x3c5)); 613 + if (i%16==15) 614 + printk("\n"); 615 + } 616 + 617 + printk("\n"); 618 + for(i=0; i <= 0x1F; i++) { 619 + inb(0x3da); // next access is index! 620 + outb(i,0x3c0); 621 + printk("AR%02x=%02x ",i,inb(0x3c1)); 622 + if (i%16==15) 623 + printk("\n"); 624 + } 625 + printk("\n"); 626 + 627 + inb(0x3DA); // reset internal flag to 3c0 index 628 + outb(0x20,0x3C0); // enable attr 629 + 630 + return; 631 + } 632 + 633 + //====================================== 634 + // 635 + // Set hardware to requested video mode 636 + // 637 + //====================================== 638 + 639 + static int cyblafb_set_par(struct fb_info *info) 640 + { 641 + struct cyblafb_par *par = info->par; 642 + u32 643 + htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch, 644 + vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend; 645 + struct fb_var_screeninfo *var = &info->var; 646 + int bpp = var->bits_per_pixel; 647 + int i; 648 + 649 + if (verbosity > 0) 650 + output("Switching to new mode: " 651 + "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n", 652 + var->xres,var->yres,var->xres_virtual, 653 + var->yres_virtual,var->bits_per_pixel,var->pixclock, 654 + var->left_margin,var->right_margin,var->upper_margin, 655 + var->lower_margin,var->hsync_len,var->vsync_len); 656 + 657 + htotal = (var->xres + var->left_margin + var->right_margin + 658 + var->hsync_len) / 8 - 5; 659 + hdispend = var->xres/8 - 1; 660 + hsyncstart = (var->xres + var->right_margin)/8; 661 + hsyncend = var->hsync_len/8; 662 + hblankstart = hdispend + 1; 663 + hblankend = htotal + 3; // should be htotal + 5, bios does it this way 664 + preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3); 665 + 666 + vtotal = var->yres + var->upper_margin + var->lower_margin + 667 + var->vsync_len - 2; 668 + vdispend = var->yres - 1; 669 + vsyncstart = var->yres + var->lower_margin; 670 + vblankstart = var->yres; 671 + vblankend = vtotal; // should be vtotal + 2, but bios does it this way 672 + vsyncend = var->vsync_len; 673 + 674 + enable_mmio(); // necessary! ... check X ... 675 + 676 + write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 677 + 678 + write3CE(GR30,8); 679 + 680 + if ((displaytype == DISPLAY_FP) && var->xres < nativex) { 681 + 682 + // stretch or center ? 683 + 684 + out8(0x3C2,0xEB); 685 + 686 + write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on 687 + 688 + if (center) { 689 + write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80); 690 + write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80); 691 + } 692 + else if (stretch) { 693 + write3CE(GR5D,0); 694 + write3CE(GR52,(read3CE(GR52) & 0x7C) | 1); 695 + write3CE(GR53,(read3CE(GR53) & 0x7C) | 1); 696 + } 697 + 698 + } else { 699 + out8(0x3C2,0x2B); 700 + write3CE(GR30,8); 701 + } 702 + 703 + // 704 + // Setup CRxx regs 705 + // 706 + 707 + write3X4(CR00,htotal & 0xFF); 708 + write3X4(CR01,hdispend & 0xFF); 709 + write3X4(CR02,hblankstart & 0xFF); 710 + write3X4(CR03,hblankend & 0x1F); 711 + write3X4(CR04,hsyncstart & 0xFF); 712 + write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2)); 713 + write3X4(CR06,vtotal & 0xFF); 714 + write3X4(CR07,(vtotal & 0x100) >> 8 | 715 + (vdispend & 0x100) >> 7 | 716 + (vsyncstart & 0x100) >> 6 | 717 + (vblankstart & 0x100) >> 5 | 718 + 0x10 | 719 + (vtotal & 0x200) >> 4 | 720 + (vdispend & 0x200) >> 3 | 721 + (vsyncstart & 0x200) >> 2); 722 + write3X4(CR08,0); 723 + write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! 724 + ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); 725 + write3X4(CR0A,0); // Init to some reasonable default 726 + write3X4(CR0B,0); // Init to some reasonable default 727 + write3X4(CR0C,0); // Offset 0 728 + write3X4(CR0D,0); // Offset 0 729 + write3X4(CR0E,0); // Init to some reasonable default 730 + write3X4(CR0F,0); // Init to some reasonable default 731 + write3X4(CR10,vsyncstart & 0xFF); 732 + write3X4(CR11,(vsyncend & 0x0F)); 733 + write3X4(CR12,vdispend & 0xFF); 734 + write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF); 735 + write3X4(CR14,0x40); // double word mode 736 + write3X4(CR15,vblankstart & 0xFF); 737 + write3X4(CR16,vblankend & 0xFF); 738 + write3X4(CR17,0xC3); 739 + write3X4(CR18,0xFF); 740 + // CR19: needed for interlaced modes ... ignore it for now 741 + write3X4(CR1A,0x07); // Arbitration Control Counter 1 742 + write3X4(CR1B,0x07); // Arbitration Control Counter 2 743 + write3X4(CR1C,0x07); // Arbitration Control Counter 3 744 + write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-) 745 + write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); 746 + // CR1F: do not set, contains BIOS info about memsize 747 + write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode 748 + write3X4(CR21,0x20); // enable linear memory access 749 + // CR22: RO cpu latch readback 750 + // CR23: ??? 751 + // CR24: RO AR flag state 752 + // CR25: RAMDAC rw timing, pclk buffer tristate control ???? 753 + // CR26: ??? 754 + write3X4(CR27,(vdispend & 0x400) >> 6 | 755 + (vsyncstart & 0x400) >> 5 | 756 + (vblankstart & 0x400) >> 4 | 757 + (vtotal & 0x400) >> 3 | 758 + 0x8); 759 + // CR28: ??? 760 + write3X4(CR29,(read3X4(CR29) & 0xCF) | 761 + ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4)); 762 + write3X4(CR2A,read3X4(CR2A) | 0x40); 763 + write3X4(CR2B,(htotal & 0x100) >> 8 | 764 + (hdispend & 0x100) >> 7 | 765 + // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? 766 + (hsyncstart & 0x100) >> 5 | 767 + (hblankstart & 0x100) >> 4); 768 + // CR2C: ??? 769 + // CR2D: initialized in cyblafb_setup_GE() 770 + write3X4(CR2F,0x92); // conservative, better signal quality 771 + // CR30: reserved 772 + // CR31: reserved 773 + // CR32: reserved 774 + // CR33: reserved 775 + // CR34: disabled in CR36 776 + // CR35: disabled in CR36 777 + // CR36: initialized in cyblafb_setup_GE 778 + // CR37: i2c, ignore for now 779 + write3X4(CR38,(bpp == 8) ? 0x00 : // 780 + (bpp == 16) ? 0x05 : // highcolor 781 + (bpp == 24) ? 0x29 : // packed 24bit truecolor 782 + (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus 783 + write3X4(CR39,0x01 | // MMIO enable 784 + (pcirb ? 0x02 : 0) | // pci read burst enable 785 + (pciwb ? 0x04 : 0)); // pci write burst enable 786 + write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase 787 + (pcirr ? 0x40 : 0) | // pci read retry enable 788 + (pciwr ? 0x80 : 0)); // pci write retry enable 789 + write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0); 790 + write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); 791 + write3X4(CR58,0x82); // Bios does this .... don't know more 792 + // 793 + // Setup SRxx regs 794 + // 795 + write3C4(SR00,3); 796 + write3C4(SR01,1); //set char clock 8 dots wide 797 + write3C4(SR02,0x0F); //enable 4 maps needed in chain4 mode 798 + write3C4(SR03,0); //no character map select 799 + write3C4(SR04,0x0E); //memory mode: ext mem, even, chain4 800 + 801 + out8(0x3C4,0x0b); 802 + in8(0x3C5); // Set NEW mode 803 + write3C4(SR0D,0x00); // test ... check 804 + 805 + set_vclk(par,(bpp==32 ? 200000000 : 100000000)/ 806 + info->var.pixclock); //SR18,SR19 807 + 808 + // 809 + // Setup GRxx regs 810 + // 811 + write3CE(GR00,0x00); // test ... check 812 + write3CE(GR01,0x00); // test ... check 813 + write3CE(GR02,0x00); // test ... check 814 + write3CE(GR03,0x00); // test ... check 815 + write3CE(GR04,0x00); // test ... check 816 + write3CE(GR05,0x40); // no CGA compat,allow 256 col 817 + write3CE(GR06,0x05); // graphics mode 818 + write3CE(GR07,0x0F); // planes? 819 + write3CE(GR08,0xFF); // test ... check 820 + write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4 821 + write3CE(GR20,0xC0); // test ... check 822 + write3CE(GR2F,0xA0); // PCLK = VCLK, no skew, 823 + 824 + // 825 + // Setup ARxx regs 826 + // 827 + for(i = 0;i < 0x10;i++) // set AR00 .. AR0f 828 + write3C0(i,i); 829 + write3C0(AR10,0x41); // graphics mode and support 256 color modes 830 + write3C0(AR12,0x0F); // planes 831 + write3C0(AR13,0); // horizontal pel panning 832 + in8(0x3DA); // reset internal flag to 3c0 index 833 + out8(0x3C0,0x20); // enable attr 834 + 835 + // 836 + // Setup hidden RAMDAC command register 837 + // 838 + in8(0x3C8); // these reads are 839 + in8(0x3C6); // necessary to 840 + in8(0x3C6); // unmask the RAMDAC 841 + in8(0x3C6); // command reg, otherwise 842 + in8(0x3C6); // we would write the pixelmask reg! 843 + out8(0x3C6,(bpp == 8) ? 0x00 : // 256 colors 844 + (bpp == 15) ? 0x10 : // 845 + (bpp == 16) ? 0x30 : // hicolor 846 + (bpp == 24) ? 0xD0 : // truecolor 847 + (bpp == 32) ? 0xD0 : 0); // truecolor 848 + in8(0x3C8); 849 + 850 + // 851 + // GR31 is not mentioned in the datasheet 852 + // 853 + if (displaytype == DISPLAY_FP) 854 + write3CE(GR31,(read3CE(GR31) & 0x8F) | 855 + ((info->var.yres > 1024) ? 0x50 : 856 + (info->var.yres > 768) ? 0x30 : 857 + (info->var.yres > 600) ? 0x20 : 858 + (info->var.yres > 480) ? 0x10 : 0)); 859 + 860 + info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR 861 + : FB_VISUAL_TRUECOLOR; 862 + info->fix.line_length = info->var.xres * (bpp >> 3); 863 + info->cmap.len = (bpp == 8) ? 256: 16; 864 + 865 + // 866 + // init acceleration engine 867 + // 868 + cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel); 869 + 870 + regdump(par); 871 + 872 + return 0; 873 + } 874 + 875 + //======================== 876 + // 877 + // Set one color register 878 + // 879 + //======================== 880 + 881 + static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green, 882 + unsigned blue, unsigned transp, 883 + struct fb_info *info) 884 + { 885 + int bpp = info->var.bits_per_pixel; 886 + 887 + if (regno >= info->cmap.len) 888 + return 1; 889 + 890 + if (bpp == 8) { 891 + out8(0x3C6,0xFF); 892 + out8(0x3C8,regno); 893 + out8(0x3C9,red>>10); 894 + out8(0x3C9,green>>10); 895 + out8(0x3C9,blue>>10); 896 + 897 + } else if (bpp == 16) // RGB 565 898 + ((u32*)info->pseudo_palette)[regno] = 899 + (red & 0xF800) | 900 + ((green & 0xFC00) >> 5) | 901 + ((blue & 0xF800) >> 11); 902 + else if (bpp == 32) // ARGB 8888 903 + ((u32*)info->pseudo_palette)[regno] = 904 + ((transp & 0xFF00) <<16) | 905 + ((red & 0xFF00) << 8) | 906 + ((green & 0xFF00)) | 907 + ((blue & 0xFF00)>>8); 908 + 909 + return 0; 910 + } 911 + 912 + //========================================================== 913 + // 914 + // Try blanking the screen. For flat panels it does nothing 915 + // 916 + //========================================================== 917 + 918 + static int cyblafb_blank(int blank_mode, struct fb_info *info) 919 + { 920 + unsigned char PMCont,DPMSCont; 921 + 922 + if (displaytype == DISPLAY_FP) 923 + return 0; 924 + 925 + out8(0x83C8,0x04); // DPMS Control 926 + PMCont = in8(0x83C6) & 0xFC; 927 + 928 + DPMSCont = read3CE(GR23) & 0xFC; 929 + 930 + switch (blank_mode) 931 + { 932 + case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On 933 + case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On 934 + PMCont |= 0x03; 935 + DPMSCont |= 0x00; 936 + break; 937 + case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On 938 + PMCont |= 0x02; 939 + DPMSCont |= 0x01; 940 + break; 941 + case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off 942 + PMCont |= 0x02; 943 + DPMSCont |= 0x02; 944 + break; 945 + case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off 946 + PMCont |= 0x00; 947 + DPMSCont |= 0x03; 948 + break; 949 + } 950 + 951 + write3CE(GR23,DPMSCont); 952 + out8(0x83C8,4); 953 + out8(0x83C6,PMCont); 954 + // 955 + // let fbcon do a softblank for us 956 + // 957 + return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; 958 + } 959 + 960 + static struct fb_ops cyblafb_ops __devinitdata = { 961 + .owner = THIS_MODULE, 962 + .fb_setcolreg = cyblafb_setcolreg, 963 + .fb_pan_display = cyblafb_pan_display, 964 + .fb_blank = cyblafb_blank, 965 + .fb_check_var = cyblafb_check_var, 966 + .fb_set_par = cyblafb_set_par, 967 + .fb_fillrect = cyblafb_fillrect, 968 + .fb_copyarea= cyblafb_copyarea, 969 + .fb_imageblit = cyblafb_imageblit, 970 + .fb_cursor = soft_cursor, 971 + }; 972 + 973 + //========================================================================== 974 + // 975 + // getstartupmode() decides about the inital video mode 976 + // 977 + // There is no reason to use modedb, a lot of video modes there would 978 + // need altered timings to display correctly. So I decided that it is much 979 + // better to provide a limited optimized set of modes plus the option of 980 + // using the mode in effect at startup time (might be selected using the 981 + // vga=??? paramter). After that the user might use fbset to select any 982 + // mode he likes, check_var will not try to alter geometry parameters as 983 + // it would be necessary otherwise. 984 + // 985 + //========================================================================== 986 + 987 + static int __devinit getstartupmode(struct fb_info *info) 988 + { 989 + u32 htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend, 990 + vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend, 991 + cr00,cr01,cr02,cr03,cr04,cr05,cr2b, 992 + cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27, 993 + cr38, 994 + sr0d,sr18,sr19, 995 + gr0f, 996 + fi,pxclkdiv,vclkdiv,tmp,i; 997 + 998 + struct modus { 999 + int xres; int yres; int vyres; int bpp; int pxclk; 1000 + int left_margin; int right_margin; int upper_margin; 1001 + int lower_margin; int hsync_len; int vsync_len; 1002 + } modedb[5] = { 1003 + { 0, 0, 8000, 0, 0, 0, 0, 0, 0, 0, 0}, 1004 + { 640, 480, 3756, 0, 0, -40, 24, 17, 0, 216, 3}, 1005 + { 800, 600, 3221, 0, 0, 96, 24, 14, 0, 136, 11}, 1006 + {1024, 768, 2815, 0, 0, 144, 24, 29, 0, 120, 3}, 1007 + {1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160, 3} 1008 + }; 1009 + 1010 + outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5); 1011 + outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5); 1012 + outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5); 1013 + outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5); 1014 + outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5); 1015 + outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5); 1016 + outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5); 1017 + outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5); 1018 + outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5); 1019 + outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5); 1020 + outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf); 1021 + 1022 + htotal = cr00 | (cr2b & 0x01) << 8; 1023 + hdispend = cr01 | (cr2b & 0x02) << 7; 1024 + hblankstart = cr02 | (cr2b & 0x10) << 4; 1025 + hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; 1026 + hsyncstart = cr04 | (cr2b & 0x08) << 5; 1027 + hsyncend = cr05 & 0x1f; 1028 + 1029 + modedb[0].xres = hblankstart * 8; 1030 + modedb[0].hsync_len = hsyncend * 8; 1031 + modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres; 1032 + modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres - 1033 + modedb[0].right_margin - modedb[0].hsync_len; 1034 + 1035 + vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 1036 + | (cr27 & 0x80) << 3; 1037 + vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 1038 + | (cr27 & 0x10) << 6; 1039 + vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 1040 + | (cr27 & 0x20) << 5; 1041 + vsyncend = cr11 & 0x0f; 1042 + vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4 1043 + | (cr27 & 0x40) << 4; 1044 + vblankend = cr16; 1045 + 1046 + modedb[0].yres = vdispend + 1; 1047 + modedb[0].vsync_len = vsyncend; 1048 + modedb[0].lower_margin = vsyncstart - modedb[0].yres; 1049 + modedb[0].upper_margin = vtotal - modedb[0].yres - 1050 + modedb[0].lower_margin - modedb[0].vsync_len + 2; 1051 + 1052 + tmp = cr38 & 0x3c; 1053 + modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 : 1054 + tmp == 8 ? 32 : 8; 1055 + 1056 + fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12; 1057 + pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1; 1058 + tmp = sr0d & 0x06; 1059 + vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 ! 1060 + modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi; 1061 + 1062 + if (verbosity > 0) 1063 + output("detected startup mode: " 1064 + "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n", 1065 + modedb[0].xres,modedb[0].yres,modedb[0].xres, 1066 + modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin, 1067 + modedb[0].right_margin,modedb[0].upper_margin, 1068 + modedb[0].lower_margin,modedb[0].hsync_len, 1069 + modedb[0].vsync_len); 1070 + 1071 + // 1072 + // We use this goto target in case of a failed check_var. No, I really 1073 + // do not want to do it in another way! 1074 + // 1075 + 1076 + tryagain: 1077 + 1078 + i = (mode == NULL) ? 0 : 1079 + !strncmp(mode,"640x480",7) ? 1 : 1080 + !strncmp(mode,"800x600",7) ? 2 : 1081 + !strncmp(mode,"1024x768",8) ? 3 : 1082 + !strncmp(mode,"1280x1024",9) ? 4 : 0; 1083 + 1084 + ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref; 1085 + 1086 + if(i==0) { 1087 + info->var.pixclock = modedb[i].pxclk; 1088 + info->var.bits_per_pixel = modedb[i].bpp; 1089 + } else { 1090 + info->var.pixclock = (100000000 / 1091 + ((modedb[i].left_margin + modedb[i].xres + 1092 + modedb[i].right_margin + modedb[i].hsync_len 1093 + ) * ( 1094 + modedb[i].upper_margin + modedb[i].yres + 1095 + modedb[i].lower_margin + modedb[i].vsync_len 1096 + ) * 1097 + ref / 10000 1098 + )); 1099 + info->var.bits_per_pixel = bpp; 1100 + } 1101 + 1102 + info->var.left_margin = modedb[i].left_margin; 1103 + info->var.right_margin = modedb[i].right_margin; 1104 + info->var.xres = modedb[i].xres; 1105 + info->var.xres_virtual = modedb[i].xres; 1106 + info->var.xoffset = 0; 1107 + info->var.hsync_len = modedb[i].hsync_len; 1108 + info->var.upper_margin = modedb[i].upper_margin; 1109 + info->var.yres = modedb[i].yres; 1110 + info->var.yres_virtual = modedb[i].vyres; 1111 + info->var.yoffset = 0; 1112 + info->var.lower_margin = modedb[i].lower_margin; 1113 + info->var.vsync_len = modedb[i].vsync_len; 1114 + info->var.sync = 0; 1115 + info->var.vmode = FB_VMODE_NONINTERLACED; 1116 + 1117 + if(cyblafb_check_var(&info->var,info)) { 1118 + // 640x480-8@75 should really never fail. One case would 1119 + // be fp == 1 and nativex < 640 ... give up then 1120 + if(i==1 && bpp == 8 && ref == 75){ 1121 + output("Can't find a valid mode :-(\n"); 1122 + return -EINVAL; 1123 + } 1124 + // Our detected mode is unlikely to fail. If it does, 1125 + // try 640x480-8@75 ... 1126 + if(i==0) { 1127 + mode="640x480"; 1128 + bpp=8; 1129 + ref=75; 1130 + output("Detected mode failed check_var! " 1131 + "Trying 640x480-8@75\n"); 1132 + goto tryagain; 1133 + } 1134 + // A specified video mode failed for some reason. 1135 + // Try the startup mode first 1136 + output("Specified mode '%s' failed check! " 1137 + "Falling back to startup mode.\n",mode); 1138 + mode=NULL; 1139 + goto tryagain; 1140 + } 1141 + 1142 + return 0; 1143 + 1144 + } 1145 + 1146 + //======================================================== 1147 + // 1148 + // Detect activated memory size. Undefined values require 1149 + // memsize parameter. 1150 + // 1151 + //======================================================== 1152 + 1153 + static unsigned int __devinit get_memsize(void) 1154 + { 1155 + unsigned char tmp; 1156 + unsigned int k; 1157 + 1158 + if (memsize) 1159 + k = memsize * Kb; 1160 + else { 1161 + tmp = read3X4(CR1F) & 0x0F; 1162 + switch (tmp) { 1163 + case 0x03: k = 1 * Mb; break; 1164 + case 0x07: k = 2 * Mb; break; 1165 + case 0x0F: k = 4 * Mb; break; 1166 + case 0x04: k = 8 * Mb; break; 1167 + default: 1168 + k = 1 * Mb; 1169 + output("Unknown memory size code %x in CR1F." 1170 + " We default to 1 Mb for now, please" 1171 + " do provide a memsize parameter!\n", 1172 + tmp); 1173 + } 1174 + } 1175 + 1176 + if (verbosity > 0) 1177 + output("framebuffer size = %d Kb\n",k/Kb); 1178 + return k; 1179 + } 1180 + 1181 + //========================================================= 1182 + // 1183 + // Detect if a flat panel monitor connected to the special 1184 + // interface is active. Override is possible by fp and crt 1185 + // parameters. 1186 + // 1187 + //========================================================= 1188 + 1189 + static unsigned int __devinit get_displaytype(void) 1190 + { 1191 + if (fp) 1192 + return DISPLAY_FP; 1193 + if (crt) 1194 + return DISPLAY_CRT; 1195 + return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT; 1196 + } 1197 + 1198 + //===================================== 1199 + // 1200 + // Get native resolution of flat panel 1201 + // 1202 + //===================================== 1203 + 1204 + static int __devinit get_nativex(void) 1205 + { 1206 + int x,y,tmp; 1207 + 1208 + if (nativex) 1209 + return nativex; 1210 + 1211 + tmp = (read3CE(GR52) >> 4) & 3; 1212 + 1213 + switch (tmp) { 1214 + case 0: x = 1280; y = 1024; break; 1215 + case 2: x = 1024; y = 768; break; 1216 + case 3: x = 800; y = 600; break; 1217 + case 4: x = 1400; y = 1050; break; 1218 + case 1: 1219 + default: x = 640; y = 480; break; 1220 + } 1221 + 1222 + if (verbosity > 0) 1223 + output("%dx%d flat panel found\n",x,y); 1224 + return x; 1225 + } 1226 + 1227 + static int __devinit cybla_pci_probe(struct pci_dev * dev, 1228 + const struct pci_device_id * id) 1229 + { 1230 + struct fb_info *info; 1231 + struct cyblafb_par *par; 1232 + 1233 + info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev); 1234 + 1235 + if (!info) 1236 + goto errout_alloc; 1237 + 1238 + par = info->par; 1239 + par->ops = cyblafb_ops; 1240 + 1241 + info->fix = cyblafb_fix; 1242 + info->fbops = &par->ops; 1243 + info->fix = cyblafb_fix; 1244 + 1245 + if (pci_enable_device(dev)) { 1246 + output("could not enable device!\n"); 1247 + goto errout_enable; 1248 + } 1249 + 1250 + // might already be requested by vga console or vesafb, 1251 + // so we do care about success 1252 + request_region(0x3c0,32,"cyblafb"); 1253 + 1254 + // 1255 + // Graphics Engine Registers 1256 + // 1257 + request_region(GEBase,0x100,"cyblafb"); 1258 + 1259 + regdump(par); 1260 + 1261 + enable_mmio(); 1262 + 1263 + // setup MMIO region 1264 + info->fix.mmio_start = pci_resource_start(dev,1); 1265 + info->fix.mmio_len = 0x20000; 1266 + 1267 + if (!request_mem_region(info->fix.mmio_start, 1268 + info->fix.mmio_len,"cyblafb")) { 1269 + output("request_mem_region failed for mmio region!\n"); 1270 + goto errout_mmio_reqmem; 1271 + } 1272 + 1273 + io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); 1274 + 1275 + if (!io_virt) { 1276 + output("ioremap failed for mmio region\n"); 1277 + goto errout_mmio_remap; 1278 + } 1279 + 1280 + // setup framebuffer memory ... might already be requested 1281 + // by vesafb. Not to fail in case of an unsuccessful request 1282 + // is useful for the development cycle 1283 + info->fix.smem_start = pci_resource_start(dev,0); 1284 + info->fix.smem_len = get_memsize(); 1285 + 1286 + if (!request_mem_region(info->fix.smem_start, 1287 + info->fix.smem_len,"cyblafb")) { 1288 + output("request_mem_region failed for smem region!\n"); 1289 + if (!vesafb) 1290 + goto errout_smem_req; 1291 + } 1292 + 1293 + info->screen_base = ioremap_nocache(info->fix.smem_start, 1294 + info->fix.smem_len); 1295 + 1296 + if (!info->screen_base) { 1297 + output("ioremap failed for smem region\n"); 1298 + goto errout_smem_remap; 1299 + } 1300 + 1301 + displaytype = get_displaytype(); 1302 + 1303 + if(displaytype == DISPLAY_FP) 1304 + nativex = get_nativex(); 1305 + 1306 + // 1307 + // FBINFO_HWACCEL_YWRAP .... does not work (could be made to work?) 1308 + // FBINFO_PARTIAL_PAN_OK .... is not ok 1309 + // FBINFO_READS_FAST .... is necessary for optimal scrolling 1310 + // 1311 + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN 1312 + | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT 1313 + | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST; 1314 + 1315 + info->pseudo_palette = par->pseudo_pal; 1316 + 1317 + if(getstartupmode(info)) 1318 + goto errout_findmode; 1319 + 1320 + fb_alloc_cmap(&info->cmap,256,0); 1321 + 1322 + if (register_framebuffer(info)) { 1323 + output("Could not register CyBla framebuffer\n"); 1324 + goto errout_register; 1325 + } 1326 + 1327 + pci_set_drvdata(dev,info); 1328 + 1329 + // 1330 + // normal exit and error paths 1331 + // 1332 + 1333 + return 0; 1334 + 1335 + errout_register: 1336 + errout_findmode: 1337 + iounmap(info->screen_base); 1338 + errout_smem_remap: 1339 + release_mem_region(info->fix.smem_start, 1340 + info->fix.smem_len); 1341 + errout_smem_req: 1342 + iounmap(io_virt); 1343 + errout_mmio_remap: 1344 + release_mem_region(info->fix.mmio_start, 1345 + info->fix.mmio_len); 1346 + errout_mmio_reqmem: 1347 + // release_region(0x3c0,32); 1348 + errout_enable: 1349 + framebuffer_release(info); 1350 + errout_alloc: 1351 + output("CyblaFB version %s aborting init.\n",VERSION); 1352 + return -ENODEV; 1353 + } 1354 + 1355 + static void __devexit cybla_pci_remove(struct pci_dev *dev) 1356 + { 1357 + struct fb_info *info = pci_get_drvdata(dev); 1358 + 1359 + unregister_framebuffer(info); 1360 + iounmap(io_virt); 1361 + iounmap(info->screen_base); 1362 + release_mem_region(info->fix.smem_start,info->fix.smem_len); 1363 + release_mem_region(info->fix.mmio_start,info->fix.mmio_len); 1364 + fb_dealloc_cmap(&info->cmap); 1365 + framebuffer_release(info); 1366 + output("CyblaFB version %s normal exit.\n",VERSION); 1367 + } 1368 + 1369 + // 1370 + // List of boards that we are trying to support 1371 + // 1372 + static struct pci_device_id cybla_devices[] = { 1373 + {PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, 1374 + {0,} 1375 + }; 1376 + 1377 + MODULE_DEVICE_TABLE(pci,cybla_devices); 1378 + 1379 + static struct pci_driver cyblafb_pci_driver = { 1380 + .name = "cyblafb", 1381 + .id_table = cybla_devices, 1382 + .probe = cybla_pci_probe, 1383 + .remove = __devexit_p(cybla_pci_remove) 1384 + }; 1385 + 1386 + //============================================================= 1387 + // 1388 + // kernel command line example: 1389 + // 1390 + // video=cyblafb:1280x1024,bpp=16,ref=50 ... 1391 + // 1392 + // modprobe command line example: 1393 + // 1394 + // modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ... 1395 + // 1396 + //============================================================= 1397 + 1398 + static int __devinit cyblafb_init(void) 1399 + { 1400 + #ifndef MODULE 1401 + char *options = NULL; 1402 + char *opt; 1403 + 1404 + if (fb_get_options("cyblafb",&options)) 1405 + return -ENODEV; 1406 + 1407 + if (options && *options) 1408 + while((opt = strsep(&options,",")) != NULL ) { 1409 + if (!*opt) continue; 1410 + else if (!strncmp(opt,"bpp=",4)) 1411 + bpp = simple_strtoul(opt+4,NULL,0); 1412 + else if (!strncmp(opt,"ref=",4)) 1413 + ref = simple_strtoul(opt+4,NULL,0); 1414 + else if (!strncmp(opt,"fp",2)) 1415 + displaytype = DISPLAY_FP; 1416 + else if (!strncmp(opt,"crt",3)) 1417 + displaytype = DISPLAY_CRT; 1418 + else if (!strncmp(opt,"nativex=",8)) 1419 + nativex = simple_strtoul(opt+8,NULL,0); 1420 + else if (!strncmp(opt,"center",6)) 1421 + center = 1; 1422 + else if (!strncmp(opt,"stretch",7)) 1423 + stretch = 1; 1424 + else if (!strncmp(opt,"pciwb=",6)) 1425 + pciwb = simple_strtoul(opt+6,NULL,0); 1426 + else if (!strncmp(opt,"pcirb=",6)) 1427 + pcirb = simple_strtoul(opt+6,NULL,0); 1428 + else if (!strncmp(opt,"pciwr=",6)) 1429 + pciwr = simple_strtoul(opt+6,NULL,0); 1430 + else if (!strncmp(opt,"pcirr=",6)) 1431 + pcirr = simple_strtoul(opt+6,NULL,0); 1432 + else if (!strncmp(opt,"memsize=",8)) 1433 + memsize = simple_strtoul(opt+8,NULL,0); 1434 + else if (!strncmp(opt,"verbosity=",10)) 1435 + verbosity = simple_strtoul(opt+10,NULL,0); 1436 + else if (!strncmp(opt,"vesafb",6)) 1437 + vesafb = 1; 1438 + else 1439 + mode = opt; 1440 + } 1441 + #endif 1442 + output("CyblaFB version %s initializing\n",VERSION); 1443 + return pci_module_init(&cyblafb_pci_driver); 1444 + } 1445 + 1446 + static void __exit cyblafb_exit(void) 1447 + { 1448 + pci_unregister_driver(&cyblafb_pci_driver); 1449 + } 1450 + 1451 + module_init(cyblafb_init); 1452 + module_exit(cyblafb_exit); 1453 + 1454 + MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>"); 1455 + MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core"); 1456 + MODULE_LICENSE("GPL");
+5
drivers/video/tridentfb.c
··· 1061 1061 1062 1062 chip_id = id->device; 1063 1063 1064 + if(chip_id == CYBERBLADEi1) 1065 + output("*** Please do use cyblafb, Cyberblade/i1 support " 1066 + "will soon be removed from tridentfb!\n"); 1067 + 1068 + 1064 1069 /* If PCI id is 0x9660 then further detect chip type */ 1065 1070 1066 1071 if (chip_id == TGUI9660) {
+171
include/video/cyblafb.h
··· 1 + 2 + #ifndef CYBLAFB_DEBUG 3 + #define CYBLAFB_DEBUG 0 4 + #endif 5 + 6 + #if CYBLAFB_DEBUG 7 + #define debug(f,a...) printk("%s:" f, __FUNCTION__ , ## a); 8 + #else 9 + #define debug(f,a...) 10 + #endif 11 + 12 + #define output(f, a...) printk("cyblafb: " f, ## a) 13 + 14 + #define Kb (1024) 15 + #define Mb (Kb*Kb) 16 + 17 + /* PCI IDS of supported cards temporarily here */ 18 + 19 + #define CYBERBLADEi1 0x8500 20 + 21 + /* these defines are for 'lcd' variable */ 22 + #define LCD_STRETCH 0 23 + #define LCD_CENTER 1 24 + #define LCD_BIOS 2 25 + 26 + /* display types */ 27 + #define DISPLAY_CRT 0 28 + #define DISPLAY_FP 1 29 + 30 + #define ROP_S 0xCC 31 + 32 + #define point(x,y) ((y)<<16|(x)) 33 + 34 + // 35 + // Attribute Regs, ARxx, 3c0/3c1 36 + // 37 + #define AR00 0x00 38 + #define AR01 0x01 39 + #define AR02 0x02 40 + #define AR03 0x03 41 + #define AR04 0x04 42 + #define AR05 0x05 43 + #define AR06 0x06 44 + #define AR07 0x07 45 + #define AR08 0x08 46 + #define AR09 0x09 47 + #define AR0A 0x0A 48 + #define AR0B 0x0B 49 + #define AR0C 0x0C 50 + #define AR0D 0x0D 51 + #define AR0E 0x0E 52 + #define AR0F 0x0F 53 + #define AR10 0x10 54 + #define AR12 0x12 55 + #define AR13 0x13 56 + 57 + // 58 + // Sequencer Regs, SRxx, 3c4/3c5 59 + // 60 + #define SR00 0x00 61 + #define SR01 0x01 62 + #define SR02 0x02 63 + #define SR03 0x03 64 + #define SR04 0x04 65 + #define SR0D 0x0D 66 + #define SR0E 0x0E 67 + #define SR11 0x11 68 + #define SR18 0x18 69 + #define SR19 0x19 70 + 71 + // 72 + // 73 + // 74 + #define CR00 0x00 75 + #define CR01 0x01 76 + #define CR02 0x02 77 + #define CR03 0x03 78 + #define CR04 0x04 79 + #define CR05 0x05 80 + #define CR06 0x06 81 + #define CR07 0x07 82 + #define CR08 0x08 83 + #define CR09 0x09 84 + #define CR0A 0x0A 85 + #define CR0B 0x0B 86 + #define CR0C 0x0C 87 + #define CR0D 0x0D 88 + #define CR0E 0x0E 89 + #define CR0F 0x0F 90 + #define CR10 0x10 91 + #define CR11 0x11 92 + #define CR12 0x12 93 + #define CR13 0x13 94 + #define CR14 0x14 95 + #define CR15 0x15 96 + #define CR16 0x16 97 + #define CR17 0x17 98 + #define CR18 0x18 99 + #define CR19 0x19 100 + #define CR1A 0x1A 101 + #define CR1B 0x1B 102 + #define CR1C 0x1C 103 + #define CR1D 0x1D 104 + #define CR1E 0x1E 105 + #define CR1F 0x1F 106 + #define CR20 0x20 107 + #define CR21 0x21 108 + #define CR27 0x27 109 + #define CR29 0x29 110 + #define CR2A 0x2A 111 + #define CR2B 0x2B 112 + #define CR2D 0x2D 113 + #define CR2F 0x2F 114 + #define CR36 0x36 115 + #define CR38 0x38 116 + #define CR39 0x39 117 + #define CR3A 0x3A 118 + #define CR55 0x55 119 + #define CR56 0x56 120 + #define CR57 0x57 121 + #define CR58 0x58 122 + 123 + // 124 + // 125 + // 126 + 127 + #define GR00 0x01 128 + #define GR01 0x01 129 + #define GR02 0x02 130 + #define GR03 0x03 131 + #define GR04 0x04 132 + #define GR05 0x05 133 + #define GR06 0x06 134 + #define GR07 0x07 135 + #define GR08 0x08 136 + #define GR0F 0x0F 137 + #define GR20 0x20 138 + #define GR23 0x23 139 + #define GR2F 0x2F 140 + #define GR30 0x30 141 + #define GR31 0x31 142 + #define GR33 0x33 143 + #define GR52 0x52 144 + #define GR53 0x53 145 + #define GR5D 0x5d 146 + 147 + 148 + // 149 + // Graphics Engine 150 + // 151 + #define GEBase 0x2100 // could be mapped elsewhere if we like it 152 + #define GE00 (GEBase+0x00) // source 1, p 111 153 + #define GE04 (GEBase+0x04) // source 2, p 111 154 + #define GE08 (GEBase+0x08) // destination 1, p 111 155 + #define GE0C (GEBase+0x0C) // destination 2, p 112 156 + #define GE20 (GEBase+0x20) // engine status, p 113 157 + #define GE24 (GEBase+0x24) // reset all GE pointers 158 + #define GE44 (GEBase+0x44) // command register, p 126 159 + #define GE48 (GEBase+0x48) // raster operation, p 127 160 + #define GE60 (GEBase+0x60) // foreground color, p 128 161 + #define GE64 (GEBase+0x64) // background color, p 128 162 + #define GE6C (GEBase+0x6C) // Pattern and Style, p 129, ok 163 + #define GE9C (GEBase+0x9C) // pixel engine data port, p 125 164 + #define GEB8 (GEBase+0xB8) // Destination Stride / Buffer Base 0, p 133 165 + #define GEBC (GEBase+0xBC) // Destination Stride / Buffer Base 1, p 133 166 + #define GEC0 (GEBase+0xC0) // Destination Stride / Buffer Base 2, p 133 167 + #define GEC4 (GEBase+0xC4) // Destination Stride / Buffer Base 3, p 133 168 + #define GEC8 (GEBase+0xC8) // Source Stride / Buffer Base 0, p 133 169 + #define GECC (GEBase+0xCC) // Source Stride / Buffer Base 1, p 133 170 + #define GED0 (GEBase+0xD0) // Source Stride / Buffer Base 2, p 133 171 + #define GED4 (GEBase+0xD4) // Source Stride / Buffer Base 3, p 133