lkml.org 
[lkml]   [2002]   [Dec]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: [STATUS] fbdev api.
From
Date
On Tue, 2002-12-03 at 02:07, James Simmons wrote:
>
> Hi!
>
> I have a new patch avaiable. It is against 2.5.50. The patch is at
>
> http://phoenix.infradead.org/~jsimmons/fbdev.diff.gz
>
> Have fun!!!!
>
> Drivers ported are: (Give them a try)
>
> ATI Mach 64
> ATI 128
> VESA
> VGA16
> HGA
> NIVIDA
> NEOMAGIC
>
> The BIG changes are:
>
> 1) The seperation of the console code out of the fbdev drivers.
>
> 2) Total modularity of the frmaebuffer console system. Yes that is
> right. You can build it has modules. Great for testing.
>
> The following are results of the new changes which I have tested.
>
> With my VIA laptop with my neomagic card I was able to build it with
> vgacon and no fbcon. Then I insmod neofb and the soft accel (cfb*.c)
> needed. It loading and did NOT change the video hardware state. At this
> point I could run fbdev apps including a X server using /dev/fb solely.
> On opening /dev/fb0 the graphics hardware state changed. In theory I could
> exit X and get vgacon back. In order to do this I have to reset the
> hardware back to vga text mode in the fb_release function. It can be done
> but I haven't done it yet.
> With the second experiment I was able to insmod the fonts and fbcon.o.
> Then it switched from vgacon to fbcon. In theory I could again call the
> release function and reset the hardware back to a text mode state. All
> that is needed is the hardware specific code to do this.
>
> Things to be done:
>
> 1) A few bugs in fbcon to hammer out.
>
> 2) Fbcon to support changing resolution via the console layer.
>
> 3) Move the logo code out of fbcon.c to fbmem.c. With pure fbdev
> you need something to let you know things worked.
>
> 4) Software rotation.
>

Attached is a patch against linux-2.5.50 + your fbdev.diff.

a. changed __MOD_INC_USE_COUNT and __MOD_DEC_USE_COUNT to
try_module_get() and module_put() respectively. This will allow modules
to be safely unloaded.

b. Another rewrite of fbcon_show_logo() so it's more understandable
(hopefully). I also added support for the rest of the visuals, but
untested yet.

Tested with different hardware (little endian):
truecolor, directcolor, pseudocolor, vga 4-bit pseudocolor.

Not tested:
static psuedocolor, mono01, and mono10.

c. prevent fbcon module from loading if no fbdev is registered. Also
made fbcon module unsafe to unload (for now). This is optional, of course.

diff -Naur linux-2.5.50-js/drivers/video/console/fbcon.c linux/drivers/video/console/fbcon.c
--- linux-2.5.50-js/drivers/video/console/fbcon.c 2002-12-03 10:55:55.000000000 +0000
+++ linux/drivers/video/console/fbcon.c 2002-12-03 10:56:26.000000000 +0000
@@ -317,18 +317,16 @@
if (newidx != con2fb_map[unit]) {
oldfb = registered_fb[oldidx];
newfb = registered_fb[newidx];
- if (newfb->fbops->owner)
- __MOD_INC_USE_COUNT(newfb->fbops->owner);
+ if (!try_module_get(newfb->fbops->owner))
+ return;
if (newfb->fbops->fb_open
&& newfb->fbops->fb_open(newfb, 0)) {
- if (newfb->fbops->owner)
- __MOD_DEC_USE_COUNT(newfb->fbops->owner);
+ module_put(newfb->fbops->owner);
return;
}
if (oldfb->fbops->fb_release)
oldfb->fbops->fb_release(oldfb, 0);
- if (oldfb->fbops->owner)
- __MOD_DEC_USE_COUNT(oldfb->fbops->owner);
+ module_put(oldfb->fbops->owner);
vc = fb_display[unit].conp;
fontdata = fb_display[unit].fontdata;
userfont = fb_display[unit].userfont;
@@ -596,10 +594,10 @@
info->currcon = -1;

owner = info->fbops->owner;
- if (owner)
- __MOD_INC_USE_COUNT(owner);
- if (info->fbops->fb_open && info->fbops->fb_open(info, 0) && owner)
- __MOD_DEC_USE_COUNT(owner);
+ if (!try_module_get(owner))
+ return NULL;
+ if (info->fbops->fb_open && info->fbops->fb_open(info, 0))
+ module_put(owner);

if (info->fix.type != FB_TYPE_TEXT) {
if (fbcon_softback_size) {
@@ -2549,111 +2547,226 @@
return n < 0 ? d >> -n : d << n;
}

-static int __init fbcon_show_logo(void)
+static void __init fbcon_set_logocmap(struct fb_info *info)
+{
+ int i, j, n;
+
+ for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
+ n = LINUX_LOGO_COLORS - i;
+ if (n > 16)
+ /* palette_cmap provides space for only 16 colors at once */
+ n = 16;
+ palette_cmap.start = 32 + i;
+ palette_cmap.len = n;
+ for (j = 0; j < n; ++j) {
+ palette_cmap.red[j] =
+ (linux_logo_red[i + j] << 8) |
+ linux_logo_red[i + j];
+ palette_cmap.green[j] =
+ (linux_logo_green[i + j] << 8) |
+ linux_logo_green[i + j];
+ palette_cmap.blue[j] =
+ (linux_logo_blue[i + j] << 8) |
+ linux_logo_blue[i + j];
+ }
+ fb_set_cmap(&palette_cmap, 1, info);
+ }
+}
+
+static void __init fbcon_set_logo_truepalette(struct fb_info *info, u32 *palette)
+{
+ unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
+ unsigned char redmask, greenmask, bluemask;
+ int redshift, greenshift, blueshift;
+ int i;
+
+ /*
+ * We have to create a temporary palette since console palette is only
+ * 16 colors long.
+ */
+ /* Bug: Doesn't obey msb_right ... (who needs that?) */
+ redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
+ greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
+ bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
+ redshift = info->var.red.offset - (8 - info->var.red.length);
+ greenshift = info->var.green.offset - (8 - info->var.green.length);
+ blueshift = info->var.blue.offset - (8 - info->var.blue.length);
+
+
+ for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
+ palette[i+32] = (safe_shift((linux_logo_red[i] & redmask), redshift) |
+ safe_shift((linux_logo_green[i] & greenmask), greenshift) |
+ safe_shift((linux_logo_blue[i] & bluemask), blueshift));
+ }
+}
+
+static void __init fbcon_set_logo_directpalette(struct fb_info *info, u32 *palette)
+{
+ int redshift, greenshift, blueshift;
+ int i;
+
+ redshift = info->var.red.offset;
+ greenshift = info->var.green.offset;
+ blueshift = info->var.blue.offset;
+
+ for (i = 32; i < LINUX_LOGO_COLORS; i++)
+ palette[i] = i << redshift | i << greenshift | i << blueshift;
+
+}
+
+static void __init fbcon_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
{
- struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
+ int i, j;
+
+ switch (needs_logo) {
+ case 4:
+ for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
+ logo[i*2] = linux_logo16[i] >> 4;
+ logo[(i*2)+1] = linux_logo16[i] & 0xf;
+ }
+ break;
+ case 1:
+ case ~1:
+ default:
+ for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
+ for (j = 0; j < 8; j++)
+ logo[i*2] = (linux_logo_bw[i] & (7 - j)) ?
+ ((needs_logo == 1) ? 1 : 0) :
+ ((needs_logo == 1) ? 0 : 1);
+
+ break;
+ }
+}
+
+/*
+ * Three (3) kinds of logo maps exist. linux_logo (>16 colors), linux_logo_16
+ * (16 colors) and linux_logo_bw (2 colors). Depending on the visual format and
+ * color depth of the framebuffer, the DAC, the pseudo_palette, and the logo data
+ * will be adjusted accordingly.
+ *
+ * Case 1 - linux_logo:
+ * Color exceeds the number of console colors (16), thus we set the hardware DAC
+ * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
+ *
+ * For visuals that require color info from the pseudo_palette, we also construct
+ * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
+ * will be set.
+ *
+ * Case 2 - linux_logo_16:
+ * The number of colors just matches the console colors, thus there is no need
+ * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
+ * each byte contains color information for two pixels (upper and lower nibble).
+ * To be consistent with fb_imageblit() usage, we therefore separate the two
+ * nibbles into separate bytes. The "needs_logo" flag will be set to 4.
+ *
+ * Case 3 - linux_logo_bw:
+ * This is similar with Case 2. Each byte contains information for 8 pixels.
+ * We isolate each bit and expand each into a byte. The "needs_logo" flag will
+ * be set to 1.
+ */
+static int __init fbcon_show_logo(void)
+ {
+ struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
struct fb_info *info = p->fb_info;
struct vc_data *vc = info->display_fg;
struct fb_image image;
u32 *palette = NULL, *saved_palette = NULL;
- int depth = info->var.bits_per_pixel;
- unsigned char *fb = info->screen_base;
- unsigned char *logo;
- int i, j, n, x;
- int logo_depth, done = 0;
+ unsigned char *fb = info->screen_base, *logo_new = NULL;
+ int done = 0, x;
+ int needs_cmapreset = 0;
+ int needs_truepalette = 0;
+ int needs_directpalette = 0;
+ int needs_logo = 0;

/* Return if the frame buffer is not mapped */
- if (!fb)
+ if (!fb || !info->fbops->fb_imageblit)
return 0;

- /*
- * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for
- * DIRECTCOLOR
- * We don't have to set the colors for the 16-color logo, since that logo
- * uses the standard VGA text console palette
- */
- if ((info->fix.visual == FB_VISUAL_PSEUDOCOLOR && depth >= 8) ||
- (info->fix.visual == FB_VISUAL_DIRECTCOLOR && depth >= 24))
- for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
- n = LINUX_LOGO_COLORS - i;
- if (n > 16)
- /* palette_cmap provides space for only 16 colors at once */
- n = 16;
- palette_cmap.start = 32 + i;
- palette_cmap.len = n;
- for (j = 0; j < n; ++j) {
- palette_cmap.red[j] =
- (linux_logo_red[i + j] << 8) |
- linux_logo_red[i + j];
- palette_cmap.green[j] =
- (linux_logo_green[i + j] << 8) |
- linux_logo_green[i + j];
- palette_cmap.blue[j] =
- (linux_logo_blue[i + j] << 8) |
- linux_logo_blue[i + j];
- }
- fb_set_cmap(&palette_cmap, 1, info);
- }
-
- if (depth >= 8) {
- logo = linux_logo;
- logo_depth = 8;
- } else if (depth >= 4) {
- logo = linux_logo16;
- logo_depth = 4;
- } else {
- logo = linux_logo_bw;
- logo_depth = 1;
- }
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
- unsigned char mask[9] =
- { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
- unsigned char redmask, greenmask, bluemask;
- int redshift, greenshift, blueshift;
-
- /* Bug: Doesn't obey msb_right ... (who needs that?) */
- redmask =
- mask[info->var.red.length <
- 8 ? info->var.red.length : 8];
- greenmask =
- mask[info->var.green.length <
- 8 ? info->var.green.length : 8];
- bluemask =
- mask[info->var.blue.length <
- 8 ? info->var.blue.length : 8];
- redshift =
- info->var.red.offset - (8 - info->var.red.length);
- greenshift =
- info->var.green.offset - (8 - info->var.green.length);
- blueshift =
- info->var.blue.offset - (8 - info->var.blue.length);
+ image.depth = info->var.bits_per_pixel;

- /*
- * We have to create a temporary palette since console palette is only
- * 16 colors long.
- */
+ /* reasonable default */
+ if (image.depth >= 8)
+ image.data = linux_logo;
+ else if (image.depth >= 4)
+ image.data = linux_logo16;
+ else
+ image.data = linux_logo_bw;
+
+ switch (info->fix.visual) {
+ case FB_VISUAL_TRUECOLOR:
+ needs_truepalette = 1;
+ if (image.depth >= 4 && image.depth <= 8)
+ needs_logo = 4;
+ else if (image.depth < 4)
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_DIRECTCOLOR:
+ if (image.depth >= 24) {
+ needs_directpalette = 1;
+ needs_cmapreset = 1;
+ }
+ /* 16 colors */
+ else if (image.depth >= 16)
+ needs_logo = 4;
+ /* 2 colors */
+ else
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_MONO01:
+ /* reversed 0 = fg, 1 = bg */
+ needs_logo = ~1;
+ break;
+ case FB_VISUAL_MONO10:
+ needs_logo = 1;
+ break;
+ case FB_VISUAL_PSEUDOCOLOR:
+ default:
+ if (image.depth >= 8)
+ needs_cmapreset = 1;
+ /* fall through */
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ /* 16 colors */
+ if (image.depth >= 4 && image.depth < 8)
+ needs_logo = 4;
+ /* 2 colors */
+ else if (image.depth < 4)
+ needs_logo = 1;
+ break;
+ }
+
+ if (needs_cmapreset)
+ fbcon_set_logocmap(info);
+
+ if (needs_truepalette || needs_directpalette) {
palette = kmalloc(256 * 4, GFP_KERNEL);
if (palette == NULL)
- return (LOGO_H + vc->vc_font.height - 1)/vc->vc_font.height;
+ return 1;
+
+ if (needs_truepalette)
+ fbcon_set_logo_truepalette(info, palette);
+ else
+ fbcon_set_logo_directpalette(info, palette);

- for (i = 0; i < LINUX_LOGO_COLORS; i++) {
- palette[i + 32] =
- (safe_shift
- ((linux_logo_red[i] & redmask),
- redshift) | safe_shift((linux_logo_green[i] &
- greenmask),
- greenshift) |
- safe_shift((linux_logo_blue[i] & bluemask),
- blueshift));
- }
saved_palette = info->pseudo_palette;
info->pseudo_palette = palette;
}
+
+ if (needs_logo) {
+ logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
+ if (logo_new == NULL) {
+ if (palette)
+ kfree(palette);
+ if (saved_palette)
+ info->pseudo_palette = saved_palette;
+ return 1;
+ }
+
+ image.data = logo_new;
+ fbcon_set_logo(info, logo_new, needs_logo);
+ }
+
image.width = LOGO_W;
image.height = LOGO_H;
- image.depth = depth;
- image.data = logo;
image.dy = 0;

for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
@@ -2667,6 +2780,8 @@
kfree(palette);
if (saved_palette != NULL)
info->pseudo_palette = saved_palette;
+ if (logo_new != NULL)
+ kfree(logo_new);
/*
* Modes not yet supported: packed pixels with depth != 8 (does such a
* thing exist in reality?)
@@ -2701,7 +2816,10 @@

int __init fb_console_init(void)
{
+ if (!num_registered_fb)
+ return -ENODEV;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+ __unsafe(THIS_MODULE);
return 0;
}

diff -Naur linux-2.5.50-js/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.5.50-js/drivers/video/fbmem.c 2002-12-03 10:55:42.000000000 +0000
+++ linux/drivers/video/fbmem.c 2002-12-03 10:57:29.000000000 +0000
@@ -730,12 +730,12 @@
#endif /* CONFIG_KMOD */
if (!(info = registered_fb[fbidx]))
return -ENODEV;
- if (info->fbops->owner)
- __MOD_INC_USE_COUNT(info->fbops->owner);
+ if (!try_module_get(info->fbops->owner))
+ return -ENODEV;
if (info->fbops->fb_open) {
res = info->fbops->fb_open(info,1);
- if (res && info->fbops->owner)
- __MOD_DEC_USE_COUNT(info->fbops->owner);
+ if (res)
+ module_put(info->fbops->owner);
}
return res;
}
@@ -750,8 +750,7 @@
info = registered_fb[fbidx];
if (info->fbops->fb_release)
info->fbops->fb_release(info,1);
- if (info->fbops->owner)
- __MOD_DEC_USE_COUNT(info->fbops->owner);
+ module_put(info->fbops->owner);
unlock_kernel();
return 0;
}
\
 
 \ /
  Last update: 2005-03-22 13:31    [W:0.082 / U:0.072 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site