upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / video / lcdoops.c
1 /*
2  * LCD Oops/Panic logger
3  *
4  * Copyright (C) 2010 Samsung Electronics.
5  *      Inki Dae <inki.dae@samsung.com>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  *
21  */
22
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/kmsg_dump.h>
26 #include <linux/time.h>
27 #include <linux/io.h>
28 #include <linux/ioport.h>
29 #include <linux/delay.h>
30 #include <linux/platform_device.h>
31
32 #include "fbutil.h"
33
34 #define LCDOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
35
36 #define RECORD_SIZE 4096
37
38 static int dump_oops = 1;
39 module_param(dump_oops, int, 0600);
40 MODULE_PARM_DESC(dump_oops,
41                 "set to 1 to dump oopses, 0 to only dump panics (default 1)");
42
43 static struct lcdoops_context {
44         struct kmsg_dumper      dump;
45 } oops_cxt;
46
47 char buf[8192];
48
49 static void lcdoops_do_dump(struct kmsg_dumper *dumper,
50                 enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
51                 const char *s2, unsigned long l2)
52 {
53         struct lcdoops_context *cxt = container_of(dumper,
54                         struct lcdoops_context, dump);
55         unsigned long s1_start, s2_start;
56         unsigned long l1_cpy, l2_cpy;
57
58         /* Only dump oopses if dump_oops is set */
59         if (reason == KMSG_DUMP_OOPS && !dump_oops)
60                 return;
61
62         l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - LCDOOPS_HEADER_SIZE));
63         l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - LCDOOPS_HEADER_SIZE) - l2_cpy);
64
65         s2_start = l2 - l2_cpy;
66         s1_start = l1 - l1_cpy;
67
68         memcpy(buf, s1 + s1_start, l1_cpy);
69         memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
70
71         fb_printk(buf);
72 }
73
74 static int __init lcdoops_probe(struct platform_device *pdev)
75 {
76         struct lcdoops_context *cxt = &oops_cxt;
77         int err = -EINVAL;
78
79         cxt->dump.dump = lcdoops_do_dump;
80         err = kmsg_dump_register(&cxt->dump);
81         if (err) {
82                 printk(KERN_ERR "lcdoops: registering kmsg dumper failed");
83                 goto fail;
84         }
85
86         return 0;
87
88 fail:
89         return err;
90 }
91
92 static int __exit lcdoops_remove(struct platform_device *pdev)
93 {
94         struct lcdoops_context *cxt = &oops_cxt;
95
96         if (kmsg_dump_unregister(&cxt->dump) < 0)
97                 printk(KERN_WARNING "lcdoops: could not unregister kmsg_dumper");
98
99         return 0;
100 }
101
102 static struct platform_driver lcdoops_driver = {
103         .remove                 = __exit_p(lcdoops_remove),
104         .driver                 = {
105                 .name           = "lcdoops",
106                 .owner          = THIS_MODULE,
107         },
108 };
109
110 static int __init lcdoops_init(void)
111 {
112         return platform_driver_probe(&lcdoops_driver, lcdoops_probe);
113 }
114
115 static void __exit lcdoops_exit(void)
116 {
117         platform_driver_unregister(&lcdoops_driver);
118 }
119
120 module_init(lcdoops_init);
121 module_exit(lcdoops_exit);
122
123 MODULE_LICENSE("GPL");
124 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
125 MODULE_DESCRIPTION("LCD Oops/Panic logger/driver");