Commit | Line | Data |
---|---|---|
351f683b | 1 | // SPDX-License-Identifier: GPL-2.0 |
70e84049 MOS |
2 | /* |
3 | * Filename: cfag12864bfb.c | |
4 | * Version: 0.1.0 | |
5 | * Description: cfag12864b LCD framebuffer driver | |
70e84049 MOS |
6 | * Depends: cfag12864b |
7 | * | |
c131bd0b | 8 | * Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org> |
70e84049 | 9 | * Date: 2006-10-31 |
70e84049 MOS |
10 | */ |
11 | ||
12 | #include <linux/init.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/kernel.h> | |
70e84049 MOS |
15 | #include <linux/errno.h> |
16 | #include <linux/fb.h> | |
17 | #include <linux/mm.h> | |
18 | #include <linux/platform_device.h> | |
70e84049 MOS |
19 | #include <linux/cfag12864b.h> |
20 | ||
21 | #define CFAG12864BFB_NAME "cfag12864bfb" | |
22 | ||
7223310f | 23 | static const struct fb_fix_screeninfo cfag12864bfb_fix = { |
70e84049 MOS |
24 | .id = "cfag12864b", |
25 | .type = FB_TYPE_PACKED_PIXELS, | |
26 | .visual = FB_VISUAL_MONO10, | |
27 | .xpanstep = 0, | |
28 | .ypanstep = 0, | |
29 | .ywrapstep = 0, | |
30 | .line_length = CFAG12864B_WIDTH / 8, | |
31 | .accel = FB_ACCEL_NONE, | |
32 | }; | |
33 | ||
7223310f | 34 | static const struct fb_var_screeninfo cfag12864bfb_var = { |
70e84049 MOS |
35 | .xres = CFAG12864B_WIDTH, |
36 | .yres = CFAG12864B_HEIGHT, | |
37 | .xres_virtual = CFAG12864B_WIDTH, | |
38 | .yres_virtual = CFAG12864B_HEIGHT, | |
39 | .bits_per_pixel = 1, | |
40 | .red = { 0, 1, 0 }, | |
4e5d74fc HD |
41 | .green = { 0, 1, 0 }, |
42 | .blue = { 0, 1, 0 }, | |
70e84049 MOS |
43 | .left_margin = 0, |
44 | .right_margin = 0, | |
45 | .upper_margin = 0, | |
46 | .lower_margin = 0, | |
47 | .vmode = FB_VMODE_NONINTERLACED, | |
48 | }; | |
49 | ||
50 | static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | |
51 | { | |
461e274b SJ |
52 | struct page *pages = virt_to_page(cfag12864b_buffer); |
53 | ||
54 | return vm_map_pages_zero(vma, &pages, 1); | |
70e84049 MOS |
55 | } |
56 | ||
bd223ac6 | 57 | static const struct fb_ops cfag12864bfb_ops = { |
70e84049 | 58 | .owner = THIS_MODULE, |
bfeeffbb AO |
59 | .fb_read = fb_sys_read, |
60 | .fb_write = fb_sys_write, | |
61 | .fb_fillrect = sys_fillrect, | |
62 | .fb_copyarea = sys_copyarea, | |
63 | .fb_imageblit = sys_imageblit, | |
70e84049 MOS |
64 | .fb_mmap = cfag12864bfb_mmap, |
65 | }; | |
66 | ||
0fe763c5 | 67 | static int cfag12864bfb_probe(struct platform_device *device) |
70e84049 MOS |
68 | { |
69 | int ret = -EINVAL; | |
4e5d74fc | 70 | struct fb_info *info = framebuffer_alloc(0, &device->dev); |
70e84049 MOS |
71 | |
72 | if (!info) | |
73 | goto none; | |
74 | ||
75 | info->screen_base = (char __iomem *) cfag12864b_buffer; | |
76 | info->screen_size = CFAG12864B_SIZE; | |
77 | info->fbops = &cfag12864bfb_ops; | |
78 | info->fix = cfag12864bfb_fix; | |
79 | info->var = cfag12864bfb_var; | |
80 | info->pseudo_palette = NULL; | |
81 | info->par = NULL; | |
82 | info->flags = FBINFO_FLAG_DEFAULT; | |
83 | ||
84 | if (register_framebuffer(info) < 0) | |
85 | goto fballoced; | |
86 | ||
87 | platform_set_drvdata(device, info); | |
88 | ||
31b6780c | 89 | fb_info(info, "%s frame buffer device\n", info->fix.id); |
70e84049 MOS |
90 | |
91 | return 0; | |
92 | ||
93 | fballoced: | |
94 | framebuffer_release(info); | |
95 | ||
96 | none: | |
97 | return ret; | |
98 | } | |
99 | ||
0fe763c5 | 100 | static int cfag12864bfb_remove(struct platform_device *device) |
70e84049 MOS |
101 | { |
102 | struct fb_info *info = platform_get_drvdata(device); | |
103 | ||
104 | if (info) { | |
105 | unregister_framebuffer(info); | |
106 | framebuffer_release(info); | |
107 | } | |
108 | ||
109 | return 0; | |
110 | } | |
111 | ||
112 | static struct platform_driver cfag12864bfb_driver = { | |
113 | .probe = cfag12864bfb_probe, | |
0fe763c5 | 114 | .remove = cfag12864bfb_remove, |
70e84049 MOS |
115 | .driver = { |
116 | .name = CFAG12864BFB_NAME, | |
117 | }, | |
118 | }; | |
119 | ||
120 | static struct platform_device *cfag12864bfb_device; | |
121 | ||
122 | static int __init cfag12864bfb_init(void) | |
123 | { | |
34173a4a MO |
124 | int ret = -EINVAL; |
125 | ||
126 | /* cfag12864b_init() must be called first */ | |
127 | if (!cfag12864b_isinited()) { | |
128 | printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " | |
129 | "cfag12864b is not initialized\n"); | |
130 | goto none; | |
131 | } | |
70e84049 MOS |
132 | |
133 | if (cfag12864b_enable()) { | |
134 | printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " | |
135 | "can't enable cfag12864b refreshing (being used)\n"); | |
136 | return -ENODEV; | |
137 | } | |
138 | ||
139 | ret = platform_driver_register(&cfag12864bfb_driver); | |
140 | ||
141 | if (!ret) { | |
142 | cfag12864bfb_device = | |
143 | platform_device_alloc(CFAG12864BFB_NAME, 0); | |
144 | ||
145 | if (cfag12864bfb_device) | |
146 | ret = platform_device_add(cfag12864bfb_device); | |
147 | else | |
148 | ret = -ENOMEM; | |
149 | ||
150 | if (ret) { | |
151 | platform_device_put(cfag12864bfb_device); | |
152 | platform_driver_unregister(&cfag12864bfb_driver); | |
153 | } | |
154 | } | |
155 | ||
34173a4a | 156 | none: |
70e84049 MOS |
157 | return ret; |
158 | } | |
159 | ||
160 | static void __exit cfag12864bfb_exit(void) | |
161 | { | |
162 | platform_device_unregister(cfag12864bfb_device); | |
163 | platform_driver_unregister(&cfag12864bfb_driver); | |
164 | cfag12864b_disable(); | |
165 | } | |
166 | ||
167 | module_init(cfag12864bfb_init); | |
168 | module_exit(cfag12864bfb_exit); | |
169 | ||
170 | MODULE_LICENSE("GPL v2"); | |
c131bd0b | 171 | MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>"); |
70e84049 | 172 | MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); |