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;
}
next prev parent 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).