summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch2590
1 files changed, 2590 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch b/meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch
new file mode 100644
index 0000000000..711375114f
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-rp-2.6.23/uvesafb-0.1-rc3-2.6.22.patch
@@ -0,0 +1,2590 @@
1---
2 Documentation/fb/uvesafb.txt | 188 +++
3 drivers/video/Kconfig | 18
4 drivers/video/Makefile | 1
5 drivers/video/modedb.c | 28
6 drivers/video/uvesafb.c | 2058 +++++++++++++++++++++++++++++++++++++++++++
7 include/linux/connector.h | 7
8 include/video/Kbuild | 2
9 include/video/uvesafb.h | 193 ++++
10 8 files changed, 2479 insertions(+), 16 deletions(-)
11
12Index: linux-2.6.22/Documentation/fb/uvesafb.txt
13===================================================================
14--- /dev/null 1970-01-01 00:00:00.000000000 +0000
15+++ linux-2.6.22/Documentation/fb/uvesafb.txt 2007-08-28 21:56:34.000000000 +0100
16@@ -0,0 +1,188 @@
17+
18+uvesafb - A Generic Driver for VBE2+ compliant video cards
19+==========================================================
20+
21+1. Requirements
22+---------------
23+
24+uvesafb should work with any video card that has a Video BIOS compliant
25+with the VBE 2.0 standard.
26+
27+Unlike other drivers, uvesafb makes use of a userspace helper called
28+v86d. v86d is used to run the x86 Video BIOS code in a simulated and
29+controlled environment. This allows uvesafb to function on arches other
30+than x86. Check the v86d documentation for a list of currently supported
31+arches.
32+
33+v86d source code can be downloaded from the following website:
34+ http://dev.gentoo.org/~spock/projects/uvesafb
35+
36+Please refer to the v86d documentation for detailed configuration and
37+installation instructions.
38+
39+Note that the v86d userspace helper has to be available at all times in
40+order for uvesafb to work properly. If you want to use uvesafb during
41+early boot, you will have to include v86d into an initramfs image, and
42+either compile it into the kernel or use it as an initrd.
43+
44+2. Caveats and limitations
45+--------------------------
46+
47+uvesafb is a _generic_ driver which supports a wide variety of video
48+cards, but which is ultimately limited by the Video BIOS interface.
49+The most important limitations are:
50+
51+- Lack of any type of acceleration.
52+- A strict and limited set of supported video modes. Often the native
53+ or most optimal resolution/refresh rate for your setup will not work
54+ with uvesafb, simply because the Video BIOS doesn't support the
55+ video mode you want to use. This can be especially painful with
56+ widescreen panels, where native video modes don't have the 4:3 aspect
57+ ratio, which is what most BIOS-es are limited to.
58+- Adjusting the refresh rate is only possible with a VBE 3.0 compliant
59+ Video BIOS. Note that many nVidia Video BIOS-es claim to be VBE 3.0
60+ compliant, while they simply ignore any refresh rate settings.
61+
62+3. Configuration
63+----------------
64+
65+uvesafb can be compiled either as a module, or directly into the kernel.
66+In both cases it supports the same set of configuration options, which
67+are either given on the kernel command line or as module parameters, e.g.:
68+
69+ video=uvesafb:1024x768-32,mtrr:3,ywrap (compiled into the kernel)
70+
71+ # modprobe uvesafb mode=1024x768-32 mtrr=3 scroll=ywrap (module)
72+
73+Accepted options:
74+
75+ypan Enable display panning using the VESA protected mode
76+ interface. The visible screen is just a window of the
77+ video memory, console scrolling is done by changing the
78+ start of the window. Available on x86 only.
79+
80+ywrap Same as ypan, but assumes your gfx board can wrap-around
81+ the video memory (i.e. starts reading from top if it
82+ reaches the end of video memory). Faster than ypan.
83+ Available on x86 only.
84+
85+redraw Scroll by redrawing the affected part of the screen, this
86+ is the safe (and slow) default.
87+
88+(If you're using uvesafb as a module, the above three options are
89+ used a parameter of the scroll option, e.g. scroll=ypan.)
90+
91+vgapal Use the standard VGA registers for palette changes.
92+
93+pmipal Use the protected mode interface for palette changes.
94+ This is the default if the protected mode interface is
95+ available. Available on x86 only.
96+
97+mtrr:n Setup memory type range registers for the framebuffer
98+ where n:
99+ 0 - disabled (equivalent to nomtrr) (default)
100+ 1 - uncachable
101+ 2 - write-back
102+ 3 - write-combining
103+ 4 - write-through
104+
105+ If you see the following in dmesg, choose the type that matches
106+ the old one. In this example, use "mtrr:2".
107+...
108+mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
109+...
110+
111+nomtrr Do not use memory type range registers.
112+
113+vremap:n
114+ Remap 'n' MiB of video RAM. If 0 or not specified, remap memory
115+ according to video mode.
116+
117+vtotal:n
118+ If the video BIOS of your card incorrectly determines the total
119+ amount of video RAM, use this option to override the BIOS (in MiB).
120+
121+<mode> The mode you want to set, in the standard modedb format. Refer to
122+ modedb.txt for a detailed description. When uvesafb is compiled as
123+ a module, the mode string should be provided as a value of the
124+ 'mode' option.
125+
126+vbemode:x
127+ Force the use of VBE mode x. The mode will only be set if it's
128+ found in the VBE-provided list of supported modes.
129+ NOTE: The mode number 'x' should be specified in VESA mode number
130+ notation, not the Linux kernel one (eg. 257 instead of 769).
131+ HINT: If you use this option because normal <mode> parameter does
132+ not work for you and you use a X server, you'll probably want to
133+ set the 'nocrtc' option to ensure that the video mode is properly
134+ restored after console <-> X switches.
135+
136+nocrtc Do not use CRTC timings while setting the video mode. This option
137+ has any effect only if the Video BIOS is VBE 3.0 compliant. Use it
138+ if you have problems with modes set the standard way. Note that
139+ using this option implies that any refresh rate adjustments will
140+ be ignored and the refresh rate will stay at your BIOS default (60 Hz).
141+
142+noedid Do not try to fetch and use EDID-provided modes.
143+
144+noblank Disable hardware blanking.
145+
146+v86d:path
147+ Set path to the v86d executable. This option is only available as
148+ a module parameter, and not as a part of the video= string. If you
149+ need to use it and have uvesafb built into the kernel, use
150+ uvesafb.v86d="path".
151+
152+Additionally, the following parameters may be provided. They all override the
153+EDID-provided values and BIOS defaults. Refer to your monitor's specs to get
154+the correct values for maxhf, maxvf and maxclk for your hardware.
155+
156+maxhf:n Maximum horizontal frequency (in kHz).
157+maxvf:n Maximum vertical frequency (in Hz).
158+maxclk:n Maximum pixel clock (in MHz).
159+
160+4. The sysfs interface
161+----------------------
162+
163+uvesafb provides several sysfs nodes for configurable parameters and
164+additional information.
165+
166+Driver attributes:
167+
168+/sys/bus/platform/drivers/uvesafb
169+ - v86d (default: /sbin/v86d)
170+ Path to the v86d executable. v86d is started by uvesafb
171+ if an instance of the daemon isn't already running.
172+
173+Device attributes:
174+
175+/sys/bus/platform/drivers/uvesafb/uvesafb.0
176+ - nocrtc
177+ Use the default refresh rate (60 Hz) if set to 1.
178+
179+ - oem_product_name
180+ - oem_product_rev
181+ - oem_string
182+ - oem_vendor
183+ Information about the card and its maker.
184+
185+ - vbe_modes
186+ A list of video modes supported by the Video BIOS along with their
187+ VBE mode numbers in hex.
188+
189+ - vbe_version
190+ A BCD value indicating the implemented VBE standard.
191+
192+5. Miscellaneous
193+----------------
194+
195+Uvesafb will set a video mode with the default refresh rate and timings
196+from the Video BIOS if you set pixclock to 0 in fb_var_screeninfo.
197+
198+
199+--
200+ Michal Januszewski <spock@gentoo.org>
201+ Last updated: 2007-06-16
202+
203+ Documentation of the uvesafb options is loosely based on vesafb.txt.
204+
205Index: linux-2.6.22/drivers/video/Kconfig
206===================================================================
207--- linux-2.6.22.orig/drivers/video/Kconfig 2007-08-28 21:56:33.000000000 +0100
208+++ linux-2.6.22/drivers/video/Kconfig 2007-08-28 21:56:34.000000000 +0100
209@@ -592,6 +592,24 @@ config FB_TGA
210
211 Say Y if you have one of those.
212
213+config FB_UVESA
214+ tristate "Userspace VESA VGA graphics support"
215+ depends on FB && CONNECTOR
216+ select FB_CFB_FILLRECT
217+ select FB_CFB_COPYAREA
218+ select FB_CFB_IMAGEBLIT
219+ select FB_MODE_HELPERS
220+ help
221+ This is the frame buffer driver for generic VBE 2.0 compliant
222+ graphic cards. It can also take advantage of VBE 3.0 features,
223+ such as refresh rate adjustment.
224+
225+ This driver generally provides more features than vesafb but
226+ requires a userspace helper application called 'v86d'. See
227+ <file:Documentation/fb/uvesafb.txt> for more information.
228+
229+ If unsure, say N.
230+
231 config FB_VESA
232 bool "VESA VGA graphics support"
233 depends on (FB = y) && X86
234Index: linux-2.6.22/drivers/video/Makefile
235===================================================================
236--- linux-2.6.22.orig/drivers/video/Makefile 2007-08-28 21:56:33.000000000 +0100
237+++ linux-2.6.22/drivers/video/Makefile 2007-08-28 21:56:34.000000000 +0100
238@@ -116,6 +116,7 @@ obj-$(CONFIG_FB_XILINX) += xil
239 obj-$(CONFIG_FB_OMAP) += omap/
240
241 # Platform or fallback drivers go here
242+obj-$(CONFIG_FB_UVESA) += uvesafb.o
243 obj-$(CONFIG_FB_VESA) += vesafb.o
244 obj-$(CONFIG_FB_IMAC) += imacfb.o
245 obj-$(CONFIG_FB_VGA16) += vga16fb.o
246Index: linux-2.6.22/drivers/video/modedb.c
247===================================================================
248--- linux-2.6.22.orig/drivers/video/modedb.c 2007-08-28 21:54:13.000000000 +0100
249+++ linux-2.6.22/drivers/video/modedb.c 2007-08-28 21:56:34.000000000 +0100
250@@ -606,26 +606,29 @@ done:
251 DPRINTK("Trying specified video mode%s %ix%i\n",
252 refresh_specified ? "" : " (ignoring refresh rate)", xres, yres);
253
254- diff = refresh;
255+ if (!refresh_specified)
256+ diff = 0;
257+ else
258+ diff = refresh;
259+
260 best = -1;
261 for (i = 0; i < dbsize; i++) {
262- if (name_matches(db[i], name, namelen) ||
263- (res_specified && res_matches(db[i], xres, yres))) {
264- if(!fb_try_mode(var, info, &db[i], bpp)) {
265- if(!refresh_specified || db[i].refresh == refresh)
266- return 1;
267- else {
268- if(diff > abs(db[i].refresh - refresh)) {
269- diff = abs(db[i].refresh - refresh);
270- best = i;
271- }
272+ if ((name_matches(db[i], name, namelen) ||
273+ (res_specified && res_matches(db[i], xres, yres))) &&
274+ !fb_try_mode(var, info, &db[i], bpp)) {
275+ if (refresh_specified && db[i].refresh == refresh) {
276+ return 1;
277+ } else {
278+ if (diff < db[i].refresh) {
279+ diff = db[i].refresh;
280+ best = i;
281 }
282 }
283 }
284 }
285 if (best != -1) {
286 fb_try_mode(var, info, &db[best], bpp);
287- return 2;
288+ return (refresh_specified) ? 2 : 1;
289 }
290
291 diff = xres + yres;
292@@ -938,6 +941,7 @@ void fb_destroy_modelist(struct list_hea
293 kfree(pos);
294 }
295 }
296+EXPORT_SYMBOL_GPL(fb_destroy_modelist);
297
298 /**
299 * fb_videomode_to_modelist: convert mode array to mode list
300Index: linux-2.6.22/drivers/video/uvesafb.c
301===================================================================
302--- /dev/null 1970-01-01 00:00:00.000000000 +0000
303+++ linux-2.6.22/drivers/video/uvesafb.c 2007-08-28 21:56:34.000000000 +0100
304@@ -0,0 +1,2058 @@
305+/*
306+ * A framebuffer driver for VBE 2.0+ compliant video cards
307+ *
308+ * (c) 2007 Michal Januszewski <spock@gentoo.org>
309+ * Loosely based upon the vesafb driver.
310+ *
311+ */
312+#include <linux/init.h>
313+#include <linux/module.h>
314+#include <linux/moduleparam.h>
315+#include <linux/skbuff.h>
316+#include <linux/timer.h>
317+#include <linux/completion.h>
318+#include <linux/connector.h>
319+#include <linux/random.h>
320+#include <linux/platform_device.h>
321+#include <linux/limits.h>
322+#include <linux/fb.h>
323+#include <linux/io.h>
324+#include <linux/mutex.h>
325+#include <video/edid.h>
326+#include <video/vga.h>
327+#include <video/uvesafb.h>
328+#ifdef CONFIG_MTRR
329+#include <asm/mtrr.h>
330+#endif
331+#include "edid.h"
332+
333+static struct cb_id uvesafb_cn_id = {
334+ .idx = CN_IDX_V86D,
335+ .val = CN_VAL_V86D_UVESAFB
336+};
337+static char v86d_path[PATH_MAX] = "/sbin/v86d";
338+static char v86d_started; /* has v86d been started by uvesafb? */
339+
340+static struct fb_fix_screeninfo uvesafb_fix __devinitdata = {
341+ .id = "VESA VGA",
342+ .type = FB_TYPE_PACKED_PIXELS,
343+ .accel = FB_ACCEL_NONE,
344+ .visual = FB_VISUAL_TRUECOLOR,
345+};
346+
347+static int mtrr __devinitdata = 3; /* enable mtrr by default */
348+static int blank __devinitdata = 1; /* enable blanking by default */
349+static int ypan __devinitdata = 1; /* 0: scroll, 1: ypan, 2: ywrap */
350+static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */
351+static int nocrtc __devinitdata; /* ignore CRTC settings */
352+static int noedid __devinitdata; /* don't try DDC transfers */
353+static int vram_remap __devinitdata; /* set amt. of memory to be used */
354+static int vram_total __devinitdata; /* set total amount of memory */
355+static u16 maxclk __devinitdata; /* maximum pixel clock */
356+static u16 maxvf __devinitdata; /* maximum vertical frequency */
357+static u16 maxhf __devinitdata; /* maximum horizontal frequency */
358+static u16 vbemode __devinitdata; /* force use of a specific VBE mode */
359+static char *mode_option __devinitdata;
360+
361+static struct uvesafb_ktask *uvfb_tasks[UVESAFB_TASKS_MAX];
362+static DEFINE_MUTEX(uvfb_lock);
363+
364+/*
365+ * A handler for replies from userspace.
366+ *
367+ * Make sure each message passes consistency checks and if it does,
368+ * find the kernel part of the task struct, copy the registers and
369+ * the buffer contents and then complete the task.
370+ */
371+static void uvesafb_cn_callback(void *data)
372+{
373+ struct cn_msg *msg = data;
374+ struct uvesafb_task *utask;
375+ struct uvesafb_ktask *task;
376+
377+ if (msg->seq >= UVESAFB_TASKS_MAX)
378+ return;
379+
380+ mutex_lock(&uvfb_lock);
381+ task = uvfb_tasks[msg->seq];
382+
383+ if (!task || msg->ack != task->ack) {
384+ mutex_unlock(&uvfb_lock);
385+ return;
386+ }
387+
388+ utask = (struct uvesafb_task *)msg->data;
389+
390+ /* Sanity checks for the buffer length. */
391+ if (task->t.buf_len < utask->buf_len ||
392+ utask->buf_len > msg->len - sizeof(*utask)) {
393+ mutex_unlock(&uvfb_lock);
394+ return;
395+ }
396+
397+ uvfb_tasks[msg->seq] = NULL;
398+ mutex_unlock(&uvfb_lock);
399+
400+ memcpy(&task->t, utask, sizeof(*utask));
401+
402+ if (task->t.buf_len && task->buf)
403+ memcpy(task->buf, utask + 1, task->t.buf_len);
404+
405+ complete(task->done);
406+ return;
407+}
408+
409+static int uvesafb_helper_start(void)
410+{
411+ char *envp[] = {
412+ "HOME=/",
413+ "PATH=/sbin:/bin",
414+ NULL,
415+ };
416+
417+ char *argv[] = {
418+ v86d_path,
419+ NULL,
420+ };
421+
422+ return call_usermodehelper(v86d_path, argv, envp, 1);
423+}
424+
425+/*
426+ * Execute a uvesafb task.
427+ *
428+ * Returns 0 if the task is executed successfully.
429+ *
430+ * A message sent to the userspace consists of the uvesafb_task
431+ * struct and (optionally) a buffer. The uvesafb_task struct is
432+ * a simplified version of uvesafb_ktask (its kernel counterpart)
433+ * containing only the register values, flags and the length of
434+ * the buffer.
435+ *
436+ * Each message is assigned a sequence number (increased linearly)
437+ * and a random ack number. The sequence number is used as a key
438+ * for the uvfb_tasks array which holds pointers to uvesafb_ktask
439+ * structs for all requests.
440+ */
441+static int uvesafb_exec(struct uvesafb_ktask *task)
442+{
443+ static int seq;
444+ struct cn_msg *m;
445+ int err;
446+ int len = sizeof(task->t) + task->t.buf_len;
447+
448+ /*
449+ * Check whether the message isn't longer than the maximum
450+ * allowed by connector.
451+ */
452+ if (sizeof(*m) + len > CONNECTOR_MAX_MSG_SIZE) {
453+ printk(KERN_WARNING "uvesafb: message too long (%d), "
454+ "can't execute task\n", (int)(sizeof(*m) + len));
455+ return -E2BIG;
456+ }
457+
458+ m = kzalloc(sizeof(*m) + len, GFP_KERNEL);
459+ if (!m)
460+ return -ENOMEM;
461+
462+ init_completion(task->done);
463+
464+ memcpy(&m->id, &uvesafb_cn_id, sizeof(m->id));
465+ m->seq = seq;
466+ m->len = len;
467+ m->ack = random32();
468+
469+ /* uvesafb_task structure */
470+ memcpy(m + 1, &task->t, sizeof(task->t));
471+
472+ /* Buffer */
473+ memcpy((u8 *)(m + 1) + sizeof(task->t), task->buf, task->t.buf_len);
474+
475+ /*
476+ * Save the message ack number so that we can find the kernel
477+ * part of this task when a reply is received from userspace.
478+ */
479+ task->ack = m->ack;
480+
481+ mutex_lock(&uvfb_lock);
482+
483+ /* If all slots are taken -- bail out. */
484+ if (uvfb_tasks[seq]) {
485+ mutex_unlock(&uvfb_lock);
486+ return -EBUSY;
487+ }
488+
489+ /* Save a pointer to the kernel part of the task struct. */
490+ uvfb_tasks[seq] = task;
491+ mutex_unlock(&uvfb_lock);
492+
493+ err = cn_netlink_send(m, 0, gfp_any());
494+ if (err == -ESRCH) {
495+ /*
496+ * Try to start the userspace helper if sending
497+ * the request failed the first time.
498+ */
499+ err = uvesafb_helper_start();
500+ if (err) {
501+ printk(KERN_ERR "uvesafb: failed to execute %s\n",
502+ v86d_path);
503+ printk(KERN_ERR "uvesafb: make sure that the v86d "
504+ "helper is installed and executable\n");
505+ } else {
506+ v86d_started = 1;
507+ err = cn_netlink_send(m, 0, gfp_any());
508+ }
509+ }
510+ kfree(m);
511+
512+ if (!err && !(task->t.flags & TF_EXIT))
513+ err = !wait_for_completion_timeout(task->done,
514+ msecs_to_jiffies(UVESAFB_TIMEOUT));
515+
516+ mutex_lock(&uvfb_lock);
517+ uvfb_tasks[seq] = NULL;
518+ mutex_unlock(&uvfb_lock);
519+
520+ seq++;
521+ if (seq >= UVESAFB_TASKS_MAX)
522+ seq = 0;
523+
524+ return err;
525+}
526+
527+/*
528+ * Free a uvesafb_ktask struct.
529+ */
530+static void uvesafb_free(struct uvesafb_ktask *task)
531+{
532+ if (task) {
533+ if (task->done)
534+ kfree(task->done);
535+ kfree(task);
536+ }
537+}
538+
539+/*
540+ * Prepare a uvesafb_ktask struct to be used again.
541+ */
542+static void uvesafb_reset(struct uvesafb_ktask *task)
543+{
544+ struct completion *cpl = task->done;
545+
546+ memset(task, 0, sizeof(*task));
547+ task->done = cpl;
548+}
549+
550+/*
551+ * Allocate and prepare a uvesafb_ktask struct.
552+ */
553+static struct uvesafb_ktask *uvesafb_prep(void)
554+{
555+ struct uvesafb_ktask *task;
556+
557+ task = kzalloc(sizeof(*task), GFP_KERNEL);
558+ if (task) {
559+ task->done = kzalloc(sizeof(*task->done), GFP_KERNEL);
560+ if (!task->done) {
561+ kfree(task);
562+ task = NULL;
563+ }
564+ }
565+ return task;
566+}
567+
568+static void uvesafb_setup_var(struct fb_var_screeninfo *var,
569+ struct fb_info *info, struct vbe_mode_ib *mode)
570+{
571+ struct uvesafb_par *par = info->par;
572+
573+ var->vmode = FB_VMODE_NONINTERLACED;
574+ var->sync = FB_SYNC_VERT_HIGH_ACT;
575+
576+ var->xres = mode->x_res;
577+ var->yres = mode->y_res;
578+ var->xres_virtual = mode->x_res;
579+ var->yres_virtual = (par->ypan) ?
580+ info->fix.smem_len / mode->bytes_per_scan_line :
581+ mode->y_res;
582+ var->xoffset = 0;
583+ var->yoffset = 0;
584+ var->bits_per_pixel = mode->bits_per_pixel;
585+
586+ if (var->bits_per_pixel == 15)
587+ var->bits_per_pixel = 16;
588+
589+ if (var->bits_per_pixel > 8) {
590+ var->red.offset = mode->red_off;
591+ var->red.length = mode->red_len;
592+ var->green.offset = mode->green_off;
593+ var->green.length = mode->green_len;
594+ var->blue.offset = mode->blue_off;
595+ var->blue.length = mode->blue_len;
596+ var->transp.offset = mode->rsvd_off;
597+ var->transp.length = mode->rsvd_len;
598+ } else {
599+ var->red.offset = 0;
600+ var->green.offset = 0;
601+ var->blue.offset = 0;
602+ var->transp.offset = 0;
603+
604+ /*
605+ * We're assuming that we can switch the DAC to 8 bits. If
606+ * this proves to be incorrect, we'll update the fields
607+ * later in set_par().
608+ */
609+ if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC) {
610+ var->red.length = 8;
611+ var->green.length = 8;
612+ var->blue.length = 8;
613+ var->transp.length = 0;
614+ } else {
615+ var->red.length = 6;
616+ var->green.length = 6;
617+ var->blue.length = 6;
618+ var->transp.length = 0;
619+ }
620+ }
621+}
622+
623+static int uvesafb_vbe_find_mode(struct uvesafb_par *par,
624+ int xres, int yres, int depth, unsigned char flags)
625+{
626+ int i, match = -1, h = 0, d = 0x7fffffff;
627+
628+ for (i = 0; i < par->vbe_modes_cnt; i++) {
629+ h = abs(par->vbe_modes[i].x_res - xres) +
630+ abs(par->vbe_modes[i].y_res - yres) +
631+ abs(depth - par->vbe_modes[i].depth);
632+
633+ /*
634+ * We have an exact match in terms of resolution
635+ * and depth.
636+ */
637+ if (h == 0)
638+ return i;
639+
640+ if (h < d || (h == d && par->vbe_modes[i].depth > depth)) {
641+ d = h;
642+ match = i;
643+ }
644+ }
645+ i = 1;
646+
647+ if (flags & UVESAFB_EXACT_DEPTH &&
648+ par->vbe_modes[match].depth != depth)
649+ i = 0;
650+
651+ if (flags & UVESAFB_EXACT_RES && d > 24)
652+ i = 0;
653+
654+ if (i != 0)
655+ return match;
656+ else
657+ return -1;
658+}
659+
660+static u8 *uvesafb_vbe_state_save(struct uvesafb_par *par)
661+{
662+ struct uvesafb_ktask *task;
663+ u8 *state;
664+ int err;
665+
666+ if (!par->vbe_state_size)
667+ return NULL;
668+
669+ state = kmalloc(par->vbe_state_size, GFP_KERNEL);
670+ if (!state)
671+ return NULL;
672+
673+ task = uvesafb_prep();
674+ if (!task) {
675+ kfree(state);
676+ return NULL;
677+ }
678+
679+ task->t.regs.eax = 0x4f04;
680+ task->t.regs.ecx = 0x000f;
681+ task->t.regs.edx = 0x0001;
682+ task->t.flags = TF_BUF_RET | TF_BUF_ESBX;
683+ task->t.buf_len = par->vbe_state_size;
684+ task->buf = state;
685+ err = uvesafb_exec(task);
686+
687+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
688+ printk(KERN_WARNING "uvesafb: VBE get state call "
689+ "failed (eax=0x%x, err=%d)\n",
690+ task->t.regs.eax, err);
691+ kfree(state);
692+ state = NULL;
693+ }
694+
695+ uvesafb_free(task);
696+ return state;
697+}
698+
699+static void uvesafb_vbe_state_restore(struct uvesafb_par *par, u8 *state_buf)
700+{
701+ struct uvesafb_ktask *task;
702+ int err;
703+
704+ if (!state_buf)
705+ return;
706+
707+ task = uvesafb_prep();
708+ if (!task)
709+ return;
710+
711+ task->t.regs.eax = 0x4f04;
712+ task->t.regs.ecx = 0x000f;
713+ task->t.regs.edx = 0x0002;
714+ task->t.buf_len = par->vbe_state_size;
715+ task->t.flags = TF_BUF_ESBX;
716+ task->buf = state_buf;
717+
718+ err = uvesafb_exec(task);
719+ if (err || (task->t.regs.eax & 0xffff) != 0x004f)
720+ printk(KERN_WARNING "uvesafb: VBE state restore call "
721+ "failed (eax=0x%x, err=%d)\n",
722+ task->t.regs.eax, err);
723+
724+ uvesafb_free(task);
725+}
726+
727+static int __devinit uvesafb_vbe_getinfo(struct uvesafb_ktask *task,
728+ struct uvesafb_par *par)
729+{
730+ int err;
731+
732+ task->t.regs.eax = 0x4f00;
733+ task->t.flags = TF_VBEIB;
734+ task->t.buf_len = sizeof(struct vbe_ib);
735+ task->buf = &par->vbe_ib;
736+ strncpy(par->vbe_ib.vbe_signature, "VBE2", 4);
737+
738+ err = uvesafb_exec(task);
739+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
740+ printk(KERN_ERR "uvesafb: Getting VBE info block failed "
741+ "(eax=0x%x, err=%d)\n", (u32)task->t.regs.eax,
742+ err);
743+ return -EINVAL;
744+ }
745+
746+ if (par->vbe_ib.vbe_version < 0x0200) {
747+ printk(KERN_ERR "uvesafb: Sorry, pre-VBE 2.0 cards are "
748+ "not supported.\n");
749+ return -EINVAL;
750+ }
751+
752+ if (!par->vbe_ib.mode_list_ptr) {
753+ printk(KERN_ERR "uvesafb: Missing mode list!\n");
754+ return -EINVAL;
755+ }
756+
757+ printk(KERN_INFO "uvesafb: ");
758+
759+ /*
760+ * Convert string pointers and the mode list pointer into
761+ * usable addresses. Print informational messages about the
762+ * video adapter and its vendor.
763+ */
764+ if (par->vbe_ib.oem_vendor_name_ptr)
765+ printk("%s, ",
766+ ((char *)task->buf) + par->vbe_ib.oem_vendor_name_ptr);
767+
768+ if (par->vbe_ib.oem_product_name_ptr)
769+ printk("%s, ",
770+ ((char *)task->buf) + par->vbe_ib.oem_product_name_ptr);
771+
772+ if (par->vbe_ib.oem_product_rev_ptr)
773+ printk("%s, ",
774+ ((char *)task->buf) + par->vbe_ib.oem_product_rev_ptr);
775+
776+ if (par->vbe_ib.oem_string_ptr)
777+ printk("OEM: %s, ",
778+ ((char *)task->buf) + par->vbe_ib.oem_string_ptr);
779+
780+ printk("VBE v%d.%d\n", ((par->vbe_ib.vbe_version & 0xff00) >> 8),
781+ par->vbe_ib.vbe_version & 0xff);
782+
783+ return 0;
784+}
785+
786+static int __devinit uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
787+ struct uvesafb_par *par)
788+{
789+ int off = 0, err;
790+ u16 *mode;
791+
792+ par->vbe_modes_cnt = 0;
793+
794+ /* Count available modes. */
795+ mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
796+ while (*mode != 0xffff) {
797+ par->vbe_modes_cnt++;
798+ mode++;
799+ }
800+
801+ par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
802+ par->vbe_modes_cnt, GFP_KERNEL);
803+ if (!par->vbe_modes)
804+ return -ENOMEM;
805+
806+ /* Get info about all available modes. */
807+ mode = (u16 *) (((u8 *)&par->vbe_ib) + par->vbe_ib.mode_list_ptr);
808+ while (*mode != 0xffff) {
809+ struct vbe_mode_ib *mib;
810+
811+ uvesafb_reset(task);
812+ task->t.regs.eax = 0x4f01;
813+ task->t.regs.ecx = (u32) *mode;
814+ task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
815+ task->t.buf_len = sizeof(struct vbe_mode_ib);
816+ task->buf = par->vbe_modes + off;
817+
818+ err = uvesafb_exec(task);
819+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
820+ printk(KERN_ERR "uvesafb: Getting mode info block "
821+ "for mode 0x%x failed (eax=0x%x, err=%d)\n",
822+ *mode, (u32)task->t.regs.eax, err);
823+ return -EINVAL;
824+ }
825+
826+ mib = task->buf;
827+ mib->mode_id = *mode;
828+
829+ /*
830+ * We only want modes that are supported with the current
831+ * hardware configuration, color, graphics and that have
832+ * support for the LFB.
833+ */
834+ if ((mib->mode_attr & VBE_MODE_MASK) == VBE_MODE_MASK &&
835+ mib->bits_per_pixel >= 8)
836+ off++;
837+ else
838+ par->vbe_modes_cnt--;
839+
840+ mode++;
841+ mib->depth = mib->red_len + mib->green_len + mib->blue_len;
842+
843+ /*
844+ * Handle 8bpp modes and modes with broken color component
845+ * lengths.
846+ */
847+ if (mib->depth == 0 || (mib->depth == 24 &&
848+ mib->bits_per_pixel == 32))
849+ mib->depth = mib->bits_per_pixel;
850+ }
851+
852+ return 0;
853+}
854+
855+/*
856+ * The Protected Mode Interface is 32-bit x86 code, so we only run it on
857+ * x86 and not x86_64.
858+ */
859+#ifdef CONFIG_X86_32
860+static int __devinit uvesafb_vbe_getpmi(struct uvesafb_ktask *task,
861+ struct uvesafb_par *par)
862+{
863+ int i, err;
864+
865+ uvesafb_reset(task);
866+ task->t.regs.eax = 0x4f0a;
867+ task->t.regs.ebx = 0x0;
868+ err = uvesafb_exec(task);
869+
870+ if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) {
871+ par->pmi_setpal = par->ypan = 0;
872+ } else {
873+ par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4)
874+ + task->t.regs.edi);
875+ par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1];
876+ par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2];
877+ printk(KERN_INFO "uvesafb: protected mode interface info at "
878+ "%04x:%04x\n",
879+ (u16)task->t.regs.es, (u16)task->t.regs.edi);
880+ printk(KERN_INFO "uvesafb: pmi: set display start = %p, "
881+ "set palette = %p\n", par->pmi_start,
882+ par->pmi_pal);
883+
884+ if (par->pmi_base[3]) {
885+ printk(KERN_INFO "uvesafb: pmi: ports = ");
886+ for (i = par->pmi_base[3]/2;
887+ par->pmi_base[i] != 0xffff; i++)
888+ printk("%x ", par->pmi_base[i]);
889+ printk("\n");
890+
891+ if (par->pmi_base[i] != 0xffff) {
892+ printk(KERN_INFO "uvesafb: can't handle memory"
893+ " requests, pmi disabled\n");
894+ par->ypan = par->pmi_setpal = 0;
895+ }
896+ }
897+ }
898+ return 0;
899+}
900+#endif /* CONFIG_X86_32 */
901+
902+/*
903+ * Check whether a video mode is supported by the Video BIOS and is
904+ * compatible with the monitor limits.
905+ */
906+static int __devinit uvesafb_is_valid_mode(struct fb_videomode *mode,
907+ struct fb_info *info)
908+{
909+ if (info->monspecs.gtf) {
910+ fb_videomode_to_var(&info->var, mode);
911+ if (fb_validate_mode(&info->var, info))
912+ return 0;
913+ }
914+
915+ if (uvesafb_vbe_find_mode(info->par, mode->xres, mode->yres, 8,
916+ UVESAFB_EXACT_RES) == -1)
917+ return 0;
918+
919+ return 1;
920+}
921+
922+static int __devinit uvesafb_vbe_getedid(struct uvesafb_ktask *task,
923+ struct fb_info *info)
924+{
925+ struct uvesafb_par *par = info->par;
926+ int err = 0;
927+
928+ if (noedid || par->vbe_ib.vbe_version < 0x0300)
929+ return -EINVAL;
930+
931+ task->t.regs.eax = 0x4f15;
932+ task->t.regs.ebx = 0;
933+ task->t.regs.ecx = 0;
934+ task->t.buf_len = 0;
935+ task->t.flags = 0;
936+
937+ err = uvesafb_exec(task);
938+
939+ if ((task->t.regs.eax & 0xffff) != 0x004f || err)
940+ return -EINVAL;
941+
942+ if ((task->t.regs.ebx & 0x3) == 3) {
943+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports both "
944+ "DDC1 and DDC2 transfers\n");
945+ } else if ((task->t.regs.ebx & 0x3) == 2) {
946+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC2 "
947+ "transfers\n");
948+ } else if ((task->t.regs.ebx & 0x3) == 1) {
949+ printk(KERN_INFO "uvesafb: VBIOS/hardware supports DDC1 "
950+ "transfers\n");
951+ } else {
952+ printk(KERN_INFO "uvesafb: VBIOS/hardware doesn't support "
953+ "DDC transfers\n");
954+ return -EINVAL;
955+ }
956+
957+ task->t.regs.eax = 0x4f15;
958+ task->t.regs.ebx = 1;
959+ task->t.regs.ecx = task->t.regs.edx = 0;
960+ task->t.flags = TF_BUF_RET | TF_BUF_ESDI;
961+ task->t.buf_len = EDID_LENGTH;
962+ task->buf = kzalloc(EDID_LENGTH, GFP_KERNEL);
963+
964+ err = uvesafb_exec(task);
965+
966+ if ((task->t.regs.eax & 0xffff) == 0x004f && !err) {
967+ fb_edid_to_monspecs(task->buf, &info->monspecs);
968+
969+ if (info->monspecs.vfmax && info->monspecs.hfmax) {
970+ /*
971+ * If the maximum pixel clock wasn't specified in
972+ * the EDID block, set it to 300 MHz.
973+ */
974+ if (info->monspecs.dclkmax == 0)
975+ info->monspecs.dclkmax = 300 * 1000000;
976+ info->monspecs.gtf = 1;
977+ }
978+ } else {
979+ err = -EINVAL;
980+ }
981+
982+ kfree(task->buf);
983+ return err;
984+}
985+
986+static void __devinit uvesafb_vbe_getmonspecs(struct uvesafb_ktask *task,
987+ struct fb_info *info)
988+{
989+ struct uvesafb_par *par = info->par;
990+ int i;
991+
992+ memset(&info->monspecs, 0, sizeof(info->monspecs));
993+
994+ /*
995+ * If we don't get all necessary data from the EDID block,
996+ * mark it as incompatible with the GTF and set nocrtc so
997+ * that we always use the default BIOS refresh rate.
998+ */
999+ if (uvesafb_vbe_getedid(task, info)) {
1000+ info->monspecs.gtf = 0;
1001+ par->nocrtc = 1;
1002+ }
1003+
1004+ /* Kernel command line overrides. */
1005+ if (maxclk)
1006+ info->monspecs.dclkmax = maxclk * 1000000;
1007+ if (maxvf)
1008+ info->monspecs.vfmax = maxvf;
1009+ if (maxhf)
1010+ info->monspecs.hfmax = maxhf * 1000;
1011+
1012+ /*
1013+ * In case DDC transfers are not supported, the user can provide
1014+ * monitor limits manually. Lower limits are set to "safe" values.
1015+ */
1016+ if (info->monspecs.gtf == 0 && maxclk && maxvf && maxhf) {
1017+ info->monspecs.dclkmin = 0;
1018+ info->monspecs.vfmin = 60;
1019+ info->monspecs.hfmin = 29000;
1020+ info->monspecs.gtf = 1;
1021+ par->nocrtc = 0;
1022+ }
1023+
1024+ if (info->monspecs.gtf)
1025+ printk(KERN_INFO
1026+ "uvesafb: monitor limits: vf = %d Hz, hf = %d kHz, "
1027+ "clk = %d MHz\n", info->monspecs.vfmax,
1028+ (int)(info->monspecs.hfmax / 1000),
1029+ (int)(info->monspecs.dclkmax / 1000000));
1030+ else
1031+ printk(KERN_INFO "uvesafb: no monitor limits have been set, "
1032+ "default refresh rate will be used\n");
1033+
1034+ /* Add VBE modes to the modelist. */
1035+ for (i = 0; i < par->vbe_modes_cnt; i++) {
1036+ struct fb_var_screeninfo var;
1037+ struct vbe_mode_ib *mode;
1038+ struct fb_videomode vmode;
1039+
1040+ mode = &par->vbe_modes[i];
1041+ memset(&var, 0, sizeof(var));
1042+
1043+ var.xres = mode->x_res;
1044+ var.yres = mode->y_res;
1045+
1046+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, &var, info);
1047+ fb_var_to_videomode(&vmode, &var);
1048+ fb_add_videomode(&vmode, &info->modelist);
1049+ }
1050+
1051+ /* Add valid VESA modes to our modelist. */
1052+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
1053+ if (uvesafb_is_valid_mode((struct fb_videomode *)
1054+ &vesa_modes[i], info))
1055+ fb_add_videomode(&vesa_modes[i], &info->modelist);
1056+ }
1057+
1058+ for (i = 0; i < info->monspecs.modedb_len; i++) {
1059+ if (uvesafb_is_valid_mode(&info->monspecs.modedb[i], info))
1060+ fb_add_videomode(&info->monspecs.modedb[i],
1061+ &info->modelist);
1062+ }
1063+
1064+ return;
1065+}
1066+
1067+static void __devinit uvesafb_vbe_getstatesize(struct uvesafb_ktask *task,
1068+ struct uvesafb_par *par)
1069+{
1070+ int err;
1071+
1072+ uvesafb_reset(task);
1073+
1074+ /*
1075+ * Get the VBE state buffer size. We want all available
1076+ * hardware state data (CL = 0x0f).
1077+ */
1078+ task->t.regs.eax = 0x4f04;
1079+ task->t.regs.ecx = 0x000f;
1080+ task->t.regs.edx = 0x0000;
1081+ task->t.flags = 0;
1082+
1083+ err = uvesafb_exec(task);
1084+
1085+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
1086+ printk(KERN_WARNING "uvesafb: VBE state buffer size "
1087+ "cannot be determined (eax=0x%x, err=%d)\n",
1088+ task->t.regs.eax, err);
1089+ par->vbe_state_size = 0;
1090+ return;
1091+ }
1092+
1093+ par->vbe_state_size = 64 * (task->t.regs.ebx & 0xffff);
1094+}
1095+
1096+static int __devinit uvesafb_vbe_init(struct fb_info *info)
1097+{
1098+ struct uvesafb_ktask *task = NULL;
1099+ struct uvesafb_par *par = info->par;
1100+ int err;
1101+
1102+ task = uvesafb_prep();
1103+ if (!task)
1104+ return -ENOMEM;
1105+
1106+ err = uvesafb_vbe_getinfo(task, par);
1107+ if (err)
1108+ goto out;
1109+
1110+ err = uvesafb_vbe_getmodes(task, par);
1111+ if (err)
1112+ goto out;
1113+
1114+ par->nocrtc = nocrtc;
1115+#ifdef CONFIG_X86_32
1116+ par->pmi_setpal = pmi_setpal;
1117+ par->ypan = ypan;
1118+
1119+ if (par->pmi_setpal || par->ypan)
1120+ uvesafb_vbe_getpmi(task, par);
1121+#else
1122+ /* The protected mode interface is not available on non-x86. */
1123+ par->pmi_setpal = par->ypan = 0;
1124+#endif
1125+
1126+ INIT_LIST_HEAD(&info->modelist);
1127+ uvesafb_vbe_getmonspecs(task, info);
1128+ uvesafb_vbe_getstatesize(task, par);
1129+
1130+out: uvesafb_free(task);
1131+ return err;
1132+}
1133+
1134+static int __devinit uvesafb_vbe_init_mode(struct fb_info *info)
1135+{
1136+ struct list_head *pos;
1137+ struct fb_modelist *modelist;
1138+ struct fb_videomode *mode;
1139+ struct uvesafb_par *par = info->par;
1140+ int i, modeid;
1141+
1142+ /* Has the user requested a specific VESA mode? */
1143+ if (vbemode) {
1144+ for (i = 0; i < par->vbe_modes_cnt; i++) {
1145+ if (par->vbe_modes[i].mode_id == vbemode) {
1146+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
1147+ &info->var, info);
1148+ /*
1149+ * With pixclock set to 0, the default BIOS
1150+ * timings will be used in set_par().
1151+ */
1152+ info->var.pixclock = 0;
1153+ modeid = i;
1154+ goto gotmode;
1155+ }
1156+ }
1157+ printk(KERN_INFO "uvesafb: requested VBE mode 0x%x is "
1158+ "unavailable\n", vbemode);
1159+ vbemode = 0;
1160+ }
1161+
1162+ /* Count the modes in the modelist */
1163+ i = 0;
1164+ list_for_each(pos, &info->modelist)
1165+ i++;
1166+
1167+ /*
1168+ * Convert the modelist into a modedb so that we can use it with
1169+ * fb_find_mode().
1170+ */
1171+ mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
1172+ if (mode) {
1173+ i = 0;
1174+ list_for_each(pos, &info->modelist) {
1175+ modelist = list_entry(pos, struct fb_modelist, list);
1176+ mode[i] = modelist->mode;
1177+ i++;
1178+ }
1179+
1180+ if (!mode_option)
1181+ mode_option = UVESAFB_DEFAULT_MODE;
1182+
1183+ i = fb_find_mode(&info->var, info, mode_option, mode, i,
1184+ NULL, 8);
1185+
1186+ kfree(mode);
1187+ }
1188+
1189+ /* fb_find_mode() failed */
1190+ if (i == 0 || i >= 3) {
1191+ info->var.xres = 640;
1192+ info->var.yres = 480;
1193+ mode = (struct fb_videomode *)
1194+ fb_find_best_mode(&info->var, &info->modelist);
1195+
1196+ if (mode) {
1197+ fb_videomode_to_var(&info->var, mode);
1198+ } else {
1199+ modeid = par->vbe_modes[0].mode_id;
1200+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
1201+ &info->var, info);
1202+ goto gotmode;
1203+ }
1204+ }
1205+
1206+ /* Look for a matching VBE mode. */
1207+ modeid = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres,
1208+ info->var.bits_per_pixel, UVESAFB_EXACT_RES);
1209+
1210+ if (modeid == -1)
1211+ return -EINVAL;
1212+
1213+gotmode:
1214+ uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]);
1215+
1216+ /*
1217+ * If we are not VBE3.0+ compliant, we're done -- the BIOS will
1218+ * ignore our timings anyway.
1219+ */
1220+ if (par->vbe_ib.vbe_version < 0x0300 || par->nocrtc)
1221+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60,
1222+ &info->var, info);
1223+
1224+ return modeid;
1225+}
1226+
1227+static int uvesafb_setpalette(struct uvesafb_pal_entry *entries, int count,
1228+ int start, struct fb_info *info)
1229+{
1230+ struct uvesafb_ktask *task;
1231+ struct uvesafb_par *par = info->par;
1232+ int i = par->mode_idx;
1233+ int err = 0;
1234+
1235+ /*
1236+ * We support palette modifications for 8 bpp modes only, so
1237+ * there can never be more than 256 entries.
1238+ */
1239+ if (start + count > 256)
1240+ return -EINVAL;
1241+
1242+ /* Use VGA registers if mode is VGA-compatible. */
1243+ if (i >= 0 && i < par->vbe_modes_cnt &&
1244+ par->vbe_modes[i].mode_attr & VBE_MODE_VGACOMPAT) {
1245+ for (i = 0; i < count; i++) {
1246+ outb_p(start + i, dac_reg);
1247+ outb_p(entries[i].red, dac_val);
1248+ outb_p(entries[i].green, dac_val);
1249+ outb_p(entries[i].blue, dac_val);
1250+ }
1251+ }
1252+#ifdef CONFIG_X86_32
1253+ else if (par->pmi_setpal) {
1254+ __asm__ __volatile__(
1255+ "call *(%%esi)"
1256+ : /* no return value */
1257+ : "a" (0x4f09), /* EAX */
1258+ "b" (0), /* EBX */
1259+ "c" (count), /* ECX */
1260+ "d" (start), /* EDX */
1261+ "D" (entries), /* EDI */
1262+ "S" (&par->pmi_pal)); /* ESI */
1263+ }
1264+#endif
1265+ else {
1266+ task = uvesafb_prep();
1267+ if (!task)
1268+ return -ENOMEM;
1269+
1270+ task->t.regs.eax = 0x4f09;
1271+ task->t.regs.ebx = 0x0;
1272+ task->t.regs.ecx = count;
1273+ task->t.regs.edx = start;
1274+ task->t.flags = TF_BUF_ESDI;
1275+ task->t.buf_len = sizeof(struct uvesafb_pal_entry) * count;
1276+ task->buf = entries;
1277+
1278+ err = uvesafb_exec(task);
1279+ if ((task->t.regs.eax & 0xffff) != 0x004f)
1280+ err = 1;
1281+
1282+ uvesafb_free(task);
1283+ }
1284+ return err;
1285+}
1286+
1287+static int uvesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
1288+ unsigned blue, unsigned transp,
1289+ struct fb_info *info)
1290+{
1291+ struct uvesafb_pal_entry entry;
1292+ int shift = 16 - info->var.green.length;
1293+ int err = 0;
1294+
1295+ if (regno >= info->cmap.len)
1296+ return -EINVAL;
1297+
1298+ if (info->var.bits_per_pixel == 8) {
1299+ entry.red = red >> shift;
1300+ entry.green = green >> shift;
1301+ entry.blue = blue >> shift;
1302+ entry.pad = 0;
1303+
1304+ err = uvesafb_setpalette(&entry, 1, regno, info);
1305+ } else if (regno < 16) {
1306+ switch (info->var.bits_per_pixel) {
1307+ case 16:
1308+ if (info->var.red.offset == 10) {
1309+ /* 1:5:5:5 */
1310+ ((u32 *) (info->pseudo_palette))[regno] =
1311+ ((red & 0xf800) >> 1) |
1312+ ((green & 0xf800) >> 6) |
1313+ ((blue & 0xf800) >> 11);
1314+ } else {
1315+ /* 0:5:6:5 */
1316+ ((u32 *) (info->pseudo_palette))[regno] =
1317+ ((red & 0xf800) ) |
1318+ ((green & 0xfc00) >> 5) |
1319+ ((blue & 0xf800) >> 11);
1320+ }
1321+ break;
1322+
1323+ case 24:
1324+ case 32:
1325+ red >>= 8;
1326+ green >>= 8;
1327+ blue >>= 8;
1328+ ((u32 *)(info->pseudo_palette))[regno] =
1329+ (red << info->var.red.offset) |
1330+ (green << info->var.green.offset) |
1331+ (blue << info->var.blue.offset);
1332+ break;
1333+ }
1334+ }
1335+ return err;
1336+}
1337+
1338+static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
1339+{
1340+ struct uvesafb_pal_entry *entries;
1341+ int shift = 16 - info->var.green.length;
1342+ int i, err = 0;
1343+
1344+ if (info->var.bits_per_pixel == 8) {
1345+ if (cmap->start + cmap->len > info->cmap.start +
1346+ info->cmap.len || cmap->start < info->cmap.start)
1347+ return -EINVAL;
1348+
1349+ entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
1350+ if (!entries)
1351+ return -ENOMEM;
1352+
1353+ for (i = 0; i < cmap->len; i++) {
1354+ entries[i].red = cmap->red[i] >> shift;
1355+ entries[i].green = cmap->green[i] >> shift;
1356+ entries[i].blue = cmap->blue[i] >> shift;
1357+ entries[i].pad = 0;
1358+ }
1359+ err = uvesafb_setpalette(entries, cmap->len, cmap->start, info);
1360+ kfree(entries);
1361+ } else {
1362+ /*
1363+ * For modes with bpp > 8, we only set the pseudo palette in
1364+ * the fb_info struct. We rely on uvesafb_setcolreg to do all
1365+ * sanity checking.
1366+ */
1367+ for (i = 0; i < cmap->len; i++) {
1368+ err |= uvesafb_setcolreg(cmap->start + i, cmap->red[i],
1369+ cmap->green[i], cmap->blue[i],
1370+ 0, info);
1371+ }
1372+ }
1373+ return err;
1374+}
1375+
1376+static int uvesafb_pan_display(struct fb_var_screeninfo *var,
1377+ struct fb_info *info)
1378+{
1379+#ifdef CONFIG_X86_32
1380+ int offset;
1381+ struct uvesafb_par *par = info->par;
1382+
1383+ offset = (var->yoffset * info->fix.line_length + var->xoffset) / 4;
1384+
1385+ /*
1386+ * It turns out it's not the best idea to do panning via vm86,
1387+ * so we only allow it if we have a PMI.
1388+ */
1389+ if (par->pmi_start) {
1390+ __asm__ __volatile__(
1391+ "call *(%%edi)"
1392+ : /* no return value */
1393+ : "a" (0x4f07), /* EAX */
1394+ "b" (0), /* EBX */
1395+ "c" (offset), /* ECX */
1396+ "d" (offset >> 16), /* EDX */
1397+ "D" (&par->pmi_start)); /* EDI */
1398+ }
1399+#endif
1400+ return 0;
1401+}
1402+
1403+static int uvesafb_blank(int blank, struct fb_info *info)
1404+{
1405+ struct uvesafb_par *par = info->par;
1406+ struct uvesafb_ktask *task;
1407+ int err = 1;
1408+
1409+ if (par->vbe_ib.capabilities & VBE_CAP_VGACOMPAT) {
1410+ int loop = 10000;
1411+ u8 seq = 0, crtc17 = 0;
1412+
1413+ if (blank == FB_BLANK_POWERDOWN) {
1414+ seq = 0x20;
1415+ crtc17 = 0x00;
1416+ err = 0;
1417+ } else {
1418+ seq = 0x00;
1419+ crtc17 = 0x80;
1420+ err = (blank == FB_BLANK_UNBLANK) ? 0 : -EINVAL;
1421+ }
1422+
1423+ vga_wseq(NULL, 0x00, 0x01);
1424+ seq |= vga_rseq(NULL, 0x01) & ~0x20;
1425+ vga_wseq(NULL, 0x00, seq);
1426+
1427+ crtc17 |= vga_rcrt(NULL, 0x17) & ~0x80;
1428+ while (loop--);
1429+ vga_wcrt(NULL, 0x17, crtc17);
1430+ vga_wseq(NULL, 0x00, 0x03);
1431+ } else {
1432+ task = uvesafb_prep();
1433+ if (!task)
1434+ return -ENOMEM;
1435+
1436+ task->t.regs.eax = 0x4f10;
1437+ switch (blank) {
1438+ case FB_BLANK_UNBLANK:
1439+ task->t.regs.ebx = 0x0001;
1440+ break;
1441+ case FB_BLANK_NORMAL:
1442+ task->t.regs.ebx = 0x0101; /* standby */
1443+ break;
1444+ case FB_BLANK_POWERDOWN:
1445+ task->t.regs.ebx = 0x0401; /* powerdown */
1446+ break;
1447+ default:
1448+ goto out;
1449+ }
1450+
1451+ err = uvesafb_exec(task);
1452+ if (err || (task->t.regs.eax & 0xffff) != 0x004f)
1453+ err = 1;
1454+out: uvesafb_free(task);
1455+ }
1456+ return err;
1457+}
1458+
1459+static int uvesafb_open(struct fb_info *info, int user)
1460+{
1461+ struct uvesafb_par *par = info->par;
1462+ int cnt = atomic_read(&par->ref_count);
1463+
1464+ if (!cnt && par->vbe_state_size)
1465+ par->vbe_state_orig = uvesafb_vbe_state_save(par);
1466+
1467+ atomic_inc(&par->ref_count);
1468+ return 0;
1469+}
1470+
1471+static int uvesafb_release(struct fb_info *info, int user)
1472+{
1473+ struct uvesafb_ktask *task = NULL;
1474+ struct uvesafb_par *par = info->par;
1475+ int cnt = atomic_read(&par->ref_count);
1476+
1477+ if (!cnt)
1478+ return -EINVAL;
1479+
1480+ if (cnt != 1)
1481+ goto out;
1482+
1483+ task = uvesafb_prep();
1484+ if (!task)
1485+ goto out;
1486+
1487+ /* First, try to set the standard 80x25 text mode. */
1488+ task->t.regs.eax = 0x0003;
1489+ uvesafb_exec(task);
1490+
1491+ /*
1492+ * Now try to restore whatever hardware state we might have
1493+ * saved when the fb device was first opened.
1494+ */
1495+ uvesafb_vbe_state_restore(par, par->vbe_state_orig);
1496+out:
1497+ atomic_dec(&par->ref_count);
1498+ if (task)
1499+ uvesafb_free(task);
1500+ return 0;
1501+}
1502+
1503+static int uvesafb_set_par(struct fb_info *info)
1504+{
1505+ struct uvesafb_par *par = info->par;
1506+ struct uvesafb_ktask *task = NULL;
1507+ struct vbe_crtc_ib *crtc = NULL;
1508+ struct vbe_mode_ib *mode = NULL;
1509+ int i, err = 0, depth = info->var.bits_per_pixel;
1510+
1511+ if (depth > 8 && depth != 32)
1512+ depth = info->var.red.length + info->var.green.length +
1513+ info->var.blue.length;
1514+
1515+ i = uvesafb_vbe_find_mode(par, info->var.xres, info->var.yres, depth,
1516+ UVESAFB_EXACT_RES | UVESAFB_EXACT_DEPTH);
1517+ if (i >= 0)
1518+ mode = &par->vbe_modes[i];
1519+ else
1520+ return -EINVAL;
1521+
1522+ task = uvesafb_prep();
1523+ if (!task)
1524+ return -ENOMEM;
1525+setmode:
1526+ task->t.regs.eax = 0x4f02;
1527+ task->t.regs.ebx = mode->mode_id | 0x4000; /* use LFB */
1528+
1529+ if (par->vbe_ib.vbe_version >= 0x0300 && !par->nocrtc &&
1530+ info->var.pixclock != 0) {
1531+ task->t.regs.ebx |= 0x0800; /* use CRTC data */
1532+ task->t.flags = TF_BUF_ESDI;
1533+ crtc = kzalloc(sizeof(struct vbe_crtc_ib), GFP_KERNEL);
1534+ if (!crtc) {
1535+ err = -ENOMEM;
1536+ goto out;
1537+ }
1538+ crtc->horiz_start = info->var.xres + info->var.right_margin;
1539+ crtc->horiz_end = crtc->horiz_start + info->var.hsync_len;
1540+ crtc->horiz_total = crtc->horiz_end + info->var.left_margin;
1541+
1542+ crtc->vert_start = info->var.yres + info->var.lower_margin;
1543+ crtc->vert_end = crtc->vert_start + info->var.vsync_len;
1544+ crtc->vert_total = crtc->vert_end + info->var.upper_margin;
1545+
1546+ crtc->pixel_clock = PICOS2KHZ(info->var.pixclock) * 1000;
1547+ crtc->refresh_rate = (u16)(100 * (crtc->pixel_clock /
1548+ (crtc->vert_total * crtc->horiz_total)));
1549+
1550+ if (info->var.vmode & FB_VMODE_DOUBLE)
1551+ crtc->flags |= 0x1;
1552+ if (info->var.vmode & FB_VMODE_INTERLACED)
1553+ crtc->flags |= 0x2;
1554+ if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
1555+ crtc->flags |= 0x4;
1556+ if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
1557+ crtc->flags |= 0x8;
1558+ memcpy(&par->crtc, crtc, sizeof(*crtc));
1559+ } else {
1560+ memset(&par->crtc, 0, sizeof(*crtc));
1561+ }
1562+
1563+ task->t.buf_len = sizeof(struct vbe_crtc_ib);
1564+ task->buf = &par->crtc;
1565+
1566+ err = uvesafb_exec(task);
1567+ if (err || (task->t.regs.eax & 0xffff) != 0x004f) {
1568+ /*
1569+ * The mode switch might have failed because we tried to
1570+ * use our own timings. Try again with the default timings.
1571+ */
1572+ if (crtc != NULL) {
1573+ printk(KERN_WARNING "uvesafb: mode switch failed "
1574+ "(eax=0x%x, err=%d). Trying again with "
1575+ "default timings.\n", task->t.regs.eax, err);
1576+ uvesafb_reset(task);
1577+ kfree(crtc);
1578+ crtc = NULL;
1579+ info->var.pixclock = 0;
1580+ goto setmode;
1581+ } else {
1582+ printk(KERN_ERR "uvesafb: mode switch failed (eax="
1583+ "0x%x, err=%d)\n", task->t.regs.eax, err);
1584+ err = -EINVAL;
1585+ goto out;
1586+ }
1587+ }
1588+ par->mode_idx = i;
1589+
1590+ /* For 8bpp modes, always try to set the DAC to 8 bits. */
1591+ if (par->vbe_ib.capabilities & VBE_CAP_CAN_SWITCH_DAC &&
1592+ mode->bits_per_pixel <= 8) {
1593+ uvesafb_reset(task);
1594+ task->t.regs.eax = 0x4f08;
1595+ task->t.regs.ebx = 0x0800;
1596+
1597+ err = uvesafb_exec(task);
1598+ if (err || (task->t.regs.eax & 0xffff) != 0x004f ||
1599+ ((task->t.regs.ebx & 0xff00) >> 8) != 8) {
1600+ /*
1601+ * We've failed to set the DAC palette format -
1602+ * time to correct var.
1603+ */
1604+ info->var.red.length = 6;
1605+ info->var.green.length = 6;
1606+ info->var.blue.length = 6;
1607+ }
1608+ }
1609+
1610+ info->fix.visual = (info->var.bits_per_pixel == 8) ?
1611+ FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
1612+ info->fix.line_length = mode->bytes_per_scan_line;
1613+
1614+out: if (crtc != NULL)
1615+ kfree(crtc);
1616+ uvesafb_free(task);
1617+
1618+ return err;
1619+}
1620+
1621+static void uvesafb_check_limits(struct fb_var_screeninfo *var,
1622+ struct fb_info *info)
1623+{
1624+ const struct fb_videomode *mode;
1625+ struct uvesafb_par *par = info->par;
1626+
1627+ /*
1628+ * If pixclock is set to 0, then we're using default BIOS timings
1629+ * and thus don't have to perform any checks here.
1630+ */
1631+ if (!var->pixclock)
1632+ return;
1633+
1634+ if (par->vbe_ib.vbe_version < 0x0300) {
1635+ fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, var, info);
1636+ return;
1637+ }
1638+
1639+ if (!fb_validate_mode(var, info))
1640+ return;
1641+
1642+ mode = fb_find_best_mode(var, &info->modelist);
1643+ if (mode) {
1644+ if (mode->xres == var->xres && mode->yres == var->yres &&
1645+ !(mode->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE))) {
1646+ fb_videomode_to_var(var, mode);
1647+ return;
1648+ }
1649+ }
1650+
1651+ if (info->monspecs.gtf && !fb_get_mode(FB_MAXTIMINGS, 0, var, info))
1652+ return;
1653+ /* Use default refresh rate */
1654+ var->pixclock = 0;
1655+}
1656+
1657+static int uvesafb_check_var(struct fb_var_screeninfo *var,
1658+ struct fb_info *info)
1659+{
1660+ struct uvesafb_par *par = info->par;
1661+ struct vbe_mode_ib *mode = NULL;
1662+ int match = -1;
1663+ int depth = var->red.length + var->green.length + var->blue.length;
1664+
1665+ /*
1666+ * Various apps will use bits_per_pixel to set the color depth,
1667+ * which is theoretically incorrect, but which we'll try to handle
1668+ * here.
1669+ */
1670+ if (depth == 0 || abs(depth - var->bits_per_pixel) >= 8)
1671+ depth = var->bits_per_pixel;
1672+
1673+ match = uvesafb_vbe_find_mode(par, var->xres, var->yres, depth,
1674+ UVESAFB_EXACT_RES);
1675+ if (match == -1)
1676+ return -EINVAL;
1677+
1678+ mode = &par->vbe_modes[match];
1679+ uvesafb_setup_var(var, info, mode);
1680+
1681+ /*
1682+ * Check whether we have remapped enough memory for this mode.
1683+ * We might be called at an early stage, when we haven't remapped
1684+ * any memory yet, in which case we simply skip the check.
1685+ */
1686+ if (var->yres * mode->bytes_per_scan_line > info->fix.smem_len
1687+ && info->fix.smem_len)
1688+ return -EINVAL;
1689+
1690+ if ((var->vmode & FB_VMODE_DOUBLE) &&
1691+ !(par->vbe_modes[match].mode_attr & 0x100))
1692+ var->vmode &= ~FB_VMODE_DOUBLE;
1693+
1694+ if ((var->vmode & FB_VMODE_INTERLACED) &&
1695+ !(par->vbe_modes[match].mode_attr & 0x200))
1696+ var->vmode &= ~FB_VMODE_INTERLACED;
1697+
1698+ uvesafb_check_limits(var, info);
1699+
1700+ var->xres_virtual = var->xres;
1701+ var->yres_virtual = (par->ypan) ?
1702+ info->fix.smem_len / mode->bytes_per_scan_line :
1703+ var->yres;
1704+ return 0;
1705+}
1706+
1707+static void uvesafb_save_state(struct fb_info *info)
1708+{
1709+ struct uvesafb_par *par = info->par;
1710+
1711+ if (par->vbe_state_saved)
1712+ kfree(par->vbe_state_saved);
1713+
1714+ par->vbe_state_saved = uvesafb_vbe_state_save(par);
1715+}
1716+
1717+static void uvesafb_restore_state(struct fb_info *info)
1718+{
1719+ struct uvesafb_par *par = info->par;
1720+
1721+ uvesafb_vbe_state_restore(par, par->vbe_state_saved);
1722+}
1723+
1724+static struct fb_ops uvesafb_ops = {
1725+ .owner = THIS_MODULE,
1726+ .fb_open = uvesafb_open,
1727+ .fb_release = uvesafb_release,
1728+ .fb_setcolreg = uvesafb_setcolreg,
1729+ .fb_setcmap = uvesafb_setcmap,
1730+ .fb_pan_display = uvesafb_pan_display,
1731+ .fb_blank = uvesafb_blank,
1732+ .fb_fillrect = cfb_fillrect,
1733+ .fb_copyarea = cfb_copyarea,
1734+ .fb_imageblit = cfb_imageblit,
1735+ .fb_check_var = uvesafb_check_var,
1736+ .fb_set_par = uvesafb_set_par,
1737+ .fb_save_state = uvesafb_save_state,
1738+ .fb_restore_state = uvesafb_restore_state,
1739+};
1740+
1741+static void __devinit uvesafb_init_info(struct fb_info *info,
1742+ struct vbe_mode_ib *mode)
1743+{
1744+ unsigned int size_vmode;
1745+ unsigned int size_remap;
1746+ unsigned int size_total;
1747+ struct uvesafb_par *par = info->par;
1748+ int i, h;
1749+
1750+ info->pseudo_palette = ((u8 *)info->par + sizeof(struct uvesafb_par));
1751+ info->fix = uvesafb_fix;
1752+ info->fix.ypanstep = par->ypan ? 1 : 0;
1753+ info->fix.ywrapstep = (par->ypan > 1) ? 1 : 0;
1754+
1755+ /*
1756+ * If we were unable to get the state buffer size, disable
1757+ * functions for saving and restoring the hardware state.
1758+ */
1759+ if (par->vbe_state_size == 0) {
1760+ info->fbops->fb_save_state = NULL;
1761+ info->fbops->fb_restore_state = NULL;
1762+ }
1763+
1764+ /* Disable blanking if the user requested so. */
1765+ if (!blank)
1766+ info->fbops->fb_blank = NULL;
1767+
1768+ /*
1769+ * Find out how much IO memory is required for the mode with
1770+ * the highest resolution.
1771+ */
1772+ size_remap = 0;
1773+ for (i = 0; i < par->vbe_modes_cnt; i++) {
1774+ h = par->vbe_modes[i].bytes_per_scan_line *
1775+ par->vbe_modes[i].y_res;
1776+ if (h > size_remap)
1777+ size_remap = h;
1778+ }
1779+ size_remap *= 2;
1780+
1781+ /*
1782+ * size_vmode -- that is the amount of memory needed for the
1783+ * used video mode, i.e. the minimum amount of
1784+ * memory we need.
1785+ */
1786+ if (mode != NULL) {
1787+ size_vmode = info->var.yres * mode->bytes_per_scan_line;
1788+ } else {
1789+ size_vmode = info->var.yres * info->var.xres *
1790+ ((info->var.bits_per_pixel + 7) >> 3);
1791+ }
1792+
1793+ /*
1794+ * size_total -- all video memory we have. Used for mtrr
1795+ * entries, resource allocation and bounds
1796+ * checking.
1797+ */
1798+ size_total = par->vbe_ib.total_memory * 65536;
1799+ if (vram_total)
1800+ size_total = vram_total * 1024 * 1024;
1801+ if (size_total < size_vmode)
1802+ size_total = size_vmode;
1803+
1804+ /*
1805+ * size_remap -- the amount of video memory we are going to
1806+ * use for vesafb. With modern cards it is no
1807+ * option to simply use size_total as th
1808+ * wastes plenty of kernel address space.
1809+ */
1810+ if (vram_remap)
1811+ size_remap = vram_remap * 1024 * 1024;
1812+ if (size_remap < size_vmode)
1813+ size_remap = size_vmode;
1814+ if (size_remap > size_total)
1815+ size_remap = size_total;
1816+
1817+ info->fix.smem_len = size_remap;
1818+ info->fix.smem_start = mode->phys_base_ptr;
1819+
1820+ /*
1821+ * We have to set yres_virtual here because when setup_var() was
1822+ * called, smem_len wasn't defined yet.
1823+ */
1824+ info->var.yres_virtual = info->fix.smem_len /
1825+ mode->bytes_per_scan_line;
1826+
1827+ if (par->ypan && info->var.yres_virtual > info->var.yres) {
1828+ printk(KERN_INFO "uvesafb: scrolling: %s "
1829+ "using protected mode interface, "
1830+ "yres_virtual=%d\n",
1831+ (par->ypan > 1) ? "ywrap" : "ypan",
1832+ info->var.yres_virtual);
1833+ } else {
1834+ printk(KERN_INFO "uvesafb: scrolling: redraw\n");
1835+ info->var.yres_virtual = info->var.yres;
1836+ par->ypan = 0;
1837+ }
1838+
1839+ info->flags = FBINFO_FLAG_DEFAULT |
1840+ (par->ypan) ? FBINFO_HWACCEL_YPAN : 0;
1841+
1842+ if (!par->ypan)
1843+ info->fbops->fb_pan_display = NULL;
1844+}
1845+
1846+static void uvesafb_init_mtrr(struct fb_info *info)
1847+{
1848+#ifdef CONFIG_MTRR
1849+ if (mtrr && !(info->fix.smem_start & (PAGE_SIZE - 1))) {
1850+ int temp_size = info->fix.smem_len;
1851+ unsigned int type = 0;
1852+
1853+ switch (mtrr) {
1854+ case 1:
1855+ type = MTRR_TYPE_UNCACHABLE;
1856+ break;
1857+ case 2:
1858+ type = MTRR_TYPE_WRBACK;
1859+ break;
1860+ case 3:
1861+ type = MTRR_TYPE_WRCOMB;
1862+ break;
1863+ case 4:
1864+ type = MTRR_TYPE_WRTHROUGH;
1865+ break;
1866+ default:
1867+ type = 0;
1868+ break;
1869+ }
1870+
1871+ if (type) {
1872+ int rc;
1873+
1874+ /* Find the largest power-of-two */
1875+ while (temp_size & (temp_size - 1))
1876+ temp_size &= (temp_size - 1);
1877+
1878+ /* Try and find a power of two to add */
1879+ do {
1880+ rc = mtrr_add(info->fix.smem_start,
1881+ temp_size, type, 1);
1882+ temp_size >>= 1;
1883+ } while (temp_size >= PAGE_SIZE && rc == -EINVAL);
1884+ }
1885+ }
1886+#endif /* CONFIG_MTRR */
1887+}
1888+
1889+
1890+static ssize_t uvesafb_show_vbe_ver(struct device *dev,
1891+ struct device_attribute *attr, char *buf)
1892+{
1893+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1894+ struct uvesafb_par *par = info->par;
1895+
1896+ return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
1897+}
1898+
1899+static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
1900+
1901+static ssize_t uvesafb_show_vbe_modes(struct device *dev,
1902+ struct device_attribute *attr, char *buf)
1903+{
1904+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1905+ struct uvesafb_par *par = info->par;
1906+ int ret = 0, i;
1907+
1908+ for (i = 0; i < par->vbe_modes_cnt && ret < PAGE_SIZE; i++) {
1909+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
1910+ "%dx%d-%d, 0x%.4x\n",
1911+ par->vbe_modes[i].x_res, par->vbe_modes[i].y_res,
1912+ par->vbe_modes[i].depth, par->vbe_modes[i].mode_id);
1913+ }
1914+
1915+ return ret;
1916+}
1917+
1918+static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
1919+
1920+static ssize_t uvesafb_show_vendor(struct device *dev,
1921+ struct device_attribute *attr, char *buf)
1922+{
1923+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1924+ struct uvesafb_par *par = info->par;
1925+
1926+ if (par->vbe_ib.oem_vendor_name_ptr)
1927+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
1928+ (&par->vbe_ib) + par->vbe_ib.oem_vendor_name_ptr);
1929+ else
1930+ return 0;
1931+}
1932+
1933+static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
1934+
1935+static ssize_t uvesafb_show_product_name(struct device *dev,
1936+ struct device_attribute *attr, char *buf)
1937+{
1938+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1939+ struct uvesafb_par *par = info->par;
1940+
1941+ if (par->vbe_ib.oem_product_name_ptr)
1942+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
1943+ (&par->vbe_ib) + par->vbe_ib.oem_product_name_ptr);
1944+ else
1945+ return 0;
1946+}
1947+
1948+static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
1949+
1950+static ssize_t uvesafb_show_product_rev(struct device *dev,
1951+ struct device_attribute *attr, char *buf)
1952+{
1953+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1954+ struct uvesafb_par *par = info->par;
1955+
1956+ if (par->vbe_ib.oem_product_rev_ptr)
1957+ return snprintf(buf, PAGE_SIZE, "%s\n", (char *)
1958+ (&par->vbe_ib) + par->vbe_ib.oem_product_rev_ptr);
1959+ else
1960+ return 0;
1961+}
1962+
1963+static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
1964+
1965+static ssize_t uvesafb_show_oem_string(struct device *dev,
1966+ struct device_attribute *attr, char *buf)
1967+{
1968+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1969+ struct uvesafb_par *par = info->par;
1970+
1971+ if (par->vbe_ib.oem_string_ptr)
1972+ return snprintf(buf, PAGE_SIZE, "%s\n",
1973+ (char *)(&par->vbe_ib) + par->vbe_ib.oem_string_ptr);
1974+ else
1975+ return 0;
1976+}
1977+
1978+static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
1979+
1980+static ssize_t uvesafb_show_nocrtc(struct device *dev,
1981+ struct device_attribute *attr, char *buf)
1982+{
1983+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1984+ struct uvesafb_par *par = info->par;
1985+
1986+ return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
1987+}
1988+
1989+static ssize_t uvesafb_store_nocrtc(struct device *dev,
1990+ struct device_attribute *attr, const char *buf, size_t count)
1991+{
1992+ struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
1993+ struct uvesafb_par *par = info->par;
1994+
1995+ if (count > 0) {
1996+ if (buf[0] == '0')
1997+ par->nocrtc = 0;
1998+ else
1999+ par->nocrtc = 1;
2000+ }
2001+ return count;
2002+}
2003+
2004+static DEVICE_ATTR(nocrtc, S_IRUGO | S_IWUSR, uvesafb_show_nocrtc,
2005+ uvesafb_store_nocrtc);
2006+
2007+static struct attribute *uvesafb_dev_attrs[] = {
2008+ &dev_attr_vbe_version.attr,
2009+ &dev_attr_vbe_modes.attr,
2010+ &dev_attr_oem_vendor.attr,
2011+ &dev_attr_oem_product_name.attr,
2012+ &dev_attr_oem_product_rev.attr,
2013+ &dev_attr_oem_string.attr,
2014+ &dev_attr_nocrtc.attr,
2015+ NULL,
2016+};
2017+
2018+static struct attribute_group uvesafb_dev_attgrp = {
2019+ .name = NULL,
2020+ .attrs = uvesafb_dev_attrs,
2021+};
2022+
2023+static int __devinit uvesafb_probe(struct platform_device *dev)
2024+{
2025+ struct fb_info *info;
2026+ struct vbe_mode_ib *mode = NULL;
2027+ struct uvesafb_par *par;
2028+ int err = 0, i;
2029+
2030+ info = framebuffer_alloc(sizeof(*par) + sizeof(u32) * 256, &dev->dev);
2031+ if (!info)
2032+ return -ENOMEM;
2033+
2034+ par = info->par;
2035+
2036+ err = uvesafb_vbe_init(info);
2037+ if (err) {
2038+ printk(KERN_ERR "uvesafb: vbe_init() failed with %d\n", err);
2039+ goto out;
2040+ }
2041+
2042+ info->fbops = &uvesafb_ops;
2043+
2044+ i = uvesafb_vbe_init_mode(info);
2045+ if (i < 0) {
2046+ err = -EINVAL;
2047+ goto out;
2048+ } else {
2049+ mode = &par->vbe_modes[i];
2050+ }
2051+
2052+ if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
2053+ err = -ENXIO;
2054+ goto out;
2055+ }
2056+
2057+ uvesafb_init_info(info, mode);
2058+
2059+ if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
2060+ "uvesafb")) {
2061+ printk(KERN_ERR "uvesafb: cannot reserve video memory at "
2062+ "0x%lx\n", info->fix.smem_start);
2063+ err = -EIO;
2064+ goto out_mode;
2065+ }
2066+
2067+ info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
2068+
2069+ if (!info->screen_base) {
2070+ printk(KERN_ERR
2071+ "uvesafb: abort, cannot ioremap 0x%x bytes of video "
2072+ "memory at 0x%lx\n",
2073+ info->fix.smem_len, info->fix.smem_start);
2074+ err = -EIO;
2075+ goto out_mem;
2076+ }
2077+
2078+ if (!request_region(0x3c0, 32, "uvesafb")) {
2079+ printk(KERN_ERR "uvesafb: request region 0x3c0-0x3e0 failed\n");
2080+ err = -EIO;
2081+ goto out_unmap;
2082+ }
2083+
2084+ uvesafb_init_mtrr(info);
2085+ platform_set_drvdata(dev, info);
2086+
2087+ if (register_framebuffer(info) < 0) {
2088+ printk(KERN_ERR
2089+ "uvesafb: failed to register framebuffer device\n");
2090+ err = -EINVAL;
2091+ goto out_reg;
2092+ }
2093+
2094+ printk(KERN_INFO "uvesafb: framebuffer at 0x%lx, mapped to 0x%p, "
2095+ "using %dk, total %dk\n", info->fix.smem_start,
2096+ info->screen_base, info->fix.smem_len/1024,
2097+ par->vbe_ib.total_memory * 64);
2098+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
2099+ info->fix.id);
2100+
2101+ err = sysfs_create_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
2102+ if (err != 0)
2103+ printk(KERN_WARNING "fb%d: failed to register attributes\n",
2104+ info->node);
2105+
2106+ return 0;
2107+
2108+out_reg:
2109+ release_region(0x3c0, 32);
2110+out_unmap:
2111+ iounmap(info->screen_base);
2112+out_mem:
2113+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
2114+out_mode:
2115+ if (!list_empty(&info->modelist))
2116+ fb_destroy_modelist(&info->modelist);
2117+ fb_destroy_modedb(info->monspecs.modedb);
2118+ fb_dealloc_cmap(&info->cmap);
2119+out:
2120+ if (par->vbe_modes)
2121+ kfree(par->vbe_modes);
2122+
2123+ framebuffer_release(info);
2124+ return err;
2125+}
2126+
2127+static int uvesafb_remove(struct platform_device *dev)
2128+{
2129+ struct fb_info *info = platform_get_drvdata(dev);
2130+
2131+ if (info) {
2132+ struct uvesafb_par *par = info->par;
2133+
2134+ sysfs_remove_group(&dev->dev.kobj, &uvesafb_dev_attgrp);
2135+ unregister_framebuffer(info);
2136+ release_region(0x3c0, 32);
2137+ iounmap(info->screen_base);
2138+ release_mem_region(info->fix.smem_start, info->fix.smem_len);
2139+ fb_destroy_modedb(info->monspecs.modedb);
2140+ fb_dealloc_cmap(&info->cmap);
2141+
2142+ if (par) {
2143+ if (par->vbe_modes)
2144+ kfree(par->vbe_modes);
2145+ if (par->vbe_state_orig)
2146+ kfree(par->vbe_state_orig);
2147+ if (par->vbe_state_saved)
2148+ kfree(par->vbe_state_saved);
2149+ }
2150+
2151+ framebuffer_release(info);
2152+ }
2153+ return 0;
2154+}
2155+
2156+static struct platform_driver uvesafb_driver = {
2157+ .probe = uvesafb_probe,
2158+ .remove = uvesafb_remove,
2159+ .driver = {
2160+ .name = "uvesafb",
2161+ },
2162+};
2163+
2164+static struct platform_device *uvesafb_device;
2165+
2166+#ifndef MODULE
2167+static int __devinit uvesafb_setup(char *options)
2168+{
2169+ char *this_opt;
2170+
2171+ if (!options || !*options)
2172+ return 0;
2173+
2174+ while ((this_opt = strsep(&options, ",")) != NULL) {
2175+ if (!*this_opt) continue;
2176+
2177+ if (!strcmp(this_opt, "redraw"))
2178+ ypan = 0;
2179+ else if (!strcmp(this_opt, "ypan"))
2180+ ypan = 1;
2181+ else if (!strcmp(this_opt, "ywrap"))
2182+ ypan = 2;
2183+ else if (!strcmp(this_opt, "vgapal"))
2184+ pmi_setpal = 0;
2185+ else if (!strcmp(this_opt, "pmipal"))
2186+ pmi_setpal = 1;
2187+ else if (!strncmp(this_opt, "mtrr:", 5))
2188+ mtrr = simple_strtoul(this_opt+5, NULL, 0);
2189+ else if (!strcmp(this_opt, "nomtrr"))
2190+ mtrr = 0;
2191+ else if (!strcmp(this_opt, "nocrtc"))
2192+ nocrtc = 1;
2193+ else if (!strcmp(this_opt, "noedid"))
2194+ noedid = 1;
2195+ else if (!strcmp(this_opt, "noblank"))
2196+ blank = 0;
2197+ else if (!strncmp(this_opt, "vtotal:", 7))
2198+ vram_total = simple_strtoul(this_opt + 7, NULL, 0);
2199+ else if (!strncmp(this_opt, "vremap:", 7))
2200+ vram_remap = simple_strtoul(this_opt + 7, NULL, 0);
2201+ else if (!strncmp(this_opt, "maxhf:", 6))
2202+ maxhf = simple_strtoul(this_opt + 6, NULL, 0);
2203+ else if (!strncmp(this_opt, "maxvf:", 6))
2204+ maxvf = simple_strtoul(this_opt + 6, NULL, 0);
2205+ else if (!strncmp(this_opt, "maxclk:", 7))
2206+ maxclk = simple_strtoul(this_opt + 7, NULL, 0);
2207+ else if (!strncmp(this_opt, "vbemode:", 8))
2208+ vbemode = simple_strtoul(this_opt + 8, NULL, 0);
2209+ else if (this_opt[0] >= '0' && this_opt[0] <= '9') {
2210+ mode_option = this_opt;
2211+ } else {
2212+ printk(KERN_WARNING
2213+ "uvesafb: unrecognized option %s\n", this_opt);
2214+ }
2215+ }
2216+
2217+ return 0;
2218+}
2219+#endif /* !MODULE */
2220+
2221+static ssize_t show_v86d(struct device_driver *dev, char *buf)
2222+{
2223+ return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path);
2224+}
2225+
2226+static ssize_t store_v86d(struct device_driver *dev, const char *buf,
2227+ size_t count)
2228+{
2229+ strncpy(v86d_path, buf, PATH_MAX);
2230+ return count;
2231+}
2232+
2233+static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d);
2234+
2235+static int __devinit uvesafb_init(void)
2236+{
2237+ int err;
2238+
2239+#ifndef MODULE
2240+ char *option = NULL;
2241+
2242+ if (fb_get_options("uvesafb", &option))
2243+ return -ENODEV;
2244+ uvesafb_setup(option);
2245+#endif
2246+ err = cn_add_callback(&uvesafb_cn_id, "uvesafb", uvesafb_cn_callback);
2247+ if (err)
2248+ return err;
2249+
2250+ err = platform_driver_register(&uvesafb_driver);
2251+
2252+ if (!err) {
2253+ uvesafb_device = platform_device_alloc("uvesafb", 0);
2254+ if (uvesafb_device)
2255+ err = platform_device_add(uvesafb_device);
2256+ else
2257+ err = -ENOMEM;
2258+
2259+ if (err) {
2260+ platform_device_put(uvesafb_device);
2261+ platform_driver_unregister(&uvesafb_driver);
2262+ cn_del_callback(&uvesafb_cn_id);
2263+ return err;
2264+ }
2265+
2266+ err = driver_create_file(&uvesafb_driver.driver,
2267+ &driver_attr_v86d);
2268+ if (err) {
2269+ printk(KERN_WARNING "uvesafb: failed to register "
2270+ "attributes\n");
2271+ err = 0;
2272+ }
2273+ }
2274+ return err;
2275+}
2276+
2277+module_init(uvesafb_init);
2278+
2279+static void __devexit uvesafb_exit(void)
2280+{
2281+ struct uvesafb_ktask *task;
2282+
2283+ if (v86d_started) {
2284+ task = uvesafb_prep();
2285+ if (task) {
2286+ task->t.flags = TF_EXIT;
2287+ uvesafb_exec(task);
2288+ uvesafb_free(task);
2289+ }
2290+ }
2291+
2292+ cn_del_callback(&uvesafb_cn_id);
2293+ driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d);
2294+ platform_device_unregister(uvesafb_device);
2295+ platform_driver_unregister(&uvesafb_driver);
2296+}
2297+
2298+module_exit(uvesafb_exit);
2299+
2300+static inline int param_get_scroll(char *buffer, struct kernel_param *kp)
2301+{
2302+ return 0;
2303+}
2304+
2305+static inline int param_set_scroll(const char *val, struct kernel_param *kp)
2306+{
2307+ ypan = 0;
2308+
2309+ if (!strcmp(val, "redraw"))
2310+ ypan = 0;
2311+ else if (!strcmp(val, "ypan"))
2312+ ypan = 1;
2313+ else if (!strcmp(val, "ywrap"))
2314+ ypan = 2;
2315+
2316+ return 0;
2317+}
2318+
2319+#define param_check_scroll(name, p) __param_check(name, p, void);
2320+
2321+module_param_named(scroll, ypan, scroll, 0);
2322+MODULE_PARM_DESC(scroll,
2323+ "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'");
2324+module_param_named(vgapal, pmi_setpal, invbool, 0);
2325+MODULE_PARM_DESC(vgapal, "Set palette using VGA registers");
2326+module_param_named(pmipal, pmi_setpal, bool, 0);
2327+MODULE_PARM_DESC(pmipal, "Set palette using PMI calls");
2328+module_param(mtrr, uint, 0);
2329+MODULE_PARM_DESC(mtrr,
2330+ "Memory Type Range Registers setting. Use 0 to disable.");
2331+module_param(blank, bool, 0);
2332+MODULE_PARM_DESC(blank, "Enable hardware blanking");
2333+module_param(nocrtc, bool, 0);
2334+MODULE_PARM_DESC(nocrtc, "Ignore CRTC timings when setting modes");
2335+module_param(noedid, bool, 0);
2336+MODULE_PARM_DESC(noedid,
2337+ "Ignore EDID-provided monitor limits when setting modes");
2338+module_param(vram_remap, uint, 0);
2339+MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
2340+module_param(vram_total, uint, 0);
2341+MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]");
2342+module_param(maxclk, ushort, 0);
2343+MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
2344+module_param(maxhf, ushort, 0);
2345+MODULE_PARM_DESC(maxhf,
2346+ "Maximum horizontal frequency [kHz], overrides EDID data");
2347+module_param(maxvf, ushort, 0);
2348+MODULE_PARM_DESC(maxvf,
2349+ "Maximum vertical frequency [Hz], overrides EDID data");
2350+module_param_named(mode, mode_option, charp, 0);
2351+MODULE_PARM_DESC(mode,
2352+ "Specify initial video mode as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");
2353+module_param(vbemode, ushort, 0);
2354+MODULE_PARM_DESC(vbemode,
2355+ "VBE mode number to set, overrides the 'mode' option");
2356+module_param_string(v86d, v86d_path, PATH_MAX, 0660);
2357+MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper.");
2358+
2359+MODULE_LICENSE("GPL");
2360+MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>");
2361+MODULE_DESCRIPTION("Framebuffer driver for VBE2.0+ compliant graphics boards");
2362+
2363Index: linux-2.6.22/include/linux/connector.h
2364===================================================================
2365--- linux-2.6.22.orig/include/linux/connector.h 2007-08-28 21:54:13.000000000 +0100
2366+++ linux-2.6.22/include/linux/connector.h 2007-08-28 21:56:34.000000000 +0100
2367@@ -36,14 +36,15 @@
2368 #define CN_VAL_CIFS 0x1
2369 #define CN_W1_IDX 0x3 /* w1 communication */
2370 #define CN_W1_VAL 0x1
2371+#define CN_IDX_V86D 0x4
2372+#define CN_VAL_V86D_UVESAFB 0x1
2373
2374-
2375-#define CN_NETLINK_USERS 4
2376+#define CN_NETLINK_USERS 5
2377
2378 /*
2379 * Maximum connector's message size.
2380 */
2381-#define CONNECTOR_MAX_MSG_SIZE 1024
2382+#define CONNECTOR_MAX_MSG_SIZE 16384
2383
2384 /*
2385 * idx and val are unique identifiers which
2386Index: linux-2.6.22/include/video/Kbuild
2387===================================================================
2388--- linux-2.6.22.orig/include/video/Kbuild 2007-08-28 21:54:13.000000000 +0100
2389+++ linux-2.6.22/include/video/Kbuild 2007-08-28 21:56:34.000000000 +0100
2390@@ -1 +1 @@
2391-unifdef-y += sisfb.h
2392+unifdef-y += sisfb.h uvesafb.h
2393Index: linux-2.6.22/include/video/uvesafb.h
2394===================================================================
2395--- /dev/null 1970-01-01 00:00:00.000000000 +0000
2396+++ linux-2.6.22/include/video/uvesafb.h 2007-08-28 21:56:34.000000000 +0100
2397@@ -0,0 +1,193 @@
2398+#ifndef _UVESAFB_H
2399+#define _UVESAFB_H
2400+
2401+struct v86_regs {
2402+ __u32 ebx;
2403+ __u32 ecx;
2404+ __u32 edx;
2405+ __u32 esi;
2406+ __u32 edi;
2407+ __u32 ebp;
2408+ __u32 eax;
2409+ __u32 eip;
2410+ __u32 eflags;
2411+ __u32 esp;
2412+ __u16 cs;
2413+ __u16 ss;
2414+ __u16 es;
2415+ __u16 ds;
2416+ __u16 fs;
2417+ __u16 gs;
2418+};
2419+
2420+/* Task flags */
2421+#define TF_VBEIB 0x01
2422+#define TF_BUF_ESDI 0x02
2423+#define TF_BUF_ESBX 0x04
2424+#define TF_BUF_RET 0x08
2425+#define TF_EXIT 0x10
2426+
2427+struct uvesafb_task {
2428+ __u8 flags;
2429+ int buf_len;
2430+ struct v86_regs regs;
2431+};
2432+
2433+/* Constants for the capabilities field
2434+ * in vbe_ib */
2435+#define VBE_CAP_CAN_SWITCH_DAC 0x01
2436+#define VBE_CAP_VGACOMPAT 0x02
2437+
2438+/* The VBE Info Block */
2439+struct vbe_ib {
2440+ char vbe_signature[4];
2441+ __u16 vbe_version;
2442+ __u32 oem_string_ptr;
2443+ __u32 capabilities;
2444+ __u32 mode_list_ptr;
2445+ __u16 total_memory;
2446+ __u16 oem_software_rev;
2447+ __u32 oem_vendor_name_ptr;
2448+ __u32 oem_product_name_ptr;
2449+ __u32 oem_product_rev_ptr;
2450+ __u8 reserved[222];
2451+ char oem_data[256];
2452+ char misc_data[512];
2453+} __attribute__ ((packed));
2454+
2455+#ifdef __KERNEL__
2456+
2457+/* VBE CRTC Info Block */
2458+struct vbe_crtc_ib {
2459+ u16 horiz_total;
2460+ u16 horiz_start;
2461+ u16 horiz_end;
2462+ u16 vert_total;
2463+ u16 vert_start;
2464+ u16 vert_end;
2465+ u8 flags;
2466+ u32 pixel_clock;
2467+ u16 refresh_rate;
2468+ u8 reserved[40];
2469+} __attribute__ ((packed));
2470+
2471+#define VBE_MODE_VGACOMPAT 0x20
2472+#define VBE_MODE_COLOR 0x08
2473+#define VBE_MODE_SUPPORTEDHW 0x01
2474+#define VBE_MODE_GRAPHICS 0x10
2475+#define VBE_MODE_LFB 0x80
2476+
2477+#define VBE_MODE_MASK (VBE_MODE_COLOR | VBE_MODE_SUPPORTEDHW | \
2478+ VBE_MODE_GRAPHICS | VBE_MODE_LFB)
2479+
2480+/* VBE Mode Info Block */
2481+struct vbe_mode_ib {
2482+ /* for all VBE revisions */
2483+ u16 mode_attr;
2484+ u8 winA_attr;
2485+ u8 winB_attr;
2486+ u16 win_granularity;
2487+ u16 win_size;
2488+ u16 winA_seg;
2489+ u16 winB_seg;
2490+ u32 win_func_ptr;
2491+ u16 bytes_per_scan_line;
2492+
2493+ /* for VBE 1.2+ */
2494+ u16 x_res;
2495+ u16 y_res;
2496+ u8 x_char_size;
2497+ u8 y_char_size;
2498+ u8 planes;
2499+ u8 bits_per_pixel;
2500+ u8 banks;
2501+ u8 memory_model;
2502+ u8 bank_size;
2503+ u8 image_pages;
2504+ u8 reserved1;
2505+
2506+ /* Direct color fields for direct/6 and YUV/7 memory models. */
2507+ /* Offsets are bit positions of lsb in the mask. */
2508+ u8 red_len;
2509+ u8 red_off;
2510+ u8 green_len;
2511+ u8 green_off;
2512+ u8 blue_len;
2513+ u8 blue_off;
2514+ u8 rsvd_len;
2515+ u8 rsvd_off;
2516+ u8 direct_color_info; /* direct color mode attributes */
2517+
2518+ /* for VBE 2.0+ */
2519+ u32 phys_base_ptr;
2520+ u8 reserved2[6];
2521+
2522+ /* for VBE 3.0+ */
2523+ u16 lin_bytes_per_scan_line;
2524+ u8 bnk_image_pages;
2525+ u8 lin_image_pages;
2526+ u8 lin_red_len;
2527+ u8 lin_red_off;
2528+ u8 lin_green_len;
2529+ u8 lin_green_off;
2530+ u8 lin_blue_len;
2531+ u8 lin_blue_off;
2532+ u8 lin_rsvd_len;
2533+ u8 lin_rsvd_off;
2534+ u32 max_pixel_clock;
2535+ u16 mode_id;
2536+ u8 depth;
2537+} __attribute__ ((packed));
2538+
2539+#define UVESAFB_DEFAULT_MODE "640x480-16"
2540+
2541+/* How long to wait for a reply from userspace [ms] */
2542+#define UVESAFB_TIMEOUT 5000
2543+
2544+/* Max number of concurrent tasks */
2545+#define UVESAFB_TASKS_MAX 16
2546+
2547+#define dac_reg (0x3c8)
2548+#define dac_val (0x3c9)
2549+
2550+struct uvesafb_pal_entry {
2551+ u_char blue, green, red, pad;
2552+} __attribute__ ((packed));
2553+
2554+struct uvesafb_ktask {
2555+ struct uvesafb_task t;
2556+ void *buf;
2557+ struct completion *done;
2558+ u32 ack;
2559+};
2560+
2561+static int uvesafb_exec(struct uvesafb_ktask *tsk);
2562+
2563+#define UVESAFB_EXACT_RES 1
2564+#define UVESAFB_EXACT_DEPTH 2
2565+
2566+struct uvesafb_par {
2567+ struct vbe_ib vbe_ib; /* VBE Info Block */
2568+ struct vbe_mode_ib *vbe_modes; /* list of supported VBE modes */
2569+ int vbe_modes_cnt;
2570+
2571+ u8 nocrtc;
2572+ u8 ypan; /* 0 - nothing, 1 - ypan, 2 - ywrap */
2573+ u8 pmi_setpal; /* PMI for palette changes */
2574+ u16 *pmi_base; /* protected mode interface location */
2575+ void *pmi_start;
2576+ void *pmi_pal;
2577+ u8 *vbe_state_orig; /*
2578+ * original hardware state, before the
2579+ * driver was loaded
2580+ */
2581+ u8 *vbe_state_saved; /* state saved by fb_save_state */
2582+ int vbe_state_size;
2583+ atomic_t ref_count;
2584+
2585+ int mode_idx;
2586+ struct vbe_crtc_ib crtc;
2587+};
2588+
2589+#endif /* __KERNEL__ */
2590+#endif /* _UVESAFB_H */