aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKnut Petersen <Knut_Petersen@t-online.de>2005-09-09 16:04:56 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 16:58:02 -0400
commit9fa68eae9f8291a98bfe00b94b78f72eb253165a (patch)
treef3619e7302871a5d56264f6df4076c30857483ce
parent6062bfa1644f401c08e78d5c8a161f7d11c5c830 (diff)
[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>
-rw-r--r--Documentation/fb/cyblafb/bugs14
-rw-r--r--Documentation/fb/cyblafb/credits7
-rw-r--r--Documentation/fb/cyblafb/documentation17
-rw-r--r--Documentation/fb/cyblafb/fb.modes155
-rw-r--r--Documentation/fb/cyblafb/performance80
-rw-r--r--Documentation/fb/cyblafb/todo32
-rw-r--r--Documentation/fb/cyblafb/usage206
-rw-r--r--Documentation/fb/cyblafb/whycyblafb85
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/video/Kconfig31
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/cyblafb.c1456
-rw-r--r--drivers/video/tridentfb.c5
-rw-r--r--include/video/cyblafb.h171
14 files changed, 2266 insertions, 2 deletions
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs
new file mode 100644
index 000000000000..f90cc66ea919
--- /dev/null
+++ b/Documentation/fb/cyblafb/bugs
@@ -0,0 +1,14 @@
1Bugs
2====
3
4I 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
9Untested features
10=================
11
12All LCD stuff is untested. If it worked in tridentfb, it should work in
13cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
14
diff --git a/Documentation/fb/cyblafb/credits b/Documentation/fb/cyblafb/credits
new file mode 100644
index 000000000000..0eb3b443dc2b
--- /dev/null
+++ b/Documentation/fb/cyblafb/credits
@@ -0,0 +1,7 @@
1Thanks 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
diff --git a/Documentation/fb/cyblafb/documentation b/Documentation/fb/cyblafb/documentation
new file mode 100644
index 000000000000..bb1aac048425
--- /dev/null
+++ b/Documentation/fb/cyblafb/documentation
@@ -0,0 +1,17 @@
1Available Documentation
2=======================
3
4Apollo PLE 133 Chipset VT8601A North Bridge Datasheet, Rev. 1.82, October 22,
52001, available from VIA:
6
7 http://www.viavpsd.com/product/6/15/DS8601A182.pdf
8
9The datasheet is incomplete, some registers that need to be programmed are not
10explained at all and important bits are listed as "reserved". But you really
11need the datasheet to understand the code. "p. xxx" comments refer to page
12numbers of this document.
13
14XFree/XOrg drivers are available and of good quality, looking at the code
15there is a good idea if the datasheet does not provide enough information
16or if the datasheet seems to be wrong.
17
diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes
new file mode 100644
index 000000000000..cf4351fc32ff
--- /dev/null
+++ b/Documentation/fb/cyblafb/fb.modes
@@ -0,0 +1,155 @@
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
16mode "640x480-50"
17 geometry 640 480 640 3756 8
18 timings 47619 4294967256 24 17 0 216 3
19endmode
20
21mode "640x480-60"
22 geometry 640 480 640 3756 8
23 timings 39682 4294967256 24 17 0 216 3
24endmode
25
26mode "640x480-70"
27 geometry 640 480 640 3756 8
28 timings 34013 4294967256 24 17 0 216 3
29endmode
30
31mode "640x480-72"
32 geometry 640 480 640 3756 8
33 timings 33068 4294967256 24 17 0 216 3
34endmode
35
36mode "640x480-75"
37 geometry 640 480 640 3756 8
38 timings 31746 4294967256 24 17 0 216 3
39endmode
40
41mode "640x480-80"
42 geometry 640 480 640 3756 8
43 timings 29761 4294967256 24 17 0 216 3
44endmode
45
46mode "640x480-85"
47 geometry 640 480 640 3756 8
48 timings 28011 4294967256 24 17 0 216 3
49endmode
50
51mode "800x600-50"
52 geometry 800 600 800 3221 8
53 timings 30303 96 24 14 0 136 11
54endmode
55
56mode "800x600-60"
57 geometry 800 600 800 3221 8
58 timings 25252 96 24 14 0 136 11
59endmode
60
61mode "800x600-70"
62 geometry 800 600 800 3221 8
63 timings 21645 96 24 14 0 136 11
64endmode
65
66mode "800x600-72"
67 geometry 800 600 800 3221 8
68 timings 21043 96 24 14 0 136 11
69endmode
70
71mode "800x600-75"
72 geometry 800 600 800 3221 8
73 timings 20202 96 24 14 0 136 11
74endmode
75
76mode "800x600-80"
77 geometry 800 600 800 3221 8
78 timings 18939 96 24 14 0 136 11
79endmode
80
81mode "800x600-85"
82 geometry 800 600 800 3221 8
83 timings 17825 96 24 14 0 136 11
84endmode
85
86mode "1024x768-50"
87 geometry 1024 768 1024 2815 8
88 timings 19054 144 24 29 0 120 3
89endmode
90
91mode "1024x768-60"
92 geometry 1024 768 1024 2815 8
93 timings 15880 144 24 29 0 120 3
94endmode
95
96mode "1024x768-70"
97 geometry 1024 768 1024 2815 8
98 timings 13610 144 24 29 0 120 3
99endmode
100
101mode "1024x768-72"
102 geometry 1024 768 1024 2815 8
103 timings 13232 144 24 29 0 120 3
104endmode
105
106mode "1024x768-75"
107 geometry 1024 768 1024 2815 8
108 timings 12703 144 24 29 0 120 3
109endmode
110
111mode "1024x768-80"
112 geometry 1024 768 1024 2815 8
113 timings 11910 144 24 29 0 120 3
114endmode
115
116mode "1024x768-85"
117 geometry 1024 768 1024 2815 8
118 timings 11209 144 24 29 0 120 3
119endmode
120
121mode "1280x1024-50"
122 geometry 1280 1024 1280 2662 8
123 timings 11114 232 16 39 0 160 3
124endmode
125
126mode "1280x1024-60"
127 geometry 1280 1024 1280 2662 8
128 timings 9262 232 16 39 0 160 3
129endmode
130
131mode "1280x1024-70"
132 geometry 1280 1024 1280 2662 8
133 timings 7939 232 16 39 0 160 3
134endmode
135
136mode "1280x1024-72"
137 geometry 1280 1024 1280 2662 8
138 timings 7719 232 16 39 0 160 3
139endmode
140
141mode "1280x1024-75"
142 geometry 1280 1024 1280 2662 8
143 timings 7410 232 16 39 0 160 3
144endmode
145
146mode "1280x1024-80"
147 geometry 1280 1024 1280 2662 8
148 timings 6946 232 16 39 0 160 3
149endmode
150
151mode "1280x1024-85"
152 geometry 1280 1024 1280 2662 8
153 timings 6538 232 16 39 0 160 3
154endmode
155
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance
new file mode 100644
index 000000000000..eb4e47a9cea6
--- /dev/null
+++ b/Documentation/fb/cyblafb/performance
@@ -0,0 +1,80 @@
1Speed
2=====
3
4CyBlaFB is much faster than tridentfb and vesafb. Compare the performance data
5for mode 1280x1024-[8,16,32]@61 Hz.
6
7Test 1: Cat a file with 2000 lines of 0 characters.
8Test 2: Cat a file with 2000 lines of 80 characters.
9Test 3: Cat a file with 2000 lines of 160 characters.
10
11All values show system time use in seconds, kernel 2.6.12 was used for
12the measurements. 2.6.13 is a bit slower, 2.6.14 hopefully will include a
13patch 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
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo
new file mode 100644
index 000000000000..80fb2f89b6c1
--- /dev/null
+++ b/Documentation/fb/cyblafb/todo
@@ -0,0 +1,32 @@
1TODO / Missing features
2=======================
3
4Verify 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
10Interlaced 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
18low-res double scan modes Who needs it?
19
20accelerated 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
25xpanning Who needs it?
26
27ioctls Who needs it?
28
29TV-out Will be done later
30
31??? Feel free to contact me if you have any
32 feature requests
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage
new file mode 100644
index 000000000000..e627c8f54211
--- /dev/null
+++ b/Documentation/fb/cyblafb/usage
@@ -0,0 +1,206 @@
1CyBlaFB is a framebuffer driver for the Cyberblade/i1 graphics core integrated
2into the VIA Apollo PLE133 (aka vt8601) south bridge. It is developed and
3tested using a VIA EPIA 5000 board.
4
5Cyblafb - compiled into the kernel or as a module?
6==================================================
7
8You might compile cyblafb either as a module or compile it permanently into the
9kernel.
10
11Unless you have a real reason to do so you should not compile both vesafb and
12cyblafb permanently into the kernel. It's possible and it helps during the
13developement cycle, but it's useless and will at least block some otherwise
14usefull memory for ordinary users.
15
16Selecting 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
87Other Parameters
88================
89
90
91crt don't autodetect, assume monitor connected to
92 standard VGA connector
93
94fp don't autodetect, assume flat panel display
95 connected to flat panel monitor interface
96
97nativex inform driver about native x resolution of
98 flat panel monitor connected to special
99 interface (should be autodetected)
100
101stretch stretch image to adapt low resolution modes to
102 higer resolutions of flat panel monitors
103 connected to special interface
104
105center center image to adapt low resolution modes to
106 higer resolutions of flat panel monitors
107 connected to special interface
108
109memsize use if autodetected memsize is wrong ...
110 should never be necessary
111
112nopcirr disable PCI read retry
113nopciwr disable PCI write retry
114nopcirb disable PCI read bursts
115nopciwb disable PCI write bursts
116
117bpp bpp for specified modes
118 valid values: 8 || 16 || 24 || 32
119
120ref refresh rate for specified mode
121 valid values: 50 <= ref <= 85
122
123mode 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
129verbosity 0 is the default, increase to at least 2 for every
130 bug report!
131
132vesafb allows cyblafb to be loaded after vesafb has been
133 loaded. See sections "Module unloading ...".
134
135
136Development hints
137=================
138
139It's much faster do compile a module and to load the new version after
140unloading the old module than to compile a new kernel and to reboot. So if you
141try to work on cyblafb, it might be a good idea to use cyblafb as a module.
142In real life, fast often means dangerous, and that's also the case here. If
143you introduce a serious bug when cyblafb is compiled into the kernel, the
144kernel will lock or oops with a high probability before the file system is
145mounted, and the danger for your data is low. If you load a broken own version
146of cyblafb on a running system, the danger for the integrity of the file
147system is much higher as you might need a hard reset afterwards. Decide
148yourself.
149
150Module unloading, the vfb method
151================================
152
153If you want to unload/reload cyblafb using the virtual framebuffer, you need
154to enable vfb support in the kernel first. After that, load the modules as
155shown 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
164If you now made some changes to cyblafb and want to reload it, you might do it
165as show below:
166
167 con2fb /dev/fb0 /dev/tty1
168 ...
169 rmmod cyblafb
170 modprobe cyblafb
171 con2fb /dev/fb1 /dev/tty1
172 ...
173
174Of course, you might choose another mode, and most certainly you also want to
175map some other /dev/tty* to the real framebuffer device. You might also choose
176to compile fbcon as a kernel module or place it permanently in the kernel.
177
178I do not know of any way to unload fbcon, and fbcon will prevent the
179framebuffer device loaded first from unloading. [If there is a way, then
180please add a description here!]
181
182Module unloading, the vesafb method
183===================================
184
185Configure the kernel:
186
187 <*> Support for frame buffer devices
188 [*] VESA VGA graphics support
189 <M> Cyberblade/i1 support
190
191Add e.g. "video=vesafb:ypan vga=0x307" to the kernel parameters. The ypan
192parameter is important, choose any vga parameter you like as long as it is
193a graphics mode.
194
195After booting, load cyblafb without any mode and bpp parameter and assign
196cyblafb to individual ttys using con2fb, e.g.:
197
198 modprobe cyblafb vesafb=1
199 con2fb /dev/fb1 /dev/tty1
200
201Unloading cyblafb works without problems after you assign vesafb to all
202ttys again, e.g.:
203
204 con2fb /dev/fb0 /dev/tty1
205 rmmod cyblafb
206
diff --git a/Documentation/fb/cyblafb/whycyblafb b/Documentation/fb/cyblafb/whycyblafb
new file mode 100644
index 000000000000..a123bc11e698
--- /dev/null
+++ b/Documentation/fb/cyblafb/whycyblafb
@@ -0,0 +1,85 @@
1I 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
20None of these drivers was a real option for me.
21
22I believe that is unreasonable to change code that announces to support 20
23devices if I only have more or less sufficient documentation for exactly one
24of these. The risk of breaking device foo while fixing device bar is too high.
25
26So I decided to start CyBlaFB as a stripped down tridentfb.
27
28All code specific to other Trident chips has been removed. After that there
29were a lot of cosmetic changes to increase the readability of the code. All
30register names were changed to those mnemonics used in the datasheet. Function
31and macro names were changed if they hindered easy understanding of the code.
32
33After that I debugged the code and implemented some new features. I'll try to
34give 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
diff --git a/MAINTAINERS b/MAINTAINERS
index 8429bdb1d2a1..9c9a86d0685a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -626,6 +626,12 @@ M: rmk@arm.linux.org.uk
626W: http://www.arm.linux.org.uk/ 626W: http://www.arm.linux.org.uk/
627S: Maintained 627S: Maintained
628 628
629CYBLAFB FRAMEBUFFER DRIVER
630P: Knut Petersen
631M: Knut_Petersen@t-online.de
632L: linux-fbdev-devel@lists.sourceforge.net
633S: Maintained
634
629CYCLADES 2X SYNC CARD DRIVER 635CYCLADES 2X SYNC CARD DRIVER
630P: Arnaldo Carvalho de Melo 636P: Arnaldo Carvalho de Melo
631M: acme@conectiva.com.br 637M: acme@conectiva.com.br
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index e906b5421795..e27aefd49ea3 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1177,6 +1177,32 @@ config FB_VOODOO1
1177 Please read the <file:Documentation/fb/README-sstfb.txt> for supported 1177 Please read the <file:Documentation/fb/README-sstfb.txt> for supported
1178 options and other important info support. 1178 options and other important info support.
1179 1179
1180config 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
1180config FB_TRIDENT 1206config FB_TRIDENT
1181 tristate "Trident support" 1207 tristate "Trident support"
1182 depends on FB && PCI 1208 depends on FB && PCI
@@ -1190,8 +1216,12 @@ config FB_TRIDENT
1190 but also on some motherboards. For more information, read 1216 but also on some motherboards. For more information, read
1191 <file:Documentation/fb/tridentfb.txt> 1217 <file:Documentation/fb/tridentfb.txt>
1192 1218
1219 Cyberblade/i1 support will be removed soon, use the cyblafb driver
1220 instead.
1221
1193 Say Y if you have such a graphics board. 1222 Say Y if you have such a graphics board.
1194 1223
1224
1195 To compile this driver as a module, choose M here: the 1225 To compile this driver as a module, choose M here: the
1196 module will be called tridentfb. 1226 module will be called tridentfb.
1197 1227
@@ -1202,7 +1232,6 @@ config FB_TRIDENT_ACCEL
1202 This will compile the Trident frame buffer device with 1232 This will compile the Trident frame buffer device with
1203 acceleration functions. 1233 acceleration functions.
1204 1234
1205
1206config FB_PM3 1235config FB_PM3
1207 tristate "Permedia3 support" 1236 tristate "Permedia3 support"
1208 depends on FB && PCI && BROKEN 1237 depends on FB && PCI && BROKEN
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b018df4e95c8..8478d217aaf0 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -50,7 +50,8 @@ obj-$(CONFIG_FB_CT65550) += chipsfb.o
50obj-$(CONFIG_FB_IMSTT) += imsttfb.o 50obj-$(CONFIG_FB_IMSTT) += imsttfb.o
51obj-$(CONFIG_FB_S3TRIO) += S3triofb.o 51obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
52obj-$(CONFIG_FB_FM2) += fm2fb.o 52obj-$(CONFIG_FB_FM2) += fm2fb.o
53obj-$(CONFIG_FB_TRIDENT) += tridentfb.o 53obj-$(CONFIG_FB_CYBLA) += cyblafb.o
54obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
54obj-$(CONFIG_FB_STI) += stifb.o 55obj-$(CONFIG_FB_STI) += stifb.o
55obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o 56obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o
56obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o 57obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
new file mode 100644
index 000000000000..ae2762cb5608
--- /dev/null
+++ b/drivers/video/cyblafb.c
@@ -0,0 +1,1456 @@
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
27struct cyblafb_par {
28 u32 pseudo_pal[16];
29 struct fb_ops ops;
30};
31
32static 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
40static char *mode __devinitdata = NULL;
41static int bpp __devinitdata = 8;
42static int ref __devinitdata = 75;
43static int fp __devinitdata;
44static int crt __devinitdata;
45static int memsize __devinitdata;
46static int vesafb __devinitdata;
47
48static int nativex;
49static int center;
50static int stretch;
51static int pciwb = 1;
52static int pcirb = 1;
53static int pciwr = 1;
54static int pcirr = 1;
55static int verbosity;
56static int displaytype;
57
58static void __iomem * io_virt; // iospace virtual memory address
59
60module_param(mode,charp,0);
61module_param(bpp,int,0);
62module_param(ref,int,0);
63module_param(fp,int,0);
64module_param(crt,int,0);
65module_param(nativex,int,0);
66module_param(center,int,0);
67module_param(stretch,int,0);
68module_param(pciwb,int,0);
69module_param(pcirb,int,0);
70module_param(pciwr,int,0);
71module_param(pcirr,int,0);
72module_param(memsize,int,0);
73module_param(verbosity,int,0);
74module_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
93static inline unsigned char read3X4(int reg)
94{
95 out8(0x3D4,reg);
96 return in8(0x3D5);
97}
98
99static inline unsigned char read3C4(int reg)
100{
101 out8(0x3C4,reg);
102 return in8(0x3C5);
103}
104
105static inline unsigned char read3CE(int reg)
106{
107 out8(0x3CE,reg);
108 return in8(0x3CF);
109}
110
111static inline void write3X4(int reg,unsigned char val)
112{
113 out8(0x3D4,reg);
114 out8(0x3D5,val);
115}
116
117static inline void write3C4(int reg,unsigned char val)
118{
119 out8(0x3C4,reg);
120 out8(0x3C5,val);
121}
122
123static inline void write3CE(int reg,unsigned char val)
124{
125 out8(0x3CE,reg);
126 out8(0x3CF,val);
127}
128
129static 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
142static 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
171static 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
202static 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
241static 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
294static 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
329static 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
363static 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
441static 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
547static 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
572static 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
639static 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
881static 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
918static 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
960static 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
987static 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
1153static 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
1189static 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
1204static 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
1227static 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
1355static 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//
1372static 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
1377MODULE_DEVICE_TABLE(pci,cybla_devices);
1378
1379static 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
1398static 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
1446static void __exit cyblafb_exit(void)
1447{
1448 pci_unregister_driver(&cyblafb_pci_driver);
1449}
1450
1451module_init(cyblafb_init);
1452module_exit(cyblafb_exit);
1453
1454MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>");
1455MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core");
1456MODULE_LICENSE("GPL");
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 698ca9232e73..81a6d9f188cf 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -1061,6 +1061,11 @@ static int __devinit trident_pci_probe(struct pci_dev * dev, const struct pci_de
1061 1061
1062 chip_id = id->device; 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 /* If PCI id is 0x9660 then further detect chip type */ 1069 /* If PCI id is 0x9660 then further detect chip type */
1065 1070
1066 if (chip_id == TGUI9660) { 1071 if (chip_id == TGUI9660) {
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
new file mode 100644
index 000000000000..a9948232b131
--- /dev/null
+++ b/include/video/cyblafb.h
@@ -0,0 +1,171 @@
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