2 * linux/drivers/video/metronomefb.c -- FB driver for Metronome controller
4 * Copyright (C) 2008, Jaya Kumar
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
10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
12 * This work was made possible by help and equipment support from E-Ink
13 * Corporation. http://support.eink.com/community
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
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/errno.h>
24 #include <linux/string.h>
26 #include <linux/slab.h>
27 #include <linux/vmalloc.h>
28 #include <linux/delay.h>
29 #include <linux/interrupt.h>
31 #include <linux/init.h>
32 #include <linux/platform_device.h>
33 #include <linux/list.h>
34 #include <linux/firmware.h>
35 #include <linux/dma-mapping.h>
36 #include <linux/uaccess.h>
37 #include <linux/irq.h>
39 #include <video/metronomefb.h>
41 #include <asm/unaligned.h>
46 #define DPRINTK(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
48 #define DPRINTK(f, a...)
52 /* Display specific information */
56 /* frame differs from image. frame includes non-visible pixels */
58 int fw; /* frame width */
59 int fh; /* frame height */
62 static struct epd_frame epd_frame_table[] = {
69 static struct fb_fix_screeninfo metronomefb_fix __devinitdata = {
71 .type = FB_TYPE_PACKED_PIXELS,
72 .visual = FB_VISUAL_STATIC_PSEUDOCOLOR,
77 .accel = FB_ACCEL_NONE,
80 static struct fb_var_screeninfo metronomefb_var __devinitdata = {
83 .xres_virtual = DPY_W,
84 .yres_virtual = DPY_H,
91 .transp = { 0, 0, 0 },
94 /* the waveform structure that is coming from userspace firmware */
112 } __attribute__ ((packed));
114 /* main metronomefb functions */
115 static u8 calc_cksum(int start, int end, u8 *mem)
120 for (i = start; i < end; i++)
126 static u16 calc_img_cksum(u16 *start, int length)
136 /* here we decode the incoming waveform file and populate metromem */
137 #define EXP_WFORM_SIZE 47001
138 static int load_waveform(u8 *mem, size_t size, u8 *metromem, int m, int t,
148 int wfm_idx, owfm_idx;
150 struct waveform_hdr *wfm_hdr;
152 if (size != EXP_WFORM_SIZE) {
153 printk(KERN_ERR "Error: unexpected size %d != %d\n", size,
158 wfm_hdr = (struct waveform_hdr *) mem;
160 if (wfm_hdr->fvsn != 1) {
161 printk(KERN_ERR "Error: bad fvsn %x\n", wfm_hdr->fvsn);
164 if (wfm_hdr->luts != 0) {
165 printk(KERN_ERR "Error: bad luts %x\n", wfm_hdr->luts);
168 cksum = calc_cksum(32, 47, mem);
169 if (cksum != wfm_hdr->wfm_cs) {
170 printk(KERN_ERR "Error: bad cksum %x != %x\n", cksum,
176 for (i = 0; i < 5; i++) {
177 if (*(wfm_hdr->stuff2a + i) != 0) {
178 printk(KERN_ERR "Error: unexpected value in padding\n");
183 /* calculating trn. trn is something used to index into
184 the waveform. presumably selecting the right one for the
185 desired temperature. it works out the offset of the first
186 v that exceeds the specified temperature */
187 if ((sizeof(*wfm_hdr) + wfm_hdr->trc) > size)
190 for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + wfm_hdr->trc; i++) {
192 trn = i - sizeof(*wfm_hdr) - 1;
197 /* check temperature range table checksum */
198 cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
199 if (cksum_idx > size)
201 cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
202 if (cksum != mem[cksum_idx]) {
203 printk(KERN_ERR "Error: bad temperature range table cksum"
204 " %x != %x\n", cksum, mem[cksum_idx]);
208 /* check waveform mode table address checksum */
209 wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
210 cksum_idx = wmta + m*4 + 3;
211 if (cksum_idx > size)
213 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
214 if (cksum != mem[cksum_idx]) {
215 printk(KERN_ERR "Error: bad mode table address cksum"
216 " %x != %x\n", cksum, mem[cksum_idx]);
220 /* check waveform temperature table address checksum */
221 tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
222 cksum_idx = tta + trn*4 + 3;
223 if (cksum_idx > size)
225 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
226 if (cksum != mem[cksum_idx]) {
227 printk(KERN_ERR "Error: bad temperature table address cksum"
228 " %x != %x\n", cksum, mem[cksum_idx]);
232 /* here we do the real work of putting the waveform into the
233 metromem buffer. this does runlength decoding of the waveform */
234 wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
238 while (wfm_idx < size) {
241 if (v == wfm_hdr->swtb) {
242 while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
244 metromem[mem_idx++] = v;
249 if (v == wfm_hdr->endb)
253 for (i = 0; i <= rl; i++)
254 metromem[mem_idx++] = v;
258 if (cksum_idx > size)
260 cksum = calc_cksum(owfm_idx, cksum_idx, mem);
261 if (cksum != mem[cksum_idx]) {
262 printk(KERN_ERR "Error: bad waveform data cksum"
263 " %x != %x\n", cksum, mem[cksum_idx]);
266 *frame_count = (mem_idx/64);
271 static int metronome_display_cmd(struct metronomefb_par *par)
279 /* setup display command
280 we can't immediately set the opcode since the controller
281 will try parse the command before we've set it all up
282 so we just set cs here and set the opcode at the end */
286 if (par->metromem_cmd->opcode == 0xCC40)
287 opcode = cs = 0xCC41;
289 opcode = cs = 0xCC40;
291 /* set the args ( 2 bytes ) for display */
293 par->metromem_cmd->args[i] = 1 << 3 /* border update */
294 | ((borderval++ % 4) & 0x0F) << 4
295 | (par->frame_count - 1) << 8;
296 cs += par->metromem_cmd->args[i++];
299 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
301 par->metromem_cmd->csum = cs;
302 par->metromem_cmd->opcode = opcode; /* display cmd */
304 return par->board->met_wait_event_intr(par);
307 static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
312 /* setup power up command */
313 par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
314 cs = par->metromem_cmd->opcode;
316 /* set pwr1,2,3 to 1024 */
317 for (i = 0; i < 3; i++) {
318 par->metromem_cmd->args[i] = 1024;
319 cs += par->metromem_cmd->args[i];
323 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
325 par->metromem_cmd->csum = cs;
328 par->board->set_rst(par, 1);
331 par->board->set_stdby(par, 1);
333 return par->board->met_wait_event(par);
336 static int __devinit metronome_config_cmd(struct metronomefb_par *par)
341 /* setup config command
342 we can't immediately set the opcode since the controller
343 will try parse the command before we've set it all up
344 so we just set cs here and set the opcode at the end */
348 /* set the 12 args ( 8 bytes ) for config. see spec for meanings */
350 par->metromem_cmd->args[i] = 15 /* sdlew */
353 | 0 << 12 /* sdces */
354 | 0 << 15; /* sdcer */
355 cs += par->metromem_cmd->args[i++];
357 par->metromem_cmd->args[i] = 42 /* gdspl */
360 | 0 << 15; /* gdspp */
361 cs += par->metromem_cmd->args[i++];
363 par->metromem_cmd->args[i] = 18 /* gdspw */
364 | 0 << 15; /* dispc */
365 cs += par->metromem_cmd->args[i++];
367 par->metromem_cmd->args[i] = 599 /* vdlc */
369 | 0 << 12; /* dsic */
370 cs += par->metromem_cmd->args[i++];
373 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
375 par->metromem_cmd->csum = cs;
376 par->metromem_cmd->opcode = 0xCC10; /* config cmd */
378 return par->board->met_wait_event(par);
381 static int __devinit metronome_init_cmd(struct metronomefb_par *par)
386 /* setup init command
387 we can't immediately set the opcode since the controller
388 will try parse the command before we've set it all up
389 so we just set cs here and set the opcode at the end */
393 /* set the args ( 2 bytes ) for init */
395 par->metromem_cmd->args[i] = 0;
396 cs += par->metromem_cmd->args[i++];
399 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
401 par->metromem_cmd->csum = cs;
402 par->metromem_cmd->opcode = 0xCC20; /* init cmd */
404 return par->board->met_wait_event(par);
407 static int __devinit metronome_init_regs(struct metronomefb_par *par)
411 par->board->init_gpio_regs(par);
413 par->board->init_lcdc_regs(par);
415 /* now that lcd is setup, setup dma descriptor */
416 par->board->post_dma_setup(par);
418 res = metronome_powerup_cmd(par);
422 res = metronome_config_cmd(par);
426 res = metronome_init_cmd(par);
431 static void metronomefb_dpy_update(struct metronomefb_par *par)
434 unsigned char *buf = (unsigned char __force *)par->info->screen_base;
436 /* copy from vm to metromem */
437 memcpy(par->metromem_img, buf, DPY_W*DPY_H);
439 cksum = calc_img_cksum((u16 *) par->metromem_img,
440 (epd_frame_table[0].fw * DPY_H)/2);
441 *((u16 *)(par->metromem_img) +
442 (epd_frame_table[0].fw * DPY_H)/2) = cksum;
443 metronome_display_cmd(par);
446 static u16 metronomefb_dpy_update_page(struct metronomefb_par *par, int index)
450 u16 *buf = (u16 __force *)(par->info->screen_base + index);
451 u16 *img = (u16 *)(par->metromem_img + index);
453 /* swizzle from vm to metromem and recalc cksum at the same time*/
454 for (i = 0; i < PAGE_SIZE/2; i++) {
455 *(img + i) = (buf[i] << 5) & 0xE0E0;
461 /* this is called back from the deferred io workqueue */
462 static void metronomefb_dpy_deferred_io(struct fb_info *info,
463 struct list_head *pagelist)
467 struct fb_deferred_io *fbdefio = info->fbdefio;
468 struct metronomefb_par *par = info->par;
470 /* walk the written page list and swizzle the data */
471 list_for_each_entry(cur, &fbdefio->pagelist, lru) {
472 cksum = metronomefb_dpy_update_page(par,
473 (cur->index << PAGE_SHIFT));
474 par->metromem_img_csum -= par->csum_table[cur->index];
475 par->csum_table[cur->index] = cksum;
476 par->metromem_img_csum += cksum;
479 metronome_display_cmd(par);
482 static void metronomefb_fillrect(struct fb_info *info,
483 const struct fb_fillrect *rect)
485 struct metronomefb_par *par = info->par;
487 sys_fillrect(info, rect);
488 metronomefb_dpy_update(par);
491 static void metronomefb_copyarea(struct fb_info *info,
492 const struct fb_copyarea *area)
494 struct metronomefb_par *par = info->par;
496 sys_copyarea(info, area);
497 metronomefb_dpy_update(par);
500 static void metronomefb_imageblit(struct fb_info *info,
501 const struct fb_image *image)
503 struct metronomefb_par *par = info->par;
505 sys_imageblit(info, image);
506 metronomefb_dpy_update(par);
510 * this is the slow path from userspace. they can seek and write to
511 * the fb. it is based on fb_sys_write
513 static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
514 size_t count, loff_t *ppos)
516 struct metronomefb_par *par = info->par;
517 unsigned long p = *ppos;
520 unsigned long total_size;
522 if (info->state != FBINFO_STATE_RUNNING)
525 total_size = info->fix.smem_len;
530 if (count > total_size) {
535 if (count + p > total_size) {
539 count = total_size - p;
542 dst = (void __force *)(info->screen_base + p);
544 if (copy_from_user(dst, buf, count))
550 metronomefb_dpy_update(par);
552 return (err) ? err : count;
555 static struct fb_ops metronomefb_ops = {
556 .owner = THIS_MODULE,
557 .fb_write = metronomefb_write,
558 .fb_fillrect = metronomefb_fillrect,
559 .fb_copyarea = metronomefb_copyarea,
560 .fb_imageblit = metronomefb_imageblit,
563 static struct fb_deferred_io metronomefb_defio = {
565 .deferred_io = metronomefb_dpy_deferred_io,
568 static int __devinit metronomefb_probe(struct platform_device *dev)
570 struct fb_info *info;
571 struct metronome_board *board;
572 int retval = -ENOMEM;
574 unsigned char *videomemory;
575 struct metronomefb_par *par;
576 const struct firmware *fw_entry;
577 int cmd_size, wfm_size, img_size, padding_size, totalsize;
580 /* pick up board specific routines */
581 board = dev->dev.platform_data;
585 /* try to count device specific driver, if can't, platform recalls */
586 if (!try_module_get(board->owner))
589 /* we have two blocks of memory.
590 info->screen_base which is vm, and is the fb used by apps.
591 par->metromem which is physically contiguous memory and
592 contains the display controller commands, waveform,
593 processed image data and padding. this is the data pulled
594 by the device's LCD controller and pushed to Metronome */
596 videomemorysize = (DPY_W*DPY_H);
597 videomemory = vmalloc(videomemorysize);
601 memset(videomemory, 0, videomemorysize);
603 info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
607 info->screen_base = (char __force __iomem *)videomemory;
608 info->fbops = &metronomefb_ops;
610 info->var = metronomefb_var;
611 info->fix = metronomefb_fix;
612 info->fix.smem_len = videomemorysize;
616 init_waitqueue_head(&par->waitq);
618 /* this table caches per page csum values. */
619 par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
620 if (!par->csum_table)
623 /* the metromem buffer is divided as follows:
624 command | CRC | padding
625 16kb waveform data | CRC | padding
627 and an extra 256 bytes for dma descriptors
628 eg: IW=832 IH=622 WS=128
631 cmd_size = 1 * epd_frame_table[0].fw;
632 wfm_size = ((16*1024 + 2 + epd_frame_table[0].fw - 1)
633 / epd_frame_table[0].fw) * epd_frame_table[0].fw;
634 img_size = epd_frame_table[0].fh * epd_frame_table[0].fw;
635 padding_size = 4 * epd_frame_table[0].fw;
636 totalsize = cmd_size + wfm_size + img_size + padding_size;
637 par->metromemsize = PAGE_ALIGN(totalsize + 256);
638 DPRINTK("desired memory size = %d\n", par->metromemsize);
639 dev->dev.coherent_dma_mask = 0xffffffffull;
640 par->metromem = dma_alloc_writecombine(&dev->dev, par->metromemsize,
641 &par->metromem_dma, GFP_KERNEL);
642 if (!par->metromem) {
644 "metronomefb: unable to allocate dma buffer\n");
648 info->fix.smem_start = par->metromem_dma;
649 par->metromem_cmd = (struct metromem_cmd *) par->metromem;
650 par->metromem_wfm = par->metromem + cmd_size;
651 par->metromem_img = par->metromem + cmd_size + wfm_size;
652 par->metromem_img_csum = (u16 *) (par->metromem_img +
653 (epd_frame_table[0].fw * DPY_H));
654 DPRINTK("img offset=0x%x\n", cmd_size + wfm_size);
655 par->metromem_desc = (struct metromem_desc *) (par->metromem + cmd_size
656 + wfm_size + img_size + padding_size);
657 par->metromem_desc_dma = par->metromem_dma + cmd_size + wfm_size
658 + img_size + padding_size;
660 /* load the waveform in. assume mode 3, temp 31 for now
661 a) request the waveform file from userspace
662 b) process waveform and decode into metromem */
663 retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
665 printk(KERN_ERR "metronomefb: couldn't get waveform\n");
669 retval = load_waveform((u8 *) fw_entry->data, fw_entry->size,
670 par->metromem_wfm, 3, 31, &par->frame_count);
671 release_firmware(fw_entry);
673 printk(KERN_ERR "metronomefb: couldn't process waveform\n");
677 if (board->setup_irq(info))
680 retval = metronome_init_regs(par);
684 info->flags = FBINFO_FLAG_DEFAULT;
686 info->fbdefio = &metronomefb_defio;
687 fb_deferred_io_init(info);
689 retval = fb_alloc_cmap(&info->cmap, 8, 0);
691 printk(KERN_ERR "Failed to allocate colormap\n");
696 for (i = 0; i < 8; i++)
697 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/16;
698 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
699 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
701 retval = register_framebuffer(info);
705 platform_set_drvdata(dev, info);
708 "fb%d: Metronome frame buffer device, using %dK of video"
709 " memory\n", info->node, videomemorysize >> 10);
714 fb_dealloc_cmap(&info->cmap);
716 framebuffer_release(info);
718 board->free_irq(info);
720 dma_free_writecombine(&dev->dev, par->metromemsize, par->metromem,
723 vfree(par->csum_table);
726 module_put(board->owner);
730 static int __devexit metronomefb_remove(struct platform_device *dev)
732 struct fb_info *info = platform_get_drvdata(dev);
735 struct metronomefb_par *par = info->par;
736 fb_deferred_io_cleanup(info);
737 dma_free_writecombine(&dev->dev, par->metromemsize,
738 par->metromem, par->metromem_dma);
739 fb_dealloc_cmap(&info->cmap);
740 vfree(par->csum_table);
741 unregister_framebuffer(info);
742 vfree((void __force *)info->screen_base);
743 par->board->free_irq(info);
744 module_put(par->board->owner);
745 framebuffer_release(info);
750 static struct platform_driver metronomefb_driver = {
751 .probe = metronomefb_probe,
752 .remove = metronomefb_remove,
754 .owner = THIS_MODULE,
755 .name = "metronomefb",
759 static int __init metronomefb_init(void)
761 return platform_driver_register(&metronomefb_driver);
764 static void __exit metronomefb_exit(void)
766 platform_driver_unregister(&metronomefb_driver);
769 module_init(metronomefb_init);
770 module_exit(metronomefb_exit);
772 MODULE_DESCRIPTION("fbdev driver for Metronome controller");
773 MODULE_AUTHOR("Jaya Kumar");
774 MODULE_LICENSE("GPL");