linux-fbdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Antonino Daplas <adaplas@pol.net>
To: James Simmons <jsimmons@infradead.org>
Cc: Linux Fbdev development list
	<linux-fbdev-devel@lists.sourceforge.net>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Linux console project <linuxconsole-dev@lists.sourceforge.net>
Subject: Re: [STATUS] fbdev api.
Date: 03 Dec 2002 17:23:17 +0500	[thread overview]
Message-ID: <1038918094.1225.18.camel@localhost.localdomain> (raw)
In-Reply-To: <Pine.LNX.4.44.0212022051320.20834-100000@phoenix.infradead.org>

[-- Attachment #1: Type: text/plain, Size: 2493 bytes --]

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.


[-- Attachment #2: fbcon.diff --]
[-- Type: text/x-patch, Size: 12619 bytes --]

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;
 }

  reply	other threads:[~2002-12-03 12:23 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2002-12-02 21:07 [STATUS] fbdev api James Simmons
2002-12-03 12:23 ` Antonino Daplas [this message]
2002-12-03 22:18   ` James Simmons
2002-12-04  3:32     ` Antonino Daplas
2002-12-04 23:00       ` James Simmons
2002-12-06 19:50 ` Christoph Hellwig
2002-12-06 21:21   ` James Simmons

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1038918094.1225.18.camel@localhost.localdomain \
    --to=adaplas@pol.net \
    --cc=jsimmons@infradead.org \
    --cc=linux-fbdev-devel@lists.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxconsole-dev@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).