diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2006-01-09 23:53:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-10 11:01:49 -0500 |
commit | d911233fe6632981086942a6b66e7ae5dabaaadc (patch) | |
tree | 6608709b71f04173beb0263c76a66bc1b7b2d4a9 | |
parent | c549dc6422e4b720fed6702d70fddd8cee0f5c9a (diff) |
[PATCH] skeletonfb: Documentation update
Update skeletonfb so it reflects recent (and somewhat old) changes of the
framebuffer layer.
Signed-off-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-- | drivers/video/skeletonfb.c | 482 |
1 files changed, 383 insertions, 99 deletions
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index a01e7ecc15ed..9b707771d757 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -115,7 +115,8 @@ static struct fb_fix_screeninfo xxxfb_fix __initdata = { | |||
115 | /* | 115 | /* |
116 | * If your driver supports multiple boards or it supports multiple | 116 | * If your driver supports multiple boards or it supports multiple |
117 | * framebuffers, you should make these arrays, or allocate them | 117 | * framebuffers, you should make these arrays, or allocate them |
118 | * dynamically (using kmalloc()). | 118 | * dynamically using framebuffer_alloc() and free them with |
119 | * framebuffer_release(). | ||
119 | */ | 120 | */ |
120 | static struct fb_info info; | 121 | static struct fb_info info; |
121 | 122 | ||
@@ -179,18 +180,31 @@ static int xxxfb_release(const struct fb_info *info, int user) | |||
179 | * intent to only test a mode and not actually set it. The stuff in | 180 | * intent to only test a mode and not actually set it. The stuff in |
180 | * modedb.c is a example of this. If the var passed in is slightly | 181 | * modedb.c is a example of this. If the var passed in is slightly |
181 | * off by what the hardware can support then we alter the var PASSED in | 182 | * off by what the hardware can support then we alter the var PASSED in |
182 | * to what we can do. If the hardware doesn't support mode change | 183 | * to what we can do. |
183 | * a -EINVAL will be returned by the upper layers. You don't need to | 184 | * |
184 | * implement this function then. If you hardware doesn't support | 185 | * For values that are off, this function must round them _up_ to the |
185 | * changing the resolution then this function is not needed. In this | 186 | * next value that is supported by the hardware. If the value is |
186 | * case the driver woudl just provide a var that represents the static | 187 | * greater than the highest value supported by the hardware, then this |
187 | * state the screen is in. | 188 | * function must return -EINVAL. |
189 | * | ||
190 | * Exception to the above rule: Some drivers have a fixed mode, ie, | ||
191 | * the hardware is already set at boot up, and cannot be changed. In | ||
192 | * this case, it is more acceptable that this function just return | ||
193 | * a copy of the currently working var (info->var). Better is to not | ||
194 | * implement this function, as the upper layer will do the copying | ||
195 | * of the current var for you. | ||
196 | * | ||
197 | * Note: This is the only function where the contents of var can be | ||
198 | * freely adjusted after the driver has been registered. If you find | ||
199 | * that you have code outside of this function that alters the content | ||
200 | * of var, then you are doing something wrong. Note also that the | ||
201 | * contents of info->var must be left untouched at all times after | ||
202 | * driver registration. | ||
188 | * | 203 | * |
189 | * Returns negative errno on error, or zero on success. | 204 | * Returns negative errno on error, or zero on success. |
190 | */ | 205 | */ |
191 | static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 206 | static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
192 | { | 207 | { |
193 | const struct xxx_par *par = (const struct xxx_par *) info->par; | ||
194 | /* ... */ | 208 | /* ... */ |
195 | return 0; | 209 | return 0; |
196 | } | 210 | } |
@@ -204,14 +218,39 @@ static int xxxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
204 | * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in | 218 | * fb_fix_screeninfo stored in fb_info. It doesn't not alter var in |
205 | * fb_info since we are using that data. This means we depend on the | 219 | * fb_info since we are using that data. This means we depend on the |
206 | * data in var inside fb_info to be supported by the hardware. | 220 | * data in var inside fb_info to be supported by the hardware. |
207 | * xxxfb_check_var is always called before xxxfb_set_par to ensure this. | 221 | * |
222 | * This function is also used to recover/restore the hardware to a | ||
223 | * known working state. | ||
224 | * | ||
225 | * xxxfb_check_var is always called before xxxfb_set_par to ensure that | ||
226 | * the contents of var is always valid. | ||
227 | * | ||
208 | * Again if you can't change the resolution you don't need this function. | 228 | * Again if you can't change the resolution you don't need this function. |
209 | * | 229 | * |
230 | * However, even if your hardware does not support mode changing, | ||
231 | * a set_par might be needed to at least initialize the hardware to | ||
232 | * a known working state, especially if it came back from another | ||
233 | * process that also modifies the same hardware, such as X. | ||
234 | * | ||
235 | * If this is the case, a combination such as the following should work: | ||
236 | * | ||
237 | * static int xxxfb_check_var(struct fb_var_screeninfo *var, | ||
238 | * struct fb_info *info) | ||
239 | * { | ||
240 | * *var = info->var; | ||
241 | * return 0; | ||
242 | * } | ||
243 | * | ||
244 | * static int xxxfb_set_par(struct fb_info *info) | ||
245 | * { | ||
246 | * init your hardware here | ||
247 | * } | ||
248 | * | ||
210 | * Returns negative errno on error, or zero on success. | 249 | * Returns negative errno on error, or zero on success. |
211 | */ | 250 | */ |
212 | static int xxxfb_set_par(struct fb_info *info) | 251 | static int xxxfb_set_par(struct fb_info *info) |
213 | { | 252 | { |
214 | struct xxx_par *par = (struct xxx_par *) info->par; | 253 | struct xxx_par *par = info->par; |
215 | /* ... */ | 254 | /* ... */ |
216 | return 0; | 255 | return 0; |
217 | } | 256 | } |
@@ -258,70 +297,110 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
258 | * var->{color}.offset contains start of bitfield | 297 | * var->{color}.offset contains start of bitfield |
259 | * var->{color}.length contains length of bitfield | 298 | * var->{color}.length contains length of bitfield |
260 | * {hardwarespecific} contains width of DAC | 299 | * {hardwarespecific} contains width of DAC |
261 | * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) | 300 | * pseudo_palette[X] is programmed to (X << red.offset) | |
301 | * (X << green.offset) | | ||
302 | * (X << blue.offset) | ||
262 | * RAMDAC[X] is programmed to (red, green, blue) | 303 | * RAMDAC[X] is programmed to (red, green, blue) |
304 | * color depth = SUM(var->{color}.length) | ||
263 | * | 305 | * |
264 | * Pseudocolor: | 306 | * Pseudocolor: |
265 | * uses offset = 0 && length = DAC register width. | ||
266 | * var->{color}.offset is 0 | 307 | * var->{color}.offset is 0 |
267 | * var->{color}.length contains widht of DAC | 308 | * var->{color}.length contains width of DAC or the number of unique |
268 | * cmap is not used | 309 | * colors available (color depth) |
269 | * DAC[X] is programmed to (red, green, blue) | 310 | * pseudo_palette is not used |
311 | * RAMDAC[X] is programmed to (red, green, blue) | ||
312 | * color depth = var->{color}.length | ||
313 | * | ||
314 | * Static pseudocolor: | ||
315 | * same as Pseudocolor, but the RAMDAC is not programmed (read-only) | ||
316 | * | ||
317 | * Mono01/Mono10: | ||
318 | * Has only 2 values, black on white or white on black (fg on bg), | ||
319 | * var->{color}.offset is 0 | ||
320 | * white = (1 << var->{color}.length) - 1, black = 0 | ||
321 | * pseudo_palette is not used | ||
322 | * RAMDAC does not exist | ||
323 | * color depth is always 2 | ||
324 | * | ||
270 | * Truecolor: | 325 | * Truecolor: |
271 | * does not use RAMDAC (usually has 3 of them). | 326 | * does not use RAMDAC (usually has 3 of them). |
272 | * var->{color}.offset contains start of bitfield | 327 | * var->{color}.offset contains start of bitfield |
273 | * var->{color}.length contains length of bitfield | 328 | * var->{color}.length contains length of bitfield |
274 | * cmap is programmed to (red << red.offset) | (green << green.offset) | | 329 | * pseudo_palette is programmed to (red << red.offset) | |
275 | * (blue << blue.offset) | (transp << transp.offset) | 330 | * (green << green.offset) | |
331 | * (blue << blue.offset) | | ||
332 | * (transp << transp.offset) | ||
276 | * RAMDAC does not exist | 333 | * RAMDAC does not exist |
334 | * color depth = SUM(var->{color}.length}) | ||
335 | * | ||
336 | * The color depth is used by fbcon for choosing the logo and also | ||
337 | * for color palette transformation if color depth < 4 | ||
338 | * | ||
339 | * As can be seen from the above, the field bits_per_pixel is _NOT_ | ||
340 | * a criteria for describing the color visual. | ||
341 | * | ||
342 | * A common mistake is assuming that bits_per_pixel <= 8 is pseudocolor, | ||
343 | * and higher than that, true/directcolor. This is incorrect, one needs | ||
344 | * to look at the fix->visual. | ||
345 | * | ||
346 | * Another common mistake is using bits_per_pixel to calculate the color | ||
347 | * depth. The bits_per_pixel field does not directly translate to color | ||
348 | * depth. You have to compute for the color depth (using the color | ||
349 | * bitfields) and fix->visual as seen above. | ||
350 | */ | ||
351 | |||
352 | /* | ||
353 | * This is the point where the color is converted to something that | ||
354 | * is acceptable by the hardware. | ||
277 | */ | 355 | */ |
278 | #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) | 356 | #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) |
279 | switch (info->fix.visual) { | 357 | red = CNVT_TOHW(red, info->var.red.length); |
280 | case FB_VISUAL_TRUECOLOR: | 358 | green = CNVT_TOHW(green, info->var.green.length); |
281 | case FB_VISUAL_PSEUDOCOLOR: | 359 | blue = CNVT_TOHW(blue, info->var.blue.length); |
282 | red = CNVT_TOHW(red, info->var.red.length); | 360 | transp = CNVT_TOHW(transp, info->var.transp.length); |
283 | green = CNVT_TOHW(green, info->var.green.length); | ||
284 | blue = CNVT_TOHW(blue, info->var.blue.length); | ||
285 | transp = CNVT_TOHW(transp, info->var.transp.length); | ||
286 | break; | ||
287 | case FB_VISUAL_DIRECTCOLOR: | ||
288 | /* example here assumes 8 bit DAC. Might be different | ||
289 | * for your hardware */ | ||
290 | red = CNVT_TOHW(red, 8); | ||
291 | green = CNVT_TOHW(green, 8); | ||
292 | blue = CNVT_TOHW(blue, 8); | ||
293 | /* hey, there is bug in transp handling... */ | ||
294 | transp = CNVT_TOHW(transp, 8); | ||
295 | break; | ||
296 | } | ||
297 | #undef CNVT_TOHW | 361 | #undef CNVT_TOHW |
298 | /* Truecolor has hardware independent palette */ | 362 | /* |
299 | if (info->fix.visual == FB_VISUAL_TRUECOLOR) { | 363 | * This is the point where the function feeds the color to the hardware |
300 | u32 v; | 364 | * palette after converting the colors to something acceptable by |
301 | 365 | * the hardware. Note, only FB_VISUAL_DIRECTCOLOR and | |
302 | if (regno >= 16) | 366 | * FB_VISUAL_PSEUDOCOLOR visuals need to write to the hardware palette. |
303 | return -EINVAL; | 367 | * If you have code that writes to the hardware CLUT, and it's not |
304 | 368 | * any of the above visuals, then you are doing something wrong. | |
305 | v = (red << info->var.red.offset) | | 369 | */ |
306 | (green << info->var.green.offset) | | 370 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR || |
307 | (blue << info->var.blue.offset) | | 371 | info->fix.visual == FB_VISUAL_TRUECOLOR) |
308 | (transp << info->var.transp.offset); | 372 | write_{red|green|blue|transp}_to_clut(); |
309 | 373 | ||
310 | switch (info->var.bits_per_pixel) { | 374 | /* This is the point were you need to fill up the contents of |
311 | case 8: | 375 | * info->pseudo_palette. This structure is used _only_ by fbcon, thus |
312 | /* Yes some hand held devices have this. */ | 376 | * it only contains 16 entries to match the number of colors supported |
313 | ((u8*)(info->pseudo_palette))[regno] = v; | 377 | * by the console. The pseudo_palette is used only if the visual is |
314 | break; | 378 | * in directcolor or truecolor mode. With other visuals, the |
315 | case 16: | 379 | * pseudo_palette is not used. (This might change in the future.) |
316 | ((u16*)(info->pseudo_palette))[regno] = v; | 380 | * |
317 | break; | 381 | * The contents of the pseudo_palette is in raw pixel format. Ie, each |
318 | case 24: | 382 | * entry can be written directly to the framebuffer without any conversion. |
319 | case 32: | 383 | * The pseudo_palette is (void *). However, if using the generic |
320 | ((u32*)(info->pseudo_palette))[regno] = v; | 384 | * drawing functions (cfb_imageblit, cfb_fillrect), the pseudo_palette |
321 | break; | 385 | * must be casted to (u32 *) _regardless_ of the bits per pixel. If the |
322 | } | 386 | * driver is using its own drawing functions, then it can use whatever |
323 | return 0; | 387 | * size it wants. |
388 | */ | ||
389 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
390 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
391 | u32 v; | ||
392 | |||
393 | if (regno >= 16) | ||
394 | return -EINVAL; | ||
395 | |||
396 | v = (red << info->var.red.offset) | | ||
397 | (green << info->var.green.offset) | | ||
398 | (blue << info->var.blue.offset) | | ||
399 | (transp << info->var.transp.offset); | ||
400 | |||
401 | ((u32*)(info->pseudo_palette))[regno] = v; | ||
324 | } | 402 | } |
403 | |||
325 | /* ... */ | 404 | /* ... */ |
326 | return 0; | 405 | return 0; |
327 | } | 406 | } |
@@ -340,6 +419,17 @@ static int xxxfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
340 | static int xxxfb_pan_display(struct fb_var_screeninfo *var, | 419 | static int xxxfb_pan_display(struct fb_var_screeninfo *var, |
341 | const struct fb_info *info) | 420 | const struct fb_info *info) |
342 | { | 421 | { |
422 | /* | ||
423 | * If your hardware does not support panning, _do_ _not_ implement this | ||
424 | * function. Creating a dummy function will just confuse user apps. | ||
425 | */ | ||
426 | |||
427 | /* | ||
428 | * Note that even if this function is fully functional, a setting of | ||
429 | * 0 in both xpanstep and ypanstep means that this function will never | ||
430 | * get called. | ||
431 | */ | ||
432 | |||
343 | /* ... */ | 433 | /* ... */ |
344 | return 0; | 434 | return 0; |
345 | } | 435 | } |
@@ -349,15 +439,20 @@ static int xxxfb_pan_display(struct fb_var_screeninfo *var, | |||
349 | * @blank_mode: the blank mode we want. | 439 | * @blank_mode: the blank mode we want. |
350 | * @info: frame buffer structure that represents a single frame buffer | 440 | * @info: frame buffer structure that represents a single frame buffer |
351 | * | 441 | * |
352 | * Blank the screen if blank_mode != 0, else unblank. Return 0 if | 442 | * Blank the screen if blank_mode != FB_BLANK_UNBLANK, else unblank. |
353 | * blanking succeeded, != 0 if un-/blanking failed due to e.g. a | 443 | * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to |
354 | * video mode which doesn't support it. Implements VESA suspend | 444 | * e.g. a video mode which doesn't support it. |
355 | * and powerdown modes on hardware that supports disabling hsync/vsync: | ||
356 | * blank_mode == 2: suspend vsync | ||
357 | * blank_mode == 3: suspend hsync | ||
358 | * blank_mode == 4: powerdown | ||
359 | * | 445 | * |
360 | * Returns negative errno on error, or zero on success. | 446 | * Implements VESA suspend and powerdown modes on hardware that supports |
447 | * disabling hsync/vsync: | ||
448 | * | ||
449 | * FB_BLANK_NORMAL = display is blanked, syncs are on. | ||
450 | * FB_BLANK_HSYNC_SUSPEND = hsync off | ||
451 | * FB_BLANK_VSYNC_SUSPEND = vsync off | ||
452 | * FB_BLANK_POWERDOWN = hsync and vsync off | ||
453 | * | ||
454 | * If implementing this function, at least support FB_BLANK_UNBLANK. | ||
455 | * Return !0 for any modes that are unimplemented. | ||
361 | * | 456 | * |
362 | */ | 457 | */ |
363 | static int xxxfb_blank(int blank_mode, const struct fb_info *info) | 458 | static int xxxfb_blank(int blank_mode, const struct fb_info *info) |
@@ -454,6 +549,14 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) | |||
454 | * @data: The actual data used to construct the image on the display. | 549 | * @data: The actual data used to construct the image on the display. |
455 | * @cmap: The colormap used for color images. | 550 | * @cmap: The colormap used for color images. |
456 | */ | 551 | */ |
552 | |||
553 | /* | ||
554 | * The generic function, cfb_imageblit, expects that the bitmap scanlines are | ||
555 | * padded to the next byte. Most hardware accelerators may require padding to | ||
556 | * the next u16 or the next u32. If that is the case, the driver can specify | ||
557 | * this by setting info->pixmap.scan_align = 2 or 4. See a more | ||
558 | * comprehensive description of the pixmap below. | ||
559 | */ | ||
457 | } | 560 | } |
458 | 561 | ||
459 | /** | 562 | /** |
@@ -517,6 +620,7 @@ int xxxfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
517 | */ | 620 | */ |
518 | void xxxfb_rotate(struct fb_info *info, int angle) | 621 | void xxxfb_rotate(struct fb_info *info, int angle) |
519 | { | 622 | { |
623 | /* Will be deprecated */ | ||
520 | } | 624 | } |
521 | 625 | ||
522 | /** | 626 | /** |
@@ -540,6 +644,9 @@ void xxxfb_poll(struct fb_info *info, poll_table *wait) | |||
540 | * so we can have consistent display output. | 644 | * so we can have consistent display output. |
541 | * | 645 | * |
542 | * @info: frame buffer structure that represents a single frame buffer | 646 | * @info: frame buffer structure that represents a single frame buffer |
647 | * | ||
648 | * If the driver has implemented its own hardware-based drawing function, | ||
649 | * implementing this function is highly recommended. | ||
543 | */ | 650 | */ |
544 | void xxxfb_sync(struct fb_info *info) | 651 | void xxxfb_sync(struct fb_info *info) |
545 | { | 652 | { |
@@ -549,20 +656,25 @@ void xxxfb_sync(struct fb_info *info) | |||
549 | * Initialization | 656 | * Initialization |
550 | */ | 657 | */ |
551 | 658 | ||
552 | int __init xxxfb_init(void) | 659 | /* static int __init xxfb_probe (struct device *device) -- for platform devs */ |
660 | static int __init xxxfb_probe(struct pci_dev *dev, | ||
661 | const_struct pci_device_id *ent) | ||
553 | { | 662 | { |
663 | struct fb_info *info; | ||
664 | struct xxx_par *par; | ||
665 | struct device = &dev->dev; /* for pci drivers */ | ||
554 | int cmap_len, retval; | 666 | int cmap_len, retval; |
555 | 667 | ||
556 | /* | 668 | /* |
557 | * For kernel boot options (in 'video=xxxfb:<options>' format) | 669 | * Dynamically allocate info and par |
558 | */ | 670 | */ |
559 | #ifndef MODULE | 671 | info = framebuffer_alloc(sizeof(struct xxx_par), device); |
560 | char *option = NULL; | ||
561 | 672 | ||
562 | if (fb_get_options("xxxfb", &option)) | 673 | if (!info) { |
563 | return -ENODEV; | 674 | /* goto error path */ |
564 | xxxfb_setup(option); | 675 | } |
565 | #endif | 676 | |
677 | par = info->par; | ||
566 | 678 | ||
567 | /* | 679 | /* |
568 | * Here we set the screen_base to the virtual memory address | 680 | * Here we set the screen_base to the virtual memory address |
@@ -570,18 +682,87 @@ int __init xxxfb_init(void) | |||
570 | * from the bus layer and then translate it to virtual memory | 682 | * from the bus layer and then translate it to virtual memory |
571 | * space via ioremap. Consult ioport.h. | 683 | * space via ioremap. Consult ioport.h. |
572 | */ | 684 | */ |
573 | info.screen_base = framebuffer_virtual_memory; | 685 | info->screen_base = framebuffer_virtual_memory; |
574 | info.fbops = &xxxfb_ops; | 686 | info->fbops = &xxxfb_ops; |
575 | info.fix = xxxfb_fix; | 687 | info->fix = xxxfb_fix; /* this will be the only time xxxfb_fix will be |
576 | info.pseudo_palette = pseudo_palette; | 688 | * used, so mark it as __initdata |
577 | 689 | */ | |
690 | info->pseudo_palette = pseudo_palette; /* The pseudopalette is an | ||
691 | * 16-member array | ||
692 | */ | ||
578 | /* | 693 | /* |
579 | * Set up flags to indicate what sort of acceleration your | 694 | * Set up flags to indicate what sort of acceleration your |
580 | * driver can provide (pan/wrap/copyarea/etc.) and whether it | 695 | * driver can provide (pan/wrap/copyarea/etc.) and whether it |
581 | * is a module -- see FBINFO_* in include/linux/fb.h | 696 | * is a module -- see FBINFO_* in include/linux/fb.h |
697 | * | ||
698 | * If your hardware can support any of the hardware accelerated functions | ||
699 | * fbcon performance will improve if info->flags is set properly. | ||
700 | * | ||
701 | * FBINFO_HWACCEL_COPYAREA - hardware moves | ||
702 | * FBINFO_HWACCEL_FILLRECT - hardware fills | ||
703 | * FBINFO_HWACCEL_IMAGEBLIT - hardware mono->color expansion | ||
704 | * FBINFO_HWACCEL_YPAN - hardware can pan display in y-axis | ||
705 | * FBINFO_HWACCEL_YWRAP - hardware can wrap display in y-axis | ||
706 | * FBINFO_HWACCEL_DISABLED - supports hardware accels, but disabled | ||
707 | * FBINFO_READS_FAST - if set, prefer moves over mono->color expansion | ||
708 | * FBINFO_MISC_TILEBLITTING - hardware can do tile blits | ||
709 | * | ||
710 | * NOTE: These are for fbcon use only. | ||
711 | */ | ||
712 | info->flags = FBINFO_DEFAULT; | ||
713 | |||
714 | /********************* This stage is optional ******************************/ | ||
715 | /* | ||
716 | * The struct pixmap is a scratch pad for the drawing functions. This | ||
717 | * is where the monochrome bitmap is constructed by the higher layers | ||
718 | * and then passed to the accelerator. For drivers that uses | ||
719 | * cfb_imageblit, you can skip this part. For those that have a more | ||
720 | * rigorous requirement, this stage is needed | ||
721 | */ | ||
722 | |||
723 | /* PIXMAP_SIZE should be small enough to optimize drawing, but not | ||
724 | * large enough that memory is wasted. A safe size is | ||
725 | * (max_xres * max_font_height/8). max_xres is driver dependent, | ||
726 | * max_font_height is 32. | ||
727 | */ | ||
728 | info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); | ||
729 | if (!info->pixmap.addr) { | ||
730 | /* goto error */ | ||
731 | } | ||
732 | |||
733 | info->pixmap.size = PIXMAP_SIZE; | ||
734 | |||
735 | /* | ||
736 | * FB_PIXMAP_SYSTEM - memory is in system ram | ||
737 | * FB_PIXMAP_IO - memory is iomapped | ||
738 | * FB_PIXMAP_SYNC - if set, will call fb_sync() per access to pixmap, | ||
739 | * usually if FB_PIXMAP_IO is set. | ||
740 | * | ||
741 | * Currently, FB_PIXMAP_IO is unimplemented. | ||
742 | */ | ||
743 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
744 | |||
745 | /* | ||
746 | * scan_align is the number of padding for each scanline. It is in bytes. | ||
747 | * Thus for accelerators that need padding to the next u32, put 4 here. | ||
748 | */ | ||
749 | info->pixmap.scan_align = 4; | ||
750 | |||
751 | /* | ||
752 | * buf_align is the amount to be padded for the buffer. For example, | ||
753 | * the i810fb needs a scan_align of 2 but expects it to be fed with | ||
754 | * dwords, so a buf_align = 4 is required. | ||
582 | */ | 755 | */ |
583 | info.flags = FBINFO_DEFAULT; | 756 | info->pixmap.buf_align = 4; |
584 | info.par = current_par; | 757 | |
758 | /* access_align is how many bits can be accessed from the framebuffer | ||
759 | * ie. some epson cards allow 16-bit access only. Most drivers will | ||
760 | * be safe with u32 here. | ||
761 | * | ||
762 | * NOTE: This field is currently unused. | ||
763 | */ | ||
764 | info->pixmap.scan_align = 32 | ||
765 | /***************************** End optional stage ***************************/ | ||
585 | 766 | ||
586 | /* | 767 | /* |
587 | * This should give a reasonable default video mode. The following is | 768 | * This should give a reasonable default video mode. The following is |
@@ -590,42 +771,145 @@ int __init xxxfb_init(void) | |||
590 | if (!mode_option) | 771 | if (!mode_option) |
591 | mode_option = "640x480@60"; | 772 | mode_option = "640x480@60"; |
592 | 773 | ||
593 | retval = fb_find_mode(&info.var, &info, mode_option, NULL, 0, NULL, 8); | 774 | retval = fb_find_mode(info->var, info, mode_option, NULL, 0, NULL, 8); |
594 | 775 | ||
595 | if (!retval || retval == 4) | 776 | if (!retval || retval == 4) |
596 | return -EINVAL; | 777 | return -EINVAL; |
597 | 778 | ||
598 | /* This has to been done !!! */ | 779 | /* This has to been done !!! */ |
599 | fb_alloc_cmap(&info.cmap, cmap_len, 0); | 780 | fb_alloc_cmap(info->cmap, cmap_len, 0); |
600 | 781 | ||
601 | /* | 782 | /* |
602 | * The following is done in the case of having hardware with a static | 783 | * The following is done in the case of having hardware with a static |
603 | * mode. If we are setting the mode ourselves we don't call this. | 784 | * mode. If we are setting the mode ourselves we don't call this. |
604 | */ | 785 | */ |
605 | info.var = xxxfb_var; | 786 | info->var = xxxfb_var; |
606 | 787 | ||
607 | if (register_framebuffer(&info) < 0) | 788 | /* |
789 | * For drivers that can... | ||
790 | */ | ||
791 | xxxfb_check_var(&info->var, info); | ||
792 | |||
793 | /* | ||
794 | * Does a call to fb_set_par() before register_framebuffer needed? This | ||
795 | * will depend on you and the hardware. If you are sure that your driver | ||
796 | * is the only device in the system, a call to fb_set_par() is safe. | ||
797 | * | ||
798 | * Hardware in x86 systems has a VGA core. Calling set_par() at this | ||
799 | * point will corrupt the VGA console, so it might be safer to skip a | ||
800 | * call to set_par here and just allow fbcon to do it for you. | ||
801 | */ | ||
802 | /* xxxfb_set_par(info); */ | ||
803 | |||
804 | if (register_framebuffer(info) < 0) | ||
608 | return -EINVAL; | 805 | return -EINVAL; |
609 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node, | 806 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
610 | info.fix.id); | 807 | info->fix.id); |
808 | pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */ | ||
611 | return 0; | 809 | return 0; |
612 | } | 810 | } |
613 | 811 | ||
614 | /* | 812 | /* |
615 | * Cleanup | 813 | * Cleanup |
616 | */ | 814 | */ |
815 | /* static void __exit xxxfb_remove(struct device *device) */ | ||
816 | static void __exit xxxfb_remove(struct pci_dev *dev) | ||
817 | { | ||
818 | struct fb_info *info = pci_get_drv_data(dev); | ||
819 | /* or dev_get_drv_data(device); */ | ||
820 | |||
821 | if (info) { | ||
822 | unregister_framebuffer(info); | ||
823 | fb_dealloc_cmap(&info.cmap); | ||
824 | /* ... */ | ||
825 | framebuffer_release(info); | ||
826 | } | ||
827 | |||
828 | return 0; | ||
829 | } | ||
617 | 830 | ||
618 | static void __exit xxxfb_cleanup(void) | 831 | #if CONFIG_PCI |
832 | /* For PCI drivers */ | ||
833 | static struct pci_driver xxxfb_driver = { | ||
834 | .name = "xxxfb", | ||
835 | .id_table = xxxfb_devices, | ||
836 | .probe = xxxfb_probe, | ||
837 | .remove = __devexit_p(xxxfb_remove), | ||
838 | .suspend = xxxfb_suspend, /* optional */ | ||
839 | .resume = xxxfb_resume, /* optional */ | ||
840 | }; | ||
841 | |||
842 | static int __init xxxfb_init(void) | ||
619 | { | 843 | { |
620 | /* | 844 | /* |
621 | * If your driver supports multiple boards, you should unregister and | 845 | * For kernel boot options (in 'video=xxxfb:<options>' format) |
622 | * clean up all instances. | 846 | */ |
623 | */ | 847 | #ifndef MODULE |
848 | char *option = NULL; | ||
624 | 849 | ||
625 | unregister_framebuffer(info); | 850 | if (fb_get_options("xxxfb", &option)) |
626 | fb_dealloc_cmap(&info.cmap); | 851 | return -ENODEV; |
627 | /* ... */ | 852 | xxxfb_setup(option); |
853 | #endif | ||
854 | |||
855 | return pci_register_driver(&xxxfb_driver); | ||
856 | } | ||
857 | |||
858 | static void __exit xxxfb_exit(void) | ||
859 | { | ||
860 | pci_unregister_driver(&xxxfb_driver); | ||
628 | } | 861 | } |
862 | #else | ||
863 | #include <linux/platform_device.h> | ||
864 | /* for platform devices */ | ||
865 | static struct device_driver xxxfb_driver = { | ||
866 | .name = "xxxfb", | ||
867 | .bus = &platform_bus_type, | ||
868 | .probe = xxxfb_probe, | ||
869 | .remove = xxxfb_remove, | ||
870 | .suspend = xxxfb_suspend, /* optional */ | ||
871 | .resume = xxxfb_resume, /* optional */ | ||
872 | }; | ||
873 | |||
874 | static struct platform_device xxxfb_device = { | ||
875 | .name = "xxxfb", | ||
876 | }; | ||
877 | |||
878 | static int __init xxxfb_init(void) | ||
879 | { | ||
880 | int ret; | ||
881 | /* | ||
882 | * For kernel boot options (in 'video=xxxfb:<options>' format) | ||
883 | */ | ||
884 | #ifndef MODULE | ||
885 | char *option = NULL; | ||
886 | |||
887 | if (fb_get_options("xxxfb", &option)) | ||
888 | return -ENODEV; | ||
889 | xxxfb_setup(option); | ||
890 | #endif | ||
891 | ret = driver_register(&xxxfb_driver); | ||
892 | |||
893 | if (!ret) { | ||
894 | ret = platform_device_register(&xxxfb_device); | ||
895 | if (ret) | ||
896 | driver_unregister(&xxxfb_driver); | ||
897 | } | ||
898 | |||
899 | return ret; | ||
900 | } | ||
901 | |||
902 | static void __exit xxxfb_exit(void) | ||
903 | { | ||
904 | platform_device_unregister(&xxxfb_device); | ||
905 | driver_unregister(&xxxfb_driver); | ||
906 | } | ||
907 | #endif | ||
908 | |||
909 | MODULE_LICENSE("GPL"); | ||
910 | module_init(xxxfb_init); | ||
911 | module_exit(xxxfb_exit); | ||
912 | |||
629 | 913 | ||
630 | /* | 914 | /* |
631 | * Setup | 915 | * Setup |