1 /*
2  * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
3  *
4  * Copyright (C) 2008, Jaya Kumar
5  *
6  * This file is subject to the terms and conditions of the GNU General Public
7  * License. See the file COPYING in the main directory of this archive for
8  * more details.
9  *
10  * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11  *
12  * This work was made possible by help and equipment support from E-Ink
13  * Corporation. http://www.eink.com/
14  *
15  * This driver is written to be used with the Metronome display controller.
16  * It is intended to be architecture independent. A board specific driver
17  * must be used to perform all the physical IO interactions. An example
18  * is provided as am200epd.c
19  *
20  */
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/errno.h>
24 #include <linux/string.h>
25 #include <linux/mm.h>
26 #include <linux/vmalloc.h>
27 #include <linux/delay.h>
28 #include <linux/interrupt.h>
29 #include <linux/fb.h>
30 #include <linux/init.h>
31 #include <linux/platform_device.h>
32 #include <linux/list.h>
33 #include <linux/firmware.h>
34 #include <linux/dma-mapping.h>
35 #include <linux/uaccess.h>
36 #include <linux/irq.h>
37 
38 #include <video/metronomefb.h>
39 
40 #include <asm/unaligned.h>
41 
42 /* Display specific information */
43 #define DPY_W 832
44 #define DPY_H 622
45 
46 static int user_wfm_size;
47 
48 /* frame differs from image. frame includes non-visible pixels */
49 struct epd_frame {
50 	int fw; /* frame width */
51 	int fh; /* frame height */
52 	u16 config[4];
53 	int wfm_size;
54 };
55 
56 static struct epd_frame epd_frame_table[] = {
57 	{
58 		.fw = 832,
59 		.fh = 622,
60 		.config = {
61 			15 /* sdlew */
62 			| 2 << 8 /* sdosz */
63 			| 0 << 11 /* sdor */
64 			| 0 << 12 /* sdces */
65 			| 0 << 15, /* sdcer */
66 			42 /* gdspl */
67 			| 1 << 8 /* gdr1 */
68 			| 1 << 9 /* sdshr */
69 			| 0 << 15, /* gdspp */
70 			18 /* gdspw */
71 			| 0 << 15, /* dispc */
72 			599 /* vdlc */
73 			| 0 << 11 /* dsi */
74 			| 0 << 12, /* dsic */
75 		},
76 		.wfm_size = 47001,
77 	},
78 	{
79 		.fw = 1088,
80 		.fh = 791,
81 		.config = {
82 			0x0104,
83 			0x031f,
84 			0x0088,
85 			0x02ff,
86 		},
87 		.wfm_size = 46770,
88 	},
89 	{
90 		.fw = 1200,
91 		.fh = 842,
92 		.config = {
93 			0x0101,
94 			0x030e,
95 			0x0012,
96 			0x0280,
97 		},
98 		.wfm_size = 46770,
99 	},
100 };
101 
102 static struct fb_fix_screeninfo metronomefb_fix = {
103 	.id =		"metronomefb",
104 	.type =		FB_TYPE_PACKED_PIXELS,
105 	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
106 	.xpanstep =	0,
107 	.ypanstep =	0,
108 	.ywrapstep =	0,
109 	.line_length =	DPY_W,
110 	.accel =	FB_ACCEL_NONE,
111 };
112 
113 static struct fb_var_screeninfo metronomefb_var = {
114 	.xres		= DPY_W,
115 	.yres		= DPY_H,
116 	.xres_virtual	= DPY_W,
117 	.yres_virtual	= DPY_H,
118 	.bits_per_pixel	= 8,
119 	.grayscale	= 1,
120 	.nonstd		= 1,
121 	.red =		{ 4, 3, 0 },
122 	.green =	{ 0, 0, 0 },
123 	.blue =		{ 0, 0, 0 },
124 	.transp =	{ 0, 0, 0 },
125 };
126 
127 /* the waveform structure that is coming from userspace firmware */
128 struct waveform_hdr {
129 	u8 stuff[32];
130 
131 	u8 wmta[3];
132 	u8 fvsn;
133 
134 	u8 luts;
135 	u8 mc;
136 	u8 trc;
137 	u8 stuff3;
138 
139 	u8 endb;
140 	u8 swtb;
141 	u8 stuff2a[2];
142 
143 	u8 stuff2b[3];
144 	u8 wfm_cs;
145 } __attribute__ ((packed));
146 
147 /* main metronomefb functions */
148 static u8 calc_cksum(int start, int end, u8 *mem)
149 {
150 	u8 tmp = 0;
151 	int i;
152 
153 	for (i = start; i < end; i++)
154 		tmp += mem[i];
155 
156 	return tmp;
157 }
158 
159 static u16 calc_img_cksum(u16 *start, int length)
160 {
161 	u16 tmp = 0;
162 
163 	while (length--)
164 		tmp += *start++;
165 
166 	return tmp;
167 }
168 
169 /* here we decode the incoming waveform file and populate metromem */
170 static int load_waveform(u8 *mem, size_t size, int m, int t,
171 			 struct metronomefb_par *par)
172 {
173 	int tta;
174 	int wmta;
175 	int trn = 0;
176 	int i;
177 	unsigned char v;
178 	u8 cksum;
179 	int cksum_idx;
180 	int wfm_idx, owfm_idx;
181 	int mem_idx = 0;
182 	struct waveform_hdr *wfm_hdr;
183 	u8 *metromem = par->metromem_wfm;
184 	struct device *dev = par->info->dev;
185 
186 	if (user_wfm_size)
187 		epd_frame_table[par->dt].wfm_size = user_wfm_size;
188 
189 	if (size != epd_frame_table[par->dt].wfm_size) {
190 		dev_err(dev, "Error: unexpected size %Zd != %d\n", size,
191 					epd_frame_table[par->dt].wfm_size);
192 		return -EINVAL;
193 	}
194 
195 	wfm_hdr = (struct waveform_hdr *) mem;
196 
197 	if (wfm_hdr->fvsn != 1) {
198 		dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
199 		return -EINVAL;
200 	}
201 	if (wfm_hdr->luts != 0) {
202 		dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
203 		return -EINVAL;
204 	}
205 	cksum = calc_cksum(32, 47, mem);
206 	if (cksum != wfm_hdr->wfm_cs) {
207 		dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
208 					wfm_hdr->wfm_cs);
209 		return -EINVAL;
210 	}
211 	wfm_hdr->mc += 1;
212 	wfm_hdr->trc += 1;
213 	for (i = 0; i < 5; i++) {
214 		if (*(wfm_hdr->stuff2a + i) != 0) {
215 			dev_err(dev, "Error: unexpected value in padding\n");
216 			return -EINVAL;
217 		}
218 	}
219 
220 	/* calculating trn. trn is something used to index into
221 	the waveform. presumably selecting the right one for the
222 	desired temperature. it works out the offset of the first
223 	v that exceeds the specified temperature */
224 	if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size)
225 		return -EINVAL;
226 
227 	for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) {
228 		if (mem[i] > t) {
229 			trn = i - sizeof(*wfm_hdr) - 1;
230 			break;
231 		}
232 	}
233 
234 	/* check temperature range table checksum */
235 	cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
236 	if (cksum_idx > size)
237 		return -EINVAL;
238 	cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
239 	if (cksum != mem[cksum_idx]) {
240 		dev_err(dev, "Error: bad temperature range table cksum"
241 				" %x != %x\n", cksum, mem[cksum_idx]);
242 		return -EINVAL;
243 	}
244 
245 	/* check waveform mode table address checksum */
246 	wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
247 	cksum_idx = wmta + m*4 + 3;
248 	if (cksum_idx > size)
249 		return -EINVAL;
250 	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
251 	if (cksum != mem[cksum_idx]) {
252 		dev_err(dev, "Error: bad mode table address cksum"
253 				" %x != %x\n", cksum, mem[cksum_idx]);
254 		return -EINVAL;
255 	}
256 
257 	/* check waveform temperature table address checksum */
258 	tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
259 	cksum_idx = tta + trn*4 + 3;
260 	if (cksum_idx > size)
261 		return -EINVAL;
262 	cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
263 	if (cksum != mem[cksum_idx]) {
264 		dev_err(dev, "Error: bad temperature table address cksum"
265 			" %x != %x\n", cksum, mem[cksum_idx]);
266 		return -EINVAL;
267 	}
268 
269 	/* here we do the real work of putting the waveform into the
270 	metromem buffer. this does runlength decoding of the waveform */
271 	wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
272 	owfm_idx = wfm_idx;
273 	if (wfm_idx > size)
274 		return -EINVAL;
275 	while (wfm_idx < size) {
276 		unsigned char rl;
277 		v = mem[wfm_idx++];
278 		if (v == wfm_hdr->swtb) {
279 			while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
280 				wfm_idx < size)
281 				metromem[mem_idx++] = v;
282 
283 			continue;
284 		}
285 
286 		if (v == wfm_hdr->endb)
287 			break;
288 
289 		rl = mem[wfm_idx++];
290 		for (i = 0; i <= rl; i++)
291 			metromem[mem_idx++] = v;
292 	}
293 
294 	cksum_idx = wfm_idx;
295 	if (cksum_idx > size)
296 		return -EINVAL;
297 	cksum = calc_cksum(owfm_idx, cksum_idx, mem);
298 	if (cksum != mem[cksum_idx]) {
299 		dev_err(dev, "Error: bad waveform data cksum"
300 				" %x != %x\n", cksum, mem[cksum_idx]);
301 		return -EINVAL;
302 	}
303 	par->frame_count = (mem_idx/64);
304 
305 	return 0;
306 }
307 
308 static int metronome_display_cmd(struct metronomefb_par *par)
309 {
310 	int i;
311 	u16 cs;
312 	u16 opcode;
313 	static u8 borderval;
314 
315 	/* setup display command
316 	we can't immediately set the opcode since the controller
317 	will try parse the command before we've set it all up
318 	so we just set cs here and set the opcode at the end */
319 
320 	if (par->metromem_cmd->opcode == 0xCC40)
321 		opcode = cs = 0xCC41;
322 	else
323 		opcode = cs = 0xCC40;
324 
325 	/* set the args ( 2 bytes ) for display */
326 	i = 0;
327 	par->metromem_cmd->args[i] = 	1 << 3 /* border update */
328 					| ((borderval++ % 4) & 0x0F) << 4
329 					| (par->frame_count - 1) << 8;
330 	cs += par->metromem_cmd->args[i++];
331 
332 	/* the rest are 0 */
333 	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
334 
335 	par->metromem_cmd->csum = cs;
336 	par->metromem_cmd->opcode = opcode; /* display cmd */
337 
338 	return par->board->met_wait_event_intr(par);
339 }
340 
341 static int metronome_powerup_cmd(struct metronomefb_par *par)
342 {
343 	int i;
344 	u16 cs;
345 
346 	/* setup power up command */
347 	par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
348 	cs = par->metromem_cmd->opcode;
349 
350 	/* set pwr1,2,3 to 1024 */
351 	for (i = 0; i < 3; i++) {
352 		par->metromem_cmd->args[i] = 1024;
353 		cs += par->metromem_cmd->args[i];
354 	}
355 
356 	/* the rest are 0 */
357 	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
358 
359 	par->metromem_cmd->csum = cs;
360 
361 	msleep(1);
362 	par->board->set_rst(par, 1);
363 
364 	msleep(1);
365 	par->board->set_stdby(par, 1);
366 
367 	return par->board->met_wait_event(par);
368 }
369 
370 static int metronome_config_cmd(struct metronomefb_par *par)
371 {
372 	/* setup config command
373 	we can't immediately set the opcode since the controller
374 	will try parse the command before we've set it all up */
375 
376 	memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
377 		sizeof(epd_frame_table[par->dt].config));
378 	/* the rest are 0 */
379 	memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
380 
381 	par->metromem_cmd->csum = 0xCC10;
382 	par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
383 	par->metromem_cmd->opcode = 0xCC10; /* config cmd */
384 
385 	return par->board->met_wait_event(par);
386 }
387 
388 static int metronome_init_cmd(struct metronomefb_par *par)
389 {
390 	int i;
391 	u16 cs;
392 
393 	/* setup init command
394 	we can't immediately set the opcode since the controller
395 	will try parse the command before we've set it all up
396 	so we just set cs here and set the opcode at the end */
397 
398 	cs = 0xCC20;
399 
400 	/* set the args ( 2 bytes ) for init */
401 	i = 0;
402 	par->metromem_cmd->args[i] = 0;
403 	cs += par->metromem_cmd->args[i++];
404 
405 	/* the rest are 0 */
406 	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
407 
408 	par->metromem_cmd->csum = cs;
409 	par->metromem_cmd->opcode = 0xCC20; /* init cmd */
410 
411 	return par->board->met_wait_event(par);
412 }
413 
414 static int metronome_init_regs(struct metronomefb_par *par)
415 {
416 	int res;
417 
418 	res = par->board->setup_io(par);
419 	if (res)
420 		return res;
421 
422 	res = metronome_powerup_cmd(par);
423 	if (res)
424 		return res;
425 
426 	res = metronome_config_cmd(par);
427 	if (res)
428 		return res;
429 
430 	res = metronome_init_cmd(par);
431 
432 	return res;
433 }
434 
435 static void metronomefb_dpy_update(struct metronomefb_par *par)
436 {
437 	int fbsize;
438 	u16 cksum;
439 	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
440 
441 	fbsize = par->info->fix.smem_len;
442 	/* copy from vm to metromem */
443 	memcpy(par->metromem_img, buf, fbsize);
444 
445 	cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
446 	*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
447 	metronome_display_cmd(par);
448 }
449 
450 static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
451 {
452 	int i;
453 	u16 csum = 0;
454 	u16 *buf = (u16 __force *)(par->info->screen_base + index);
455 	u16 *img = (u16 *)(par->metromem_img + index);
456 
457 	/* swizzle from vm to metromem and recalc cksum at the same time*/
458 	for (i = 0; i < PAGE_SIZE/2; i++) {
459 		*(img + i) = (buf[i] << 5) & 0xE0E0;
460 		csum += *(img + i);
461 	}
462 	return csum;
463 }
464 
465 /* this is called back from the deferred io workqueue */
466 static void metronomefb_dpy_deferred_io(struct fb_info *info,
467 				struct list_head *pagelist)
468 {
469 	u16 cksum;
470 	struct page *cur;
471 	struct fb_deferred_io *fbdefio = info->fbdefio;
472 	struct metronomefb_par *par = info->par;
473 
474 	/* walk the written page list and swizzle the data */
475 	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
476 		cksum = metronomefb_dpy_update_page(par,
477 					(cur->index << PAGE_SHIFT));
478 		par->metromem_img_csum -= par->csum_table[cur->index];
479 		par->csum_table[cur->index] = cksum;
480 		par->metromem_img_csum += cksum;
481 	}
482 
483 	metronome_display_cmd(par);
484 }
485 
486 static void metronomefb_fillrect(struct fb_info *info,
487 				   const struct fb_fillrect *rect)
488 {
489 	struct metronomefb_par *par = info->par;
490 
491 	sys_fillrect(info, rect);
492 	metronomefb_dpy_update(par);
493 }
494 
495 static void metronomefb_copyarea(struct fb_info *info,
496 				   const struct fb_copyarea *area)
497 {
498 	struct metronomefb_par *par = info->par;
499 
500 	sys_copyarea(info, area);
501 	metronomefb_dpy_update(par);
502 }
503 
504 static void metronomefb_imageblit(struct fb_info *info,
505 				const struct fb_image *image)
506 {
507 	struct metronomefb_par *par = info->par;
508 
509 	sys_imageblit(info, image);
510 	metronomefb_dpy_update(par);
511 }
512 
513 /*
514  * this is the slow path from userspace. they can seek and write to
515  * the fb. it is based on fb_sys_write
516  */
517 static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
518 				size_t count, loff_t *ppos)
519 {
520 	struct metronomefb_par *par = info->par;
521 	unsigned long p = *ppos;
522 	void *dst;
523 	int err = 0;
524 	unsigned long total_size;
525 
526 	if (info->state != FBINFO_STATE_RUNNING)
527 		return -EPERM;
528 
529 	total_size = info->fix.smem_len;
530 
531 	if (p > total_size)
532 		return -EFBIG;
533 
534 	if (count > total_size) {
535 		err = -EFBIG;
536 		count = total_size;
537 	}
538 
539 	if (count + p > total_size) {
540 		if (!err)
541 			err = -ENOSPC;
542 
543 		count = total_size - p;
544 	}
545 
546 	dst = (void __force *)(info->screen_base + p);
547 
548 	if (copy_from_user(dst, buf, count))
549 		err = -EFAULT;
550 
551 	if  (!err)
552 		*ppos += count;
553 
554 	metronomefb_dpy_update(par);
555 
556 	return (err) ? err : count;
557 }
558 
559 static struct fb_ops metronomefb_ops = {
560 	.owner		= THIS_MODULE,
561 	.fb_write	= metronomefb_write,
562 	.fb_fillrect	= metronomefb_fillrect,
563 	.fb_copyarea	= metronomefb_copyarea,
564 	.fb_imageblit	= metronomefb_imageblit,
565 };
566 
567 static struct fb_deferred_io metronomefb_defio = {
568 	.delay		= HZ,
569 	.deferred_io	= metronomefb_dpy_deferred_io,
570 };
571 
572 static int metronomefb_probe(struct platform_device *dev)
573 {
574 	struct fb_info *info;
575 	struct metronome_board *board;
576 	int retval = -ENOMEM;
577 	int videomemorysize;
578 	unsigned char *videomemory;
579 	struct metronomefb_par *par;
580 	const struct firmware *fw_entry;
581 	int i;
582 	int panel_type;
583 	int fw, fh;
584 	int epd_dt_index;
585 
586 	/* pick up board specific routines */
587 	board = dev->dev.platform_data;
588 	if (!board)
589 		return -EINVAL;
590 
591 	/* try to count device specific driver, if can't, platform recalls */
592 	if (!try_module_get(board->owner))
593 		return -ENODEV;
594 
595 	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
596 	if (!info)
597 		goto err;
598 
599 	/* we have two blocks of memory.
600 	info->screen_base which is vm, and is the fb used by apps.
601 	par->metromem which is physically contiguous memory and
602 	contains the display controller commands, waveform,
603 	processed image data and padding. this is the data pulled
604 	by the device's LCD controller and pushed to Metronome.
605 	the metromem memory is allocated by the board driver and
606 	is provided to us */
607 
608 	panel_type = board->get_panel_type();
609 	switch (panel_type) {
610 	case 6:
611 		epd_dt_index = 0;
612 		break;
613 	case 8:
614 		epd_dt_index = 1;
615 		break;
616 	case 97:
617 		epd_dt_index = 2;
618 		break;
619 	default:
620 		dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
621 		epd_dt_index = 0;
622 		break;
623 	}
624 
625 	fw = epd_frame_table[epd_dt_index].fw;
626 	fh = epd_frame_table[epd_dt_index].fh;
627 
628 	/* we need to add a spare page because our csum caching scheme walks
629 	 * to the end of the page */
630 	videomemorysize = PAGE_SIZE + (fw * fh);
631 	videomemory = vzalloc(videomemorysize);
632 	if (!videomemory)
633 		goto err_fb_rel;
634 
635 	info->screen_base = (char __force __iomem *)videomemory;
636 	info->fbops = &metronomefb_ops;
637 
638 	metronomefb_fix.line_length = fw;
639 	metronomefb_var.xres = fw;
640 	metronomefb_var.yres = fh;
641 	metronomefb_var.xres_virtual = fw;
642 	metronomefb_var.yres_virtual = fh;
643 	info->var = metronomefb_var;
644 	info->fix = metronomefb_fix;
645 	info->fix.smem_len = videomemorysize;
646 	par = info->par;
647 	par->info = info;
648 	par->board = board;
649 	par->dt = epd_dt_index;
650 	init_waitqueue_head(&par->waitq);
651 
652 	/* this table caches per page csum values. */
653 	par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
654 	if (!par->csum_table)
655 		goto err_vfree;
656 
657 	/* the physical framebuffer that we use is setup by
658 	 * the platform device driver. It will provide us
659 	 * with cmd, wfm and image memory in a contiguous area. */
660 	retval = board->setup_fb(par);
661 	if (retval) {
662 		dev_err(&dev->dev, "Failed to setup fb\n");
663 		goto err_csum_table;
664 	}
665 
666 	/* after this point we should have a framebuffer */
667 	if ((!par->metromem_wfm) ||  (!par->metromem_img) ||
668 		(!par->metromem_dma)) {
669 		dev_err(&dev->dev, "fb access failure\n");
670 		retval = -EINVAL;
671 		goto err_csum_table;
672 	}
673 
674 	info->fix.smem_start = par->metromem_dma;
675 
676 	/* load the waveform in. assume mode 3, temp 31 for now
677 		a) request the waveform file from userspace
678 		b) process waveform and decode into metromem */
679 	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
680 	if (retval < 0) {
681 		dev_err(&dev->dev, "Failed to get waveform\n");
682 		goto err_csum_table;
683 	}
684 
685 	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
686 				par);
687 	release_firmware(fw_entry);
688 	if (retval < 0) {
689 		dev_err(&dev->dev, "Failed processing waveform\n");
690 		goto err_csum_table;
691 	}
692 
693 	retval = board->setup_irq(info);
694 	if (retval)
695 		goto err_csum_table;
696 
697 	retval = metronome_init_regs(par);
698 	if (retval < 0)
699 		goto err_free_irq;
700 
701 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
702 
703 	info->fbdefio = &metronomefb_defio;
704 	fb_deferred_io_init(info);
705 
706 	retval = fb_alloc_cmap(&info->cmap, 8, 0);
707 	if (retval < 0) {
708 		dev_err(&dev->dev, "Failed to allocate colormap\n");
709 		goto err_free_irq;
710 	}
711 
712 	/* set cmap */
713 	for (i = 0; i < 8; i++)
714 		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16;
715 	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
716 	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
717 
718 	retval = register_framebuffer(info);
719 	if (retval < 0)
720 		goto err_cmap;
721 
722 	platform_set_drvdata(dev, info);
723 
724 	dev_dbg(&dev->dev,
725 		"fb%d: Metronome frame buffer device, using %dK of video"
726 		" memory\n", info->node, videomemorysize >> 10);
727 
728 	return 0;
729 
730 err_cmap:
731 	fb_dealloc_cmap(&info->cmap);
732 err_free_irq:
733 	board->cleanup(par);
734 err_csum_table:
735 	vfree(par->csum_table);
736 err_vfree:
737 	vfree(videomemory);
738 err_fb_rel:
739 	framebuffer_release(info);
740 err:
741 	module_put(board->owner);
742 	return retval;
743 }
744 
745 static int metronomefb_remove(struct platform_device *dev)
746 {
747 	struct fb_info *info = platform_get_drvdata(dev);
748 
749 	if (info) {
750 		struct metronomefb_par *par = info->par;
751 
752 		unregister_framebuffer(info);
753 		fb_deferred_io_cleanup(info);
754 		fb_dealloc_cmap(&info->cmap);
755 		par->board->cleanup(par);
756 		vfree(par->csum_table);
757 		vfree((void __force *)info->screen_base);
758 		module_put(par->board->owner);
759 		dev_dbg(&dev->dev, "calling release\n");
760 		framebuffer_release(info);
761 	}
762 	return 0;
763 }
764 
765 static struct platform_driver metronomefb_driver = {
766 	.probe	= metronomefb_probe,
767 	.remove = metronomefb_remove,
768 	.driver	= {
769 		.name	= "metronomefb",
770 	},
771 };
772 module_platform_driver(metronomefb_driver);
773 
774 module_param(user_wfm_size, uint, 0);
775 MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
776 
777 MODULE_DESCRIPTION("fbdev driver for Metronome controller");
778 MODULE_AUTHOR("Jaya Kumar");
779 MODULE_LICENSE("GPL");
780