xref: /linux/drivers/video/fbdev/metronomefb.c (revision 0be3ff0c)
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. https://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(&par->metromem_cmd->args[i], 0,
358 	       (ARRAY_SIZE(par->metromem_cmd->args) - i) * 2);
359 
360 	par->metromem_cmd->csum = cs;
361 
362 	msleep(1);
363 	par->board->set_rst(par, 1);
364 
365 	msleep(1);
366 	par->board->set_stdby(par, 1);
367 
368 	return par->board->met_wait_event(par);
369 }
370 
371 static int metronome_config_cmd(struct metronomefb_par *par)
372 {
373 	/* setup config command
374 	we can't immediately set the opcode since the controller
375 	will try parse the command before we've set it all up */
376 
377 	memcpy(par->metromem_cmd->args, epd_frame_table[par->dt].config,
378 		sizeof(epd_frame_table[par->dt].config));
379 	/* the rest are 0 */
380 	memset(&par->metromem_cmd->args[4], 0,
381 	       (ARRAY_SIZE(par->metromem_cmd->args) - 4) * 2);
382 
383 	par->metromem_cmd->csum = 0xCC10;
384 	par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
385 	par->metromem_cmd->opcode = 0xCC10; /* config cmd */
386 
387 	return par->board->met_wait_event(par);
388 }
389 
390 static int metronome_init_cmd(struct metronomefb_par *par)
391 {
392 	int i;
393 	u16 cs;
394 
395 	/* setup init command
396 	we can't immediately set the opcode since the controller
397 	will try parse the command before we've set it all up
398 	so we just set cs here and set the opcode at the end */
399 
400 	cs = 0xCC20;
401 
402 	/* set the args ( 2 bytes ) for init */
403 	i = 0;
404 	par->metromem_cmd->args[i] = 0;
405 	cs += par->metromem_cmd->args[i++];
406 
407 	/* the rest are 0 */
408 	memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
409 
410 	par->metromem_cmd->csum = cs;
411 	par->metromem_cmd->opcode = 0xCC20; /* init cmd */
412 
413 	return par->board->met_wait_event(par);
414 }
415 
416 static int metronome_init_regs(struct metronomefb_par *par)
417 {
418 	int res;
419 
420 	res = par->board->setup_io(par);
421 	if (res)
422 		return res;
423 
424 	res = metronome_powerup_cmd(par);
425 	if (res)
426 		return res;
427 
428 	res = metronome_config_cmd(par);
429 	if (res)
430 		return res;
431 
432 	res = metronome_init_cmd(par);
433 
434 	return res;
435 }
436 
437 static void metronomefb_dpy_update(struct metronomefb_par *par)
438 {
439 	int fbsize;
440 	u16 cksum;
441 	unsigned char *buf = (unsigned char __force *)par->info->screen_base;
442 
443 	fbsize = par->info->fix.smem_len;
444 	/* copy from vm to metromem */
445 	memcpy(par->metromem_img, buf, fbsize);
446 
447 	cksum = calc_img_cksum((u16 *) par->metromem_img, fbsize/2);
448 	*((u16 *)(par->metromem_img) + fbsize/2) = cksum;
449 	metronome_display_cmd(par);
450 }
451 
452 static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
453 {
454 	int i;
455 	u16 csum = 0;
456 	u16 *buf = (u16 __force *)(par->info->screen_base + index);
457 	u16 *img = (u16 *)(par->metromem_img + index);
458 
459 	/* swizzle from vm to metromem and recalc cksum at the same time*/
460 	for (i = 0; i < PAGE_SIZE/2; i++) {
461 		*(img + i) = (buf[i] << 5) & 0xE0E0;
462 		csum += *(img + i);
463 	}
464 	return csum;
465 }
466 
467 /* this is called back from the deferred io workqueue */
468 static void metronomefb_dpy_deferred_io(struct fb_info *info,
469 				struct list_head *pagelist)
470 {
471 	u16 cksum;
472 	struct page *cur;
473 	struct fb_deferred_io *fbdefio = info->fbdefio;
474 	struct metronomefb_par *par = info->par;
475 
476 	/* walk the written page list and swizzle the data */
477 	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
478 		cksum = metronomefb_dpy_update_page(par,
479 					(cur->index << PAGE_SHIFT));
480 		par->metromem_img_csum -= par->csum_table[cur->index];
481 		par->csum_table[cur->index] = cksum;
482 		par->metromem_img_csum += cksum;
483 	}
484 
485 	metronome_display_cmd(par);
486 }
487 
488 static void metronomefb_fillrect(struct fb_info *info,
489 				   const struct fb_fillrect *rect)
490 {
491 	struct metronomefb_par *par = info->par;
492 
493 	sys_fillrect(info, rect);
494 	metronomefb_dpy_update(par);
495 }
496 
497 static void metronomefb_copyarea(struct fb_info *info,
498 				   const struct fb_copyarea *area)
499 {
500 	struct metronomefb_par *par = info->par;
501 
502 	sys_copyarea(info, area);
503 	metronomefb_dpy_update(par);
504 }
505 
506 static void metronomefb_imageblit(struct fb_info *info,
507 				const struct fb_image *image)
508 {
509 	struct metronomefb_par *par = info->par;
510 
511 	sys_imageblit(info, image);
512 	metronomefb_dpy_update(par);
513 }
514 
515 /*
516  * this is the slow path from userspace. they can seek and write to
517  * the fb. it is based on fb_sys_write
518  */
519 static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
520 				size_t count, loff_t *ppos)
521 {
522 	struct metronomefb_par *par = info->par;
523 	unsigned long p = *ppos;
524 	void *dst;
525 	int err = 0;
526 	unsigned long total_size;
527 
528 	if (info->state != FBINFO_STATE_RUNNING)
529 		return -EPERM;
530 
531 	total_size = info->fix.smem_len;
532 
533 	if (p > total_size)
534 		return -EFBIG;
535 
536 	if (count > total_size) {
537 		err = -EFBIG;
538 		count = total_size;
539 	}
540 
541 	if (count + p > total_size) {
542 		if (!err)
543 			err = -ENOSPC;
544 
545 		count = total_size - p;
546 	}
547 
548 	dst = (void __force *)(info->screen_base + p);
549 
550 	if (copy_from_user(dst, buf, count))
551 		err = -EFAULT;
552 
553 	if  (!err)
554 		*ppos += count;
555 
556 	metronomefb_dpy_update(par);
557 
558 	return (err) ? err : count;
559 }
560 
561 static const struct fb_ops metronomefb_ops = {
562 	.owner		= THIS_MODULE,
563 	.fb_write	= metronomefb_write,
564 	.fb_fillrect	= metronomefb_fillrect,
565 	.fb_copyarea	= metronomefb_copyarea,
566 	.fb_imageblit	= metronomefb_imageblit,
567 };
568 
569 static struct fb_deferred_io metronomefb_defio = {
570 	.delay		= HZ,
571 	.sort_pagelist	= true,
572 	.deferred_io	= metronomefb_dpy_deferred_io,
573 };
574 
575 static int metronomefb_probe(struct platform_device *dev)
576 {
577 	struct fb_info *info;
578 	struct metronome_board *board;
579 	int retval = -ENOMEM;
580 	int videomemorysize;
581 	unsigned char *videomemory;
582 	struct metronomefb_par *par;
583 	const struct firmware *fw_entry;
584 	int i;
585 	int panel_type;
586 	int fw, fh;
587 	int epd_dt_index;
588 
589 	/* pick up board specific routines */
590 	board = dev->dev.platform_data;
591 	if (!board)
592 		return -EINVAL;
593 
594 	/* try to count device specific driver, if can't, platform recalls */
595 	if (!try_module_get(board->owner))
596 		return -ENODEV;
597 
598 	info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
599 	if (!info)
600 		goto err;
601 
602 	/* we have two blocks of memory.
603 	info->screen_base which is vm, and is the fb used by apps.
604 	par->metromem which is physically contiguous memory and
605 	contains the display controller commands, waveform,
606 	processed image data and padding. this is the data pulled
607 	by the device's LCD controller and pushed to Metronome.
608 	the metromem memory is allocated by the board driver and
609 	is provided to us */
610 
611 	panel_type = board->get_panel_type();
612 	switch (panel_type) {
613 	case 6:
614 		epd_dt_index = 0;
615 		break;
616 	case 8:
617 		epd_dt_index = 1;
618 		break;
619 	case 97:
620 		epd_dt_index = 2;
621 		break;
622 	default:
623 		dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
624 		epd_dt_index = 0;
625 		break;
626 	}
627 
628 	fw = epd_frame_table[epd_dt_index].fw;
629 	fh = epd_frame_table[epd_dt_index].fh;
630 
631 	/* we need to add a spare page because our csum caching scheme walks
632 	 * to the end of the page */
633 	videomemorysize = PAGE_SIZE + (fw * fh);
634 	videomemory = vzalloc(videomemorysize);
635 	if (!videomemory)
636 		goto err_fb_rel;
637 
638 	info->screen_base = (char __force __iomem *)videomemory;
639 	info->fbops = &metronomefb_ops;
640 
641 	metronomefb_fix.line_length = fw;
642 	metronomefb_var.xres = fw;
643 	metronomefb_var.yres = fh;
644 	metronomefb_var.xres_virtual = fw;
645 	metronomefb_var.yres_virtual = fh;
646 	info->var = metronomefb_var;
647 	info->fix = metronomefb_fix;
648 	info->fix.smem_len = videomemorysize;
649 	par = info->par;
650 	par->info = info;
651 	par->board = board;
652 	par->dt = epd_dt_index;
653 	init_waitqueue_head(&par->waitq);
654 
655 	/* this table caches per page csum values. */
656 	par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
657 	if (!par->csum_table)
658 		goto err_vfree;
659 
660 	/* the physical framebuffer that we use is setup by
661 	 * the platform device driver. It will provide us
662 	 * with cmd, wfm and image memory in a contiguous area. */
663 	retval = board->setup_fb(par);
664 	if (retval) {
665 		dev_err(&dev->dev, "Failed to setup fb\n");
666 		goto err_csum_table;
667 	}
668 
669 	/* after this point we should have a framebuffer */
670 	if ((!par->metromem_wfm) ||  (!par->metromem_img) ||
671 		(!par->metromem_dma)) {
672 		dev_err(&dev->dev, "fb access failure\n");
673 		retval = -EINVAL;
674 		goto err_csum_table;
675 	}
676 
677 	info->fix.smem_start = par->metromem_dma;
678 
679 	/* load the waveform in. assume mode 3, temp 31 for now
680 		a) request the waveform file from userspace
681 		b) process waveform and decode into metromem */
682 	retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
683 	if (retval < 0) {
684 		dev_err(&dev->dev, "Failed to get waveform\n");
685 		goto err_csum_table;
686 	}
687 
688 	retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, 3, 31,
689 				par);
690 	release_firmware(fw_entry);
691 	if (retval < 0) {
692 		dev_err(&dev->dev, "Failed processing waveform\n");
693 		goto err_csum_table;
694 	}
695 
696 	retval = board->setup_irq(info);
697 	if (retval)
698 		goto err_csum_table;
699 
700 	retval = metronome_init_regs(par);
701 	if (retval < 0)
702 		goto err_free_irq;
703 
704 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
705 
706 	info->fbdefio = &metronomefb_defio;
707 	fb_deferred_io_init(info);
708 
709 	retval = fb_alloc_cmap(&info->cmap, 8, 0);
710 	if (retval < 0) {
711 		dev_err(&dev->dev, "Failed to allocate colormap\n");
712 		goto err_free_irq;
713 	}
714 
715 	/* set cmap */
716 	for (i = 0; i < 8; i++)
717 		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16;
718 	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
719 	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
720 
721 	retval = register_framebuffer(info);
722 	if (retval < 0)
723 		goto err_cmap;
724 
725 	platform_set_drvdata(dev, info);
726 
727 	dev_dbg(&dev->dev,
728 		"fb%d: Metronome frame buffer device, using %dK of video"
729 		" memory\n", info->node, videomemorysize >> 10);
730 
731 	return 0;
732 
733 err_cmap:
734 	fb_dealloc_cmap(&info->cmap);
735 err_free_irq:
736 	board->cleanup(par);
737 err_csum_table:
738 	vfree(par->csum_table);
739 err_vfree:
740 	vfree(videomemory);
741 err_fb_rel:
742 	framebuffer_release(info);
743 err:
744 	module_put(board->owner);
745 	return retval;
746 }
747 
748 static int metronomefb_remove(struct platform_device *dev)
749 {
750 	struct fb_info *info = platform_get_drvdata(dev);
751 
752 	if (info) {
753 		struct metronomefb_par *par = info->par;
754 
755 		unregister_framebuffer(info);
756 		fb_deferred_io_cleanup(info);
757 		fb_dealloc_cmap(&info->cmap);
758 		par->board->cleanup(par);
759 		vfree(par->csum_table);
760 		vfree((void __force *)info->screen_base);
761 		module_put(par->board->owner);
762 		dev_dbg(&dev->dev, "calling release\n");
763 		framebuffer_release(info);
764 	}
765 	return 0;
766 }
767 
768 static struct platform_driver metronomefb_driver = {
769 	.probe	= metronomefb_probe,
770 	.remove = metronomefb_remove,
771 	.driver	= {
772 		.name	= "metronomefb",
773 	},
774 };
775 module_platform_driver(metronomefb_driver);
776 
777 module_param(user_wfm_size, uint, 0);
778 MODULE_PARM_DESC(user_wfm_size, "Set custom waveform size");
779 
780 MODULE_DESCRIPTION("fbdev driver for Metronome controller");
781 MODULE_AUTHOR("Jaya Kumar");
782 MODULE_LICENSE("GPL");
783