Boot Console on LCD (fbcon) second try...

From: Pattrick Hueper <pattyh_at_gmx.net>
Date: Fri, 27 Feb 2004 21:55:02 +0100

Hi,

the last days i learned a lot about the kernel, trying to understand the
initialization of drivers, devices, ... anyway, i tried to follow Andrews
recommendation to use notifiers for fbcon initialization for LCD.

Here is what i came up with, it's a larger patch, i hope its ok to send the
patch as text in the mail, i dont know how to do it otherwise...

Here are my thoughts:

- i added fb_notify_chain in fbmem.c and fb.h to call when a new framebuffer
is registered.
- fb_console_init registers in the fb_notify_chain, if no framebuffers have
registered before, and it is not already registered in the notify_chain
- the notify_chain calls fbcon_notify and that in turn unregisters from the
notify_chain and calls take_over_console...
- another thing i found in my search is that fbmem.c calls all other
framebuffers inits methods (e.g. pxafb), so i added mq1100fb... i dont think
that is necessary, but since the other framebuffers are listed there, too...
- since mq1100fb_init may be called multiple times, then i had to protect it
too, using the driver_registered variable, otherwise the kernel hangs, i
think thats a problem of the notify chains, it the same function is added
twice to the notify_chain, it will "loop" endlessly... thats the reason for
"protecting" mq1100fb_init() and fb_console_init() from registering twice. I
dont know if the method using a static int is very elegant, but didnt find a
method to check the notify chain for the same function.

Anyway, i uploaded my zImage, initrd, .config and other files to
http://patty-server.homeip.net/h2200-port/feb27 if anyone wants to try it...

Davide, maybe this will help you try to figure out, why your ir console does
not come up?

And i am happy about any suggestions or comments from the more experienced
kernel developers!

Cheers, Patty

Here come the diff(s):

Index: arch/arm/mach-pxa/h2200_lcd.c
===================================================================
RCS file: /cvs/linux/kernel26/arch/arm/mach-pxa/h2200_lcd.c,v
retrieving revision 1.2
diff -u -b -r1.2 h2200_lcd.c
--- arch/arm/mach-pxa/h2200_lcd.c 22 Feb 2004 15:52:53 -0000 1.2
+++ arch/arm/mach-pxa/h2200_lcd.c 27 Feb 2004 19:50:41 -0000
@@ -309,7 +309,6 @@
 {
        debug_func ("\n");
        return soc_driver_register (&h2200_fp_soc_device_driver);
- return 0;
 }

 static void __exit
Index: drivers/video/fbmem.c
===================================================================
RCS file: /cvs/linux/kernel26/drivers/video/fbmem.c,v
retrieving revision 1.11
diff -u -b -r1.11 fbmem.c
--- drivers/video/fbmem.c 25 Nov 2003 17:29:58 -0000 1.11
+++ drivers/video/fbmem.c 27 Feb 2004 19:51:07 -0000
@@ -164,6 +164,7 @@
 extern int tcx_setup(char*);
 extern int leo_init(void);
 extern int leo_setup(char*);
+extern int mq1100fb_init(void);

 static struct {
        const char *name;
@@ -377,6 +378,9 @@
 #ifdef CONFIG_FB_VOODOO1
        { "sstfb", sstfb_init, sstfb_setup },
 #endif
+#ifdef CONFIG_FB_MQ1100
+ { "mq1100fb", mq1100fb_init, NULL },
+#endif
        /*
         * Generic drivers that don't use resource management (yet)
         */
@@ -1222,6 +1226,10 @@
 #endif
 };

+/* for notification of newly registered framebuffers*/
+struct notifier_block *fb_notify_chain;
+EXPORT_SYMBOL(fb_notify_chain);
+
 /**
  * register_framebuffer - registers a frame buffer device
  * @fb_info: frame buffer info structure
@@ -1265,6 +1273,9 @@

        devfs_mk_cdev(MKDEV(FB_MAJOR, i),
                        S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);
+
+ notifier_call_chain (&fb_notify_chain, 0, fb_info);
+
        return 0;
 }

Index: drivers/video/mq1100fb.c
===================================================================
RCS file: /cvs/linux/kernel26/drivers/video/mq1100fb.c,v
retrieving revision 1.18
diff -u -b -r1.18 mq1100fb.c
--- drivers/video/mq1100fb.c 23 Feb 2004 13:05:46 -0000 1.18
+++ drivers/video/mq1100fb.c 27 Feb 2004 19:51:08 -0000
@@ -47,12 +47,10 @@
        /* The name of the LCD module to use */
        const char *lm_name;
        struct lcd_module *lm;
- union {
                /* The RGB palette */
                struct mq1100fb_rgb palette[256];
- /* Notifier block (used until init complete) */
+ /* Notifier block */
                 struct notifier_block notify;
- };
        /* The pseudo-palette */
        u32 pseudo_pal[16];
        /* Device instance number (0-7) */
@@ -427,6 +425,14 @@
                return NOTIFY_DONE;

        info->lm = lm;
+
+ /* if we dont have a backlight module yet, we try to find it once again
*/
+ if (!info->bm) {
+ info->bm =
backlight_module_get(backlight_module_find(info->bm_name));
+ }
+
+
+
        mq1100fb_power (info, 1);
        if (!info->active)
                return NOTIFY_DONE;
@@ -437,7 +443,6 @@
        return NOTIFY_OK;
 }

-
 static int mq1100fb_probe (struct device *dev, struct mediaq11xx_base *base)
 {
        struct mq1100fb_info *info;
@@ -476,7 +481,6 @@
        /* Defer complete initialization if no LCD module */
        if (!info->active)
        {
- /* Temporary use palette storage for notifier block */
                info->notify.notifier_call = mq1100fb_lcd_notify;
                info->notify.next = NULL;
                info->notify.priority = 0;
@@ -496,10 +500,10 @@

 static void mq1100fb_soc_shutdown (struct device *dev)
 {
+ debug_func ("\n");
        struct mq1100fb_info *info =
                (struct mq1100fb_info *)dev_get_drvdata (dev);

- debug_func ("\n");

        if (!info->initcomplete)
                notifier_chain_unregister (&lcd_module_chain, &info->notify);
@@ -515,11 +519,10 @@

 static int mq1100fb_soc_suspend (struct device *dev, u32 state, u32 level)
 {
+ debug_func ("\n");
        struct mq1100fb_info *info =
                (struct mq1100fb_info *)dev_get_drvdata (dev);

- debug_func ("\n");
-
        mq1100fb_power (info, 0);

        return 0;
@@ -527,11 +530,10 @@

 static int mq1100fb_soc_resume (struct device *dev, u32 level)
 {
+ debug_func ("\n");
        struct mq1100fb_info *info =
                (struct mq1100fb_info *)dev_get_drvdata (dev);

- debug_func ("\n");
-
        mq1100fb_power (info, 1);

        return 0;
@@ -551,14 +553,24 @@
        }
 };

-static int __init mq1100fb_init(void)
+static int driver_registered = 0;
+
+int __init mq1100fb_init(void)
 {
+ debug_func("\n");
+ if (!driver_registered)
+ {
+ driver_registered = 1;
        return soc_driver_register (&mq1100fb_soc_device_driver);
+ }
+ return 0;
 }

-static void __exit mq1100fb_exit(void)
+void __exit mq1100fb_exit(void)
 {
+ debug_func("\n");
        soc_driver_unregister (&mq1100fb_soc_device_driver);
+ driver_registered = 0;
 }

 module_init(mq1100fb_init);
Index: drivers/video/console/fbcon.c
===================================================================
RCS file: /cvs/linux/kernel26/drivers/video/console/fbcon.c,v
retrieving revision 1.1.1.1
diff -u -b -r1.1.1.1 fbcon.c
--- drivers/video/console/fbcon.c 14 Jul 2003 18:57:14 -0000
1.1.1.1
+++ drivers/video/console/fbcon.c 27 Feb 2004 19:51:12 -0000
@@ -2259,6 +2259,21 @@
        return 0;
 }

+struct notifier_block notify;
+
+static int notify_registered = 0;
+
+int fbcon_notify (struct notifier_block *self,
+ unsigned long a, void *b)
+{
+ DPRINTK("\n");
+ notifier_chain_unregister (&fb_notify_chain, self);
+ notify_registered = 0;
+ /* a framebuffer was registered, try to take over the console */
+ take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+ return NOTIFY_OK;
+}
+
 /*
  * The console `switch' structure for the frame buffer based console
  */
@@ -2287,8 +2302,19 @@

 int __init fb_console_init(void)
 {
+ /* Defer take over console, until a framebuffer has registered */
        if (!num_registered_fb)
+ {
+ if (!notify_registered)
+ {
+ notify_registered = 1;
+ notify.notifier_call = fbcon_notify;
+ notify.next = NULL;
+ notify.priority = 0;
+ notifier_chain_register (&fb_notify_chain, &notify);
+ }
                return -ENODEV;
+ }
        take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
        return 0;
 }
Index: include/linux/fb.h
===================================================================
RCS file: /cvs/linux/kernel26/include/linux/fb.h,v
retrieving revision 1.1.1.1
diff -u -b -r1.1.1.1 fb.h
--- include/linux/fb.h 14 Jul 2003 18:58:40 -0000 1.1.1.1
+++ include/linux/fb.h 27 Feb 2004 19:51:28 -0000
@@ -3,6 +3,7 @@

 #include <linux/tty.h>
 #include <linux/workqueue.h>
+#include <linux/notifier.h>
 #include <asm/types.h>
 #include <asm/io.h>

@@ -489,6 +490,8 @@
                             u32 s_pitch, u32 height);
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
+extern struct notifier_block *fb_notify_chain;
+

 /* drivers/video/fbmon.c */
 #define FB_MAXTIMINGS 0
Received on Fri Feb 27 2004 - 21:02:16 EST

This archive was generated by hypermail 2.2.0 : Mon Jul 25 2005 - 17:19:25 EDT