Commit a417ea5b9d22dc5733f6fac5cee72735cb7f8d99
Committed by
Greg Kroah-Hartman
1 parent
ddc0ec3be8
Exists in
smarct4x-processor-sdk-04.01.00.06
and in
1 other branch
video: fbdev: cobalt_lcdfb: Handle return NULL error from devm_ioremap
[ Upstream commit 4dcd19bfabaee8f9f4bcf203afba09b98ccbaf76 ] Here, If devm_ioremap will fail. It will return NULL. Kernel can run into a NULL-pointer dereference. This error check will avoid NULL pointer dereference. Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com> Acked-by: Yoichi Yuasa <yuasa@linux-mips.org> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> Signed-off-by: Sasha Levin <alexander.levin@verizon.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 5 additions and 0 deletions Inline Diff
drivers/video/fbdev/cobalt_lcdfb.c
1 | /* | 1 | /* |
2 | * Cobalt/SEAD3 LCD frame buffer driver. | 2 | * Cobalt/SEAD3 LCD frame buffer driver. |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> | 4 | * Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org> |
5 | * Copyright (C) 2012 MIPS Technologies, Inc. | 5 | * Copyright (C) 2012 MIPS Technologies, Inc. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | * | 11 | * |
12 | * This program is distributed in the hope that it will be useful, | 12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ | 20 | */ |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/fb.h> | 22 | #include <linux/fb.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Cursor position address | 31 | * Cursor position address |
32 | * \X 0 1 2 ... 14 15 | 32 | * \X 0 1 2 ... 14 15 |
33 | * Y+----+----+----+---+----+----+ | 33 | * Y+----+----+----+---+----+----+ |
34 | * 0|0x00|0x01|0x02|...|0x0e|0x0f| | 34 | * 0|0x00|0x01|0x02|...|0x0e|0x0f| |
35 | * +----+----+----+---+----+----+ | 35 | * +----+----+----+---+----+----+ |
36 | * 1|0x40|0x41|0x42|...|0x4e|0x4f| | 36 | * 1|0x40|0x41|0x42|...|0x4e|0x4f| |
37 | * +----+----+----+---+----+----+ | 37 | * +----+----+----+---+----+----+ |
38 | */ | 38 | */ |
39 | #define LCD_DATA_REG_OFFSET 0x10 | 39 | #define LCD_DATA_REG_OFFSET 0x10 |
40 | #define LCD_XRES_MAX 16 | 40 | #define LCD_XRES_MAX 16 |
41 | #define LCD_YRES_MAX 2 | 41 | #define LCD_YRES_MAX 2 |
42 | #define LCD_CHARS_MAX 32 | 42 | #define LCD_CHARS_MAX 32 |
43 | 43 | ||
44 | #define LCD_CLEAR 0x01 | 44 | #define LCD_CLEAR 0x01 |
45 | #define LCD_CURSOR_MOVE_HOME 0x02 | 45 | #define LCD_CURSOR_MOVE_HOME 0x02 |
46 | #define LCD_RESET 0x06 | 46 | #define LCD_RESET 0x06 |
47 | #define LCD_OFF 0x08 | 47 | #define LCD_OFF 0x08 |
48 | #define LCD_CURSOR_OFF 0x0c | 48 | #define LCD_CURSOR_OFF 0x0c |
49 | #define LCD_CURSOR_BLINK_OFF 0x0e | 49 | #define LCD_CURSOR_BLINK_OFF 0x0e |
50 | #define LCD_CURSOR_ON 0x0f | 50 | #define LCD_CURSOR_ON 0x0f |
51 | #define LCD_ON LCD_CURSOR_ON | 51 | #define LCD_ON LCD_CURSOR_ON |
52 | #define LCD_CURSOR_MOVE_LEFT 0x10 | 52 | #define LCD_CURSOR_MOVE_LEFT 0x10 |
53 | #define LCD_CURSOR_MOVE_RIGHT 0x14 | 53 | #define LCD_CURSOR_MOVE_RIGHT 0x14 |
54 | #define LCD_DISPLAY_LEFT 0x18 | 54 | #define LCD_DISPLAY_LEFT 0x18 |
55 | #define LCD_DISPLAY_RIGHT 0x1c | 55 | #define LCD_DISPLAY_RIGHT 0x1c |
56 | #define LCD_PRERESET 0x3f /* execute 4 times continuously */ | 56 | #define LCD_PRERESET 0x3f /* execute 4 times continuously */ |
57 | #define LCD_BUSY 0x80 | 57 | #define LCD_BUSY 0x80 |
58 | 58 | ||
59 | #define LCD_GRAPHIC_MODE 0x40 | 59 | #define LCD_GRAPHIC_MODE 0x40 |
60 | #define LCD_TEXT_MODE 0x80 | 60 | #define LCD_TEXT_MODE 0x80 |
61 | #define LCD_CUR_POS_MASK 0x7f | 61 | #define LCD_CUR_POS_MASK 0x7f |
62 | 62 | ||
63 | #define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK) | 63 | #define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK) |
64 | #define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE) | 64 | #define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE) |
65 | 65 | ||
66 | static inline void lcd_write_control(struct fb_info *info, u8 control) | 66 | static inline void lcd_write_control(struct fb_info *info, u8 control) |
67 | { | 67 | { |
68 | writel((u32)control << 24, info->screen_base); | 68 | writel((u32)control << 24, info->screen_base); |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline u8 lcd_read_control(struct fb_info *info) | 71 | static inline u8 lcd_read_control(struct fb_info *info) |
72 | { | 72 | { |
73 | return readl(info->screen_base) >> 24; | 73 | return readl(info->screen_base) >> 24; |
74 | } | 74 | } |
75 | 75 | ||
76 | static inline void lcd_write_data(struct fb_info *info, u8 data) | 76 | static inline void lcd_write_data(struct fb_info *info, u8 data) |
77 | { | 77 | { |
78 | writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET); | 78 | writel((u32)data << 24, info->screen_base + LCD_DATA_REG_OFFSET); |
79 | } | 79 | } |
80 | 80 | ||
81 | static inline u8 lcd_read_data(struct fb_info *info) | 81 | static inline u8 lcd_read_data(struct fb_info *info) |
82 | { | 82 | { |
83 | return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24; | 83 | return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24; |
84 | } | 84 | } |
85 | 85 | ||
86 | static int lcd_busy_wait(struct fb_info *info) | 86 | static int lcd_busy_wait(struct fb_info *info) |
87 | { | 87 | { |
88 | u8 val = 0; | 88 | u8 val = 0; |
89 | int timeout = 10, retval = 0; | 89 | int timeout = 10, retval = 0; |
90 | 90 | ||
91 | do { | 91 | do { |
92 | val = lcd_read_control(info); | 92 | val = lcd_read_control(info); |
93 | val &= LCD_BUSY; | 93 | val &= LCD_BUSY; |
94 | if (val != LCD_BUSY) | 94 | if (val != LCD_BUSY) |
95 | break; | 95 | break; |
96 | 96 | ||
97 | if (msleep_interruptible(1)) | 97 | if (msleep_interruptible(1)) |
98 | return -EINTR; | 98 | return -EINTR; |
99 | 99 | ||
100 | timeout--; | 100 | timeout--; |
101 | } while (timeout); | 101 | } while (timeout); |
102 | 102 | ||
103 | if (val == LCD_BUSY) | 103 | if (val == LCD_BUSY) |
104 | retval = -EBUSY; | 104 | retval = -EBUSY; |
105 | 105 | ||
106 | return retval; | 106 | return retval; |
107 | } | 107 | } |
108 | 108 | ||
109 | static void lcd_clear(struct fb_info *info) | 109 | static void lcd_clear(struct fb_info *info) |
110 | { | 110 | { |
111 | int i; | 111 | int i; |
112 | 112 | ||
113 | for (i = 0; i < 4; i++) { | 113 | for (i = 0; i < 4; i++) { |
114 | udelay(150); | 114 | udelay(150); |
115 | 115 | ||
116 | lcd_write_control(info, LCD_PRERESET); | 116 | lcd_write_control(info, LCD_PRERESET); |
117 | } | 117 | } |
118 | 118 | ||
119 | udelay(150); | 119 | udelay(150); |
120 | 120 | ||
121 | lcd_write_control(info, LCD_CLEAR); | 121 | lcd_write_control(info, LCD_CLEAR); |
122 | 122 | ||
123 | udelay(150); | 123 | udelay(150); |
124 | 124 | ||
125 | lcd_write_control(info, LCD_RESET); | 125 | lcd_write_control(info, LCD_RESET); |
126 | } | 126 | } |
127 | 127 | ||
128 | static struct fb_fix_screeninfo cobalt_lcdfb_fix = { | 128 | static struct fb_fix_screeninfo cobalt_lcdfb_fix = { |
129 | .id = "cobalt-lcd", | 129 | .id = "cobalt-lcd", |
130 | .type = FB_TYPE_TEXT, | 130 | .type = FB_TYPE_TEXT, |
131 | .type_aux = FB_AUX_TEXT_MDA, | 131 | .type_aux = FB_AUX_TEXT_MDA, |
132 | .visual = FB_VISUAL_MONO01, | 132 | .visual = FB_VISUAL_MONO01, |
133 | .line_length = LCD_XRES_MAX, | 133 | .line_length = LCD_XRES_MAX, |
134 | .accel = FB_ACCEL_NONE, | 134 | .accel = FB_ACCEL_NONE, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf, | 137 | static ssize_t cobalt_lcdfb_read(struct fb_info *info, char __user *buf, |
138 | size_t count, loff_t *ppos) | 138 | size_t count, loff_t *ppos) |
139 | { | 139 | { |
140 | char src[LCD_CHARS_MAX]; | 140 | char src[LCD_CHARS_MAX]; |
141 | unsigned long pos; | 141 | unsigned long pos; |
142 | int len, retval = 0; | 142 | int len, retval = 0; |
143 | 143 | ||
144 | pos = *ppos; | 144 | pos = *ppos; |
145 | if (pos >= LCD_CHARS_MAX || count == 0) | 145 | if (pos >= LCD_CHARS_MAX || count == 0) |
146 | return 0; | 146 | return 0; |
147 | 147 | ||
148 | if (count > LCD_CHARS_MAX) | 148 | if (count > LCD_CHARS_MAX) |
149 | count = LCD_CHARS_MAX; | 149 | count = LCD_CHARS_MAX; |
150 | 150 | ||
151 | if (pos + count > LCD_CHARS_MAX) | 151 | if (pos + count > LCD_CHARS_MAX) |
152 | count = LCD_CHARS_MAX - pos; | 152 | count = LCD_CHARS_MAX - pos; |
153 | 153 | ||
154 | for (len = 0; len < count; len++) { | 154 | for (len = 0; len < count; len++) { |
155 | retval = lcd_busy_wait(info); | 155 | retval = lcd_busy_wait(info); |
156 | if (retval < 0) | 156 | if (retval < 0) |
157 | break; | 157 | break; |
158 | 158 | ||
159 | lcd_write_control(info, LCD_TEXT_POS(pos)); | 159 | lcd_write_control(info, LCD_TEXT_POS(pos)); |
160 | 160 | ||
161 | retval = lcd_busy_wait(info); | 161 | retval = lcd_busy_wait(info); |
162 | if (retval < 0) | 162 | if (retval < 0) |
163 | break; | 163 | break; |
164 | 164 | ||
165 | src[len] = lcd_read_data(info); | 165 | src[len] = lcd_read_data(info); |
166 | if (pos == 0x0f) | 166 | if (pos == 0x0f) |
167 | pos = 0x40; | 167 | pos = 0x40; |
168 | else | 168 | else |
169 | pos++; | 169 | pos++; |
170 | } | 170 | } |
171 | 171 | ||
172 | if (retval < 0 && signal_pending(current)) | 172 | if (retval < 0 && signal_pending(current)) |
173 | return -ERESTARTSYS; | 173 | return -ERESTARTSYS; |
174 | 174 | ||
175 | if (copy_to_user(buf, src, len)) | 175 | if (copy_to_user(buf, src, len)) |
176 | return -EFAULT; | 176 | return -EFAULT; |
177 | 177 | ||
178 | *ppos += len; | 178 | *ppos += len; |
179 | 179 | ||
180 | return len; | 180 | return len; |
181 | } | 181 | } |
182 | 182 | ||
183 | static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf, | 183 | static ssize_t cobalt_lcdfb_write(struct fb_info *info, const char __user *buf, |
184 | size_t count, loff_t *ppos) | 184 | size_t count, loff_t *ppos) |
185 | { | 185 | { |
186 | char dst[LCD_CHARS_MAX]; | 186 | char dst[LCD_CHARS_MAX]; |
187 | unsigned long pos; | 187 | unsigned long pos; |
188 | int len, retval = 0; | 188 | int len, retval = 0; |
189 | 189 | ||
190 | pos = *ppos; | 190 | pos = *ppos; |
191 | if (pos >= LCD_CHARS_MAX || count == 0) | 191 | if (pos >= LCD_CHARS_MAX || count == 0) |
192 | return 0; | 192 | return 0; |
193 | 193 | ||
194 | if (count > LCD_CHARS_MAX) | 194 | if (count > LCD_CHARS_MAX) |
195 | count = LCD_CHARS_MAX; | 195 | count = LCD_CHARS_MAX; |
196 | 196 | ||
197 | if (pos + count > LCD_CHARS_MAX) | 197 | if (pos + count > LCD_CHARS_MAX) |
198 | count = LCD_CHARS_MAX - pos; | 198 | count = LCD_CHARS_MAX - pos; |
199 | 199 | ||
200 | if (copy_from_user(dst, buf, count)) | 200 | if (copy_from_user(dst, buf, count)) |
201 | return -EFAULT; | 201 | return -EFAULT; |
202 | 202 | ||
203 | for (len = 0; len < count; len++) { | 203 | for (len = 0; len < count; len++) { |
204 | retval = lcd_busy_wait(info); | 204 | retval = lcd_busy_wait(info); |
205 | if (retval < 0) | 205 | if (retval < 0) |
206 | break; | 206 | break; |
207 | 207 | ||
208 | lcd_write_control(info, LCD_TEXT_POS(pos)); | 208 | lcd_write_control(info, LCD_TEXT_POS(pos)); |
209 | 209 | ||
210 | retval = lcd_busy_wait(info); | 210 | retval = lcd_busy_wait(info); |
211 | if (retval < 0) | 211 | if (retval < 0) |
212 | break; | 212 | break; |
213 | 213 | ||
214 | lcd_write_data(info, dst[len]); | 214 | lcd_write_data(info, dst[len]); |
215 | if (pos == 0x0f) | 215 | if (pos == 0x0f) |
216 | pos = 0x40; | 216 | pos = 0x40; |
217 | else | 217 | else |
218 | pos++; | 218 | pos++; |
219 | } | 219 | } |
220 | 220 | ||
221 | if (retval < 0 && signal_pending(current)) | 221 | if (retval < 0 && signal_pending(current)) |
222 | return -ERESTARTSYS; | 222 | return -ERESTARTSYS; |
223 | 223 | ||
224 | *ppos += len; | 224 | *ppos += len; |
225 | 225 | ||
226 | return len; | 226 | return len; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info) | 229 | static int cobalt_lcdfb_blank(int blank_mode, struct fb_info *info) |
230 | { | 230 | { |
231 | int retval; | 231 | int retval; |
232 | 232 | ||
233 | retval = lcd_busy_wait(info); | 233 | retval = lcd_busy_wait(info); |
234 | if (retval < 0) | 234 | if (retval < 0) |
235 | return retval; | 235 | return retval; |
236 | 236 | ||
237 | switch (blank_mode) { | 237 | switch (blank_mode) { |
238 | case FB_BLANK_UNBLANK: | 238 | case FB_BLANK_UNBLANK: |
239 | lcd_write_control(info, LCD_ON); | 239 | lcd_write_control(info, LCD_ON); |
240 | break; | 240 | break; |
241 | default: | 241 | default: |
242 | lcd_write_control(info, LCD_OFF); | 242 | lcd_write_control(info, LCD_OFF); |
243 | break; | 243 | break; |
244 | } | 244 | } |
245 | 245 | ||
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | 249 | static int cobalt_lcdfb_cursor(struct fb_info *info, struct fb_cursor *cursor) |
250 | { | 250 | { |
251 | u32 x, y; | 251 | u32 x, y; |
252 | int retval; | 252 | int retval; |
253 | 253 | ||
254 | switch (cursor->set) { | 254 | switch (cursor->set) { |
255 | case FB_CUR_SETPOS: | 255 | case FB_CUR_SETPOS: |
256 | x = cursor->image.dx; | 256 | x = cursor->image.dx; |
257 | y = cursor->image.dy; | 257 | y = cursor->image.dy; |
258 | if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX) | 258 | if (x >= LCD_XRES_MAX || y >= LCD_YRES_MAX) |
259 | return -EINVAL; | 259 | return -EINVAL; |
260 | 260 | ||
261 | retval = lcd_busy_wait(info); | 261 | retval = lcd_busy_wait(info); |
262 | if (retval < 0) | 262 | if (retval < 0) |
263 | return retval; | 263 | return retval; |
264 | 264 | ||
265 | lcd_write_control(info, | 265 | lcd_write_control(info, |
266 | LCD_TEXT_POS(info->fix.line_length * y + x)); | 266 | LCD_TEXT_POS(info->fix.line_length * y + x)); |
267 | break; | 267 | break; |
268 | default: | 268 | default: |
269 | return -EINVAL; | 269 | return -EINVAL; |
270 | } | 270 | } |
271 | 271 | ||
272 | retval = lcd_busy_wait(info); | 272 | retval = lcd_busy_wait(info); |
273 | if (retval < 0) | 273 | if (retval < 0) |
274 | return retval; | 274 | return retval; |
275 | 275 | ||
276 | if (cursor->enable) | 276 | if (cursor->enable) |
277 | lcd_write_control(info, LCD_CURSOR_ON); | 277 | lcd_write_control(info, LCD_CURSOR_ON); |
278 | else | 278 | else |
279 | lcd_write_control(info, LCD_CURSOR_OFF); | 279 | lcd_write_control(info, LCD_CURSOR_OFF); |
280 | 280 | ||
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | static struct fb_ops cobalt_lcd_fbops = { | 284 | static struct fb_ops cobalt_lcd_fbops = { |
285 | .owner = THIS_MODULE, | 285 | .owner = THIS_MODULE, |
286 | .fb_read = cobalt_lcdfb_read, | 286 | .fb_read = cobalt_lcdfb_read, |
287 | .fb_write = cobalt_lcdfb_write, | 287 | .fb_write = cobalt_lcdfb_write, |
288 | .fb_blank = cobalt_lcdfb_blank, | 288 | .fb_blank = cobalt_lcdfb_blank, |
289 | .fb_cursor = cobalt_lcdfb_cursor, | 289 | .fb_cursor = cobalt_lcdfb_cursor, |
290 | }; | 290 | }; |
291 | 291 | ||
292 | static int cobalt_lcdfb_probe(struct platform_device *dev) | 292 | static int cobalt_lcdfb_probe(struct platform_device *dev) |
293 | { | 293 | { |
294 | struct fb_info *info; | 294 | struct fb_info *info; |
295 | struct resource *res; | 295 | struct resource *res; |
296 | int retval; | 296 | int retval; |
297 | 297 | ||
298 | info = framebuffer_alloc(0, &dev->dev); | 298 | info = framebuffer_alloc(0, &dev->dev); |
299 | if (!info) | 299 | if (!info) |
300 | return -ENOMEM; | 300 | return -ENOMEM; |
301 | 301 | ||
302 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 302 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); |
303 | if (!res) { | 303 | if (!res) { |
304 | framebuffer_release(info); | 304 | framebuffer_release(info); |
305 | return -EBUSY; | 305 | return -EBUSY; |
306 | } | 306 | } |
307 | 307 | ||
308 | info->screen_size = resource_size(res); | 308 | info->screen_size = resource_size(res); |
309 | info->screen_base = devm_ioremap(&dev->dev, res->start, | 309 | info->screen_base = devm_ioremap(&dev->dev, res->start, |
310 | info->screen_size); | 310 | info->screen_size); |
311 | if (!info->screen_base) { | ||
312 | framebuffer_release(info); | ||
313 | return -ENOMEM; | ||
314 | } | ||
315 | |||
311 | info->fbops = &cobalt_lcd_fbops; | 316 | info->fbops = &cobalt_lcd_fbops; |
312 | info->fix = cobalt_lcdfb_fix; | 317 | info->fix = cobalt_lcdfb_fix; |
313 | info->fix.smem_start = res->start; | 318 | info->fix.smem_start = res->start; |
314 | info->fix.smem_len = info->screen_size; | 319 | info->fix.smem_len = info->screen_size; |
315 | info->pseudo_palette = NULL; | 320 | info->pseudo_palette = NULL; |
316 | info->par = NULL; | 321 | info->par = NULL; |
317 | info->flags = FBINFO_DEFAULT; | 322 | info->flags = FBINFO_DEFAULT; |
318 | 323 | ||
319 | retval = register_framebuffer(info); | 324 | retval = register_framebuffer(info); |
320 | if (retval < 0) { | 325 | if (retval < 0) { |
321 | framebuffer_release(info); | 326 | framebuffer_release(info); |
322 | return retval; | 327 | return retval; |
323 | } | 328 | } |
324 | 329 | ||
325 | platform_set_drvdata(dev, info); | 330 | platform_set_drvdata(dev, info); |
326 | 331 | ||
327 | lcd_clear(info); | 332 | lcd_clear(info); |
328 | 333 | ||
329 | fb_info(info, "Cobalt server LCD frame buffer device\n"); | 334 | fb_info(info, "Cobalt server LCD frame buffer device\n"); |
330 | 335 | ||
331 | return 0; | 336 | return 0; |
332 | } | 337 | } |
333 | 338 | ||
334 | static int cobalt_lcdfb_remove(struct platform_device *dev) | 339 | static int cobalt_lcdfb_remove(struct platform_device *dev) |
335 | { | 340 | { |
336 | struct fb_info *info; | 341 | struct fb_info *info; |
337 | 342 | ||
338 | info = platform_get_drvdata(dev); | 343 | info = platform_get_drvdata(dev); |
339 | if (info) { | 344 | if (info) { |
340 | unregister_framebuffer(info); | 345 | unregister_framebuffer(info); |
341 | framebuffer_release(info); | 346 | framebuffer_release(info); |
342 | } | 347 | } |
343 | 348 | ||
344 | return 0; | 349 | return 0; |
345 | } | 350 | } |
346 | 351 | ||
347 | static struct platform_driver cobalt_lcdfb_driver = { | 352 | static struct platform_driver cobalt_lcdfb_driver = { |
348 | .probe = cobalt_lcdfb_probe, | 353 | .probe = cobalt_lcdfb_probe, |
349 | .remove = cobalt_lcdfb_remove, | 354 | .remove = cobalt_lcdfb_remove, |
350 | .driver = { | 355 | .driver = { |
351 | .name = "cobalt-lcd", | 356 | .name = "cobalt-lcd", |
352 | }, | 357 | }, |
353 | }; | 358 | }; |
354 | module_platform_driver(cobalt_lcdfb_driver); | 359 | module_platform_driver(cobalt_lcdfb_driver); |
355 | 360 | ||
356 | MODULE_LICENSE("GPL v2"); | 361 | MODULE_LICENSE("GPL v2"); |
357 | MODULE_AUTHOR("Yoichi Yuasa"); | 362 | MODULE_AUTHOR("Yoichi Yuasa"); |
358 | MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver"); | 363 | MODULE_DESCRIPTION("Cobalt server LCD frame buffer driver"); |
359 | 364 |