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, ¬ify);
+ }
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