Set -march=mips32
[openwrt/openwrt.git] / target / linux / xburst / files-2.6.32 / drivers / video / metronomefb.c
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://support.eink.com/community
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
22 #include <linux/module.h>
23 #include <linux/kernel.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
26 #include <linux/mm.h>
27 #include <linux/slab.h>
28 #include <linux/vmalloc.h>
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/fb.h>
32 #include <linux/init.h>
33 #include <linux/platform_device.h>
34 #include <linux/list.h>
35 #include <linux/firmware.h>
36 #include <linux/dma-mapping.h>
37 #include <linux/uaccess.h>
38 #include <linux/irq.h>
39 #include <linux/ctype.h>
40
41 #include <video/metronomefb.h>
42
43 #include <asm/unaligned.h>
44
45 #define WF_MODE_INIT 0 /* Initialization */
46 #define WF_MODE_MU 1 /* Monochrome update */
47 #define WF_MODE_GU 2 /* Grayscale update */
48 #define WF_MODE_GC 3 /* Grayscale clearing */
49
50 static int temp = 25;
51
52 /* frame differs from image. frame includes non-visible pixels */
53 struct epd_frame {
54 int fw; /* frame width */
55 int fh; /* frame height */
56 u16 config[4];
57 int wfm_size;
58 };
59
60 static const struct epd_frame epd_frame_table[] = {
61 {
62 .fw = 832,
63 .fh = 622,
64 .config = {
65 15 /* sdlew */
66 | 2 << 8 /* sdosz */
67 | 0 << 11 /* sdor */
68 | 0 << 12 /* sdces */
69 | 0 << 15, /* sdcer */
70 42 /* gdspl */
71 | 1 << 8 /* gdr1 */
72 | 1 << 9 /* sdshr */
73 | 0 << 15, /* gdspp */
74 18 /* gdspw */
75 | 0 << 15, /* dispc */
76 599 /* vdlc */
77 | 0 << 11 /* dsi */
78 | 0 << 12, /* dsic */
79 },
80 .wfm_size = 47001,
81 },
82 {
83 .fw = 1088,
84 .fh = 791,
85 .config = {
86 0x0104,
87 0x031f,
88 0x0088,
89 0x02ff,
90 },
91 .wfm_size = 46770,
92 },
93 {
94 .fw = 1200,
95 .fh = 842,
96 .config = {
97 0x0101,
98 0x030e,
99 0x0012,
100 0x0280,
101 },
102 .wfm_size = 46770,
103 },
104 {
105 .fw = 800,
106 .fh = 600,
107 .config = {
108 15 /* sdlew */
109 | 2 << 8 /* sdosz */
110 | 0 << 11 /* sdor */
111 | 0 << 12 /* sdces */
112 | 0 << 15, /* sdcer */
113 42 /* gdspl */
114 | 1 << 8 /* gdr1 */
115 | 1 << 9 /* sdshr */
116 | 0 << 15, /* gdspp */
117 18 /* gdspw */
118 | 0 << 15, /* dispc */
119 599 /* vdlc */
120 | 0 << 11 /* dsi */
121 | 0 << 12, /* dsic */
122 },
123 .wfm_size = 46901,
124 },
125 };
126
127 static const struct fb_fix_screeninfo metronomefb_fix __devinitconst = {
128 .id = "metronomefb",
129 .type = FB_TYPE_PACKED_PIXELS,
130 .visual = FB_VISUAL_STATIC_PSEUDOCOLOR,
131 .xpanstep = 0,
132 .ypanstep = 0,
133 .ywrapstep = 0,
134 .accel = FB_ACCEL_NONE,
135 };
136
137 static const struct fb_var_screeninfo metronomefb_var __devinitconst = {
138 .bits_per_pixel = 8,
139 .grayscale = 1,
140 .nonstd = 1,
141 .red = { 4, 3, 0 },
142 .green = { 0, 0, 0 },
143 .blue = { 0, 0, 0 },
144 .transp = { 0, 0, 0 },
145 };
146
147 /* the waveform structure that is coming from userspace firmware */
148 struct waveform_hdr {
149 u8 stuff[32];
150
151 u8 wmta[3];
152 u8 fvsn;
153
154 u8 luts;
155 u8 mc;
156 u8 trc;
157 u8 stuff3;
158
159 u8 endb;
160 u8 swtb;
161 u8 stuff2a[2];
162
163 u8 stuff2b[3];
164 u8 wfm_cs;
165 } __attribute__ ((packed));
166
167 /* main metronomefb functions */
168 static u8 calc_cksum(int start, int end, u8 *mem)
169 {
170 u8 tmp = 0;
171 int i;
172
173 for (i = start; i < end; i++)
174 tmp += mem[i];
175
176 return tmp;
177 }
178
179 static u16 calc_img_cksum(u16 *start, int length)
180 {
181 u16 tmp = 0;
182
183 while (length--)
184 tmp += *start++;
185
186 return tmp;
187 }
188
189 /* here we decode the incoming waveform file and populate metromem */
190 static int load_waveform(u8 *mem, size_t size, int m, int t,
191 struct metronomefb_par *par)
192 {
193 int tta;
194 int wmta;
195 int trn = 0;
196 int i;
197 unsigned char v;
198 u8 cksum;
199 int cksum_idx;
200 int wfm_idx, owfm_idx;
201 int mem_idx = 0;
202 struct waveform_hdr *wfm_hdr;
203 u8 *metromem = par->metromem_wfm;
204 struct device *dev = &par->pdev->dev;
205 u8 mc, trc;
206 u16 *p;
207 u16 img_cksum;
208
209 dev_dbg(dev, "Loading waveforms, mode %d, temperature %d\n", m, t);
210
211 wfm_hdr = (struct waveform_hdr *) mem;
212
213 if (wfm_hdr->fvsn != 1) {
214 dev_err(dev, "Error: bad fvsn %x\n", wfm_hdr->fvsn);
215 return -EINVAL;
216 }
217 if (wfm_hdr->luts != 0) {
218 dev_err(dev, "Error: bad luts %x\n", wfm_hdr->luts);
219 return -EINVAL;
220 }
221 cksum = calc_cksum(32, 47, mem);
222 if (cksum != wfm_hdr->wfm_cs) {
223 dev_err(dev, "Error: bad cksum %x != %x\n", cksum,
224 wfm_hdr->wfm_cs);
225 return -EINVAL;
226 }
227 mc = wfm_hdr->mc + 1;
228 trc = wfm_hdr->trc + 1;
229
230 for (i = 0; i < 5; i++) {
231 if (*(wfm_hdr->stuff2a + i) != 0) {
232 dev_err(dev, "Error: unexpected value in padding\n");
233 return -EINVAL;
234 }
235 }
236
237 /* calculating trn. trn is something used to index into
238 the waveform. presumably selecting the right one for the
239 desired temperature. it works out the offset of the first
240 v that exceeds the specified temperature */
241 if ((sizeof(*wfm_hdr) + trc) > size)
242 return -EINVAL;
243
244 for (i = sizeof(*wfm_hdr); i <= sizeof(*wfm_hdr) + trc; i++) {
245 if (mem[i] > t) {
246 trn = i - sizeof(*wfm_hdr) - 1;
247 break;
248 }
249 }
250
251 /* check temperature range table checksum */
252 cksum_idx = sizeof(*wfm_hdr) + trc + 1;
253 if (cksum_idx > size)
254 return -EINVAL;
255 cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
256 if (cksum != mem[cksum_idx]) {
257 dev_err(dev, "Error: bad temperature range table cksum"
258 " %x != %x\n", cksum, mem[cksum_idx]);
259 return -EINVAL;
260 }
261
262 /* check waveform mode table address checksum */
263 wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
264 cksum_idx = wmta + m*4 + 3;
265 if (cksum_idx > size)
266 return -EINVAL;
267 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
268 if (cksum != mem[cksum_idx]) {
269 dev_err(dev, "Error: bad mode table address cksum"
270 " %x != %x\n", cksum, mem[cksum_idx]);
271 return -EINVAL;
272 }
273
274 /* check waveform temperature table address checksum */
275 tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
276 cksum_idx = tta + trn*4 + 3;
277 if (cksum_idx > size)
278 return -EINVAL;
279 cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
280 if (cksum != mem[cksum_idx]) {
281 dev_err(dev, "Error: bad temperature table address cksum"
282 " %x != %x\n", cksum, mem[cksum_idx]);
283 return -EINVAL;
284 }
285
286 /* here we do the real work of putting the waveform into the
287 metromem buffer. this does runlength decoding of the waveform */
288 wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
289 owfm_idx = wfm_idx;
290 if (wfm_idx > size)
291 return -EINVAL;
292 while (wfm_idx < size) {
293 unsigned char rl;
294 v = mem[wfm_idx++];
295 if (v == wfm_hdr->swtb) {
296 while (((v = mem[wfm_idx++]) != wfm_hdr->swtb) &&
297 wfm_idx < size)
298 metromem[mem_idx++] = v;
299
300 continue;
301 }
302
303 if (v == wfm_hdr->endb)
304 break;
305
306 rl = mem[wfm_idx++];
307 for (i = 0; i <= rl; i++)
308 metromem[mem_idx++] = v;
309 }
310
311 cksum_idx = wfm_idx;
312 if (cksum_idx > size)
313 return -EINVAL;
314 dev_dbg(dev, "mem_idx = %u\n", mem_idx);
315 cksum = calc_cksum(owfm_idx, cksum_idx, mem);
316 if (cksum != mem[cksum_idx]) {
317 dev_err(dev, "Error: bad waveform data cksum"
318 " %x != %x\n", cksum, mem[cksum_idx]);
319 return -EINVAL;
320 }
321 par->frame_count = (mem_idx/64);
322
323 p = (u16 *)par->metromem_wfm;
324 img_cksum = calc_img_cksum(p, 16384 / 2);
325 p[16384 / 2] = __cpu_to_le16(img_cksum);
326
327 par->current_wf_mode = m;
328 par->current_wf_temp = t;
329
330 return 0;
331 }
332
333 static int check_err(struct metronomefb_par *par)
334 {
335 int res;
336
337 res = par->board->get_err(par);
338 dev_dbg(&par->pdev->dev, "ERR = %d\n", res);
339 return res;
340 }
341
342 static inline int wait_for_rdy(struct metronomefb_par *par)
343 {
344 int res = 0;
345
346 if (!par->board->get_rdy(par))
347 res = par->board->met_wait_event_intr(par);
348
349 return res;
350 }
351
352 static int metronome_display_cmd(struct metronomefb_par *par)
353 {
354 int i;
355 u16 cs;
356 u16 opcode;
357 int res;
358
359 res = wait_for_rdy(par);
360 if (res)
361 return res;
362
363 dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
364 /* setup display command
365 we can't immediately set the opcode since the controller
366 will try parse the command before we've set it all up
367 so we just set cs here and set the opcode at the end */
368
369 if (par->metromem_cmd->opcode == 0xCC40)
370 opcode = cs = 0xCC41;
371 else
372 opcode = cs = 0xCC40;
373
374 /* set the args ( 2 bytes ) for display */
375 i = 0;
376 par->metromem_cmd->args[i] = 0 << 3 /* border update */
377 | (3 << 4)
378 // | ((borderval++ % 4) & 0x0F) << 4
379 | (par->frame_count - 1) << 8;
380 cs += par->metromem_cmd->args[i++];
381
382 /* the rest are 0 */
383 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
384
385 par->metromem_cmd->csum = cs;
386 par->metromem_cmd->opcode = opcode; /* display cmd */
387
388 return 0;
389
390 }
391
392 static int __devinit metronome_powerup_cmd(struct metronomefb_par *par)
393 {
394 int i;
395 u16 cs;
396 int res;
397
398 dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
399 /* setup power up command */
400 par->metromem_cmd->opcode = 0x1234; /* pwr up pseudo cmd */
401 cs = par->metromem_cmd->opcode;
402
403 /* set pwr1,2,3 to 1024 */
404 for (i = 0; i < 3; i++) {
405 // par->metromem_cmd->args[i] = 1024;
406 par->metromem_cmd->args[i] = 100;
407 cs += par->metromem_cmd->args[i];
408 }
409
410 /* the rest are 0 */
411 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
412
413 par->metromem_cmd->csum = cs;
414
415 msleep(1);
416 par->board->set_rst(par, 1);
417
418 msleep(1);
419 par->board->set_stdby(par, 1);
420
421 res = par->board->met_wait_event(par);
422 dev_dbg(&par->pdev->dev, "%s: EXIT: %d\n", __func__, res);
423 return res;
424 }
425
426 static int __devinit metronome_config_cmd(struct metronomefb_par *par)
427 {
428 /* setup config command
429 we can't immediately set the opcode since the controller
430 will try parse the command before we've set it all up */
431
432 dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
433 memcpy(par->metromem_cmd->args, par->epd_frame->config,
434 sizeof(par->epd_frame->config));
435 /* the rest are 0 */
436 memset((u8 *) (par->metromem_cmd->args + 4), 0, (32-4)*2);
437
438 par->metromem_cmd->csum = 0xCC10;
439 par->metromem_cmd->csum += calc_img_cksum(par->metromem_cmd->args, 4);
440 par->metromem_cmd->opcode = 0xCC10; /* config cmd */
441
442 return par->board->met_wait_event(par);
443 }
444
445 static int __devinit metronome_init_cmd(struct metronomefb_par *par)
446 {
447 int i;
448 u16 cs;
449
450 /* setup init command
451 we can't immediately set the opcode since the controller
452 will try parse the command before we've set it all up
453 so we just set cs here and set the opcode at the end */
454
455 dev_dbg(&par->pdev->dev, "%s: ENTER\n", __func__);
456 cs = 0xCC20;
457
458 /* set the args ( 2 bytes ) for init */
459 i = 0;
460 par->metromem_cmd->args[i] = 0x0007;
461 cs += par->metromem_cmd->args[i++];
462
463 /* the rest are 0 */
464 memset((u8 *) (par->metromem_cmd->args + i), 0, (32-i)*2);
465
466 par->metromem_cmd->csum = cs;
467 par->metromem_cmd->opcode = 0xCC20; /* init cmd */
468
469 return par->board->met_wait_event(par);
470 }
471
472 static int metronome_bootup(struct metronomefb_par *par)
473 {
474 int res;
475
476 res = metronome_powerup_cmd(par);
477 if (res) {
478 dev_err(&par->pdev->dev, "metronomefb: POWERUP cmd failed\n");
479 goto finish;
480 }
481
482 check_err(par);
483 res = metronome_config_cmd(par);
484 if (res) {
485 dev_err(&par->pdev->dev, "metronomefb: CONFIG cmd failed\n");
486 goto finish;
487 }
488 check_err(par);
489
490 res = metronome_init_cmd(par);
491 if (res)
492 dev_err(&par->pdev->dev, "metronomefb: INIT cmd failed\n");
493 check_err(par);
494
495 finish:
496 return res;
497 }
498
499 static int __devinit metronome_init_regs(struct metronomefb_par *par)
500 {
501 int res;
502
503 if (par->board->power_ctl)
504 par->board->power_ctl(par, METRONOME_POWER_ON);
505
506 res = metronome_bootup(par);
507
508 return res;
509 }
510
511 static uint16_t metronomefb_update_img_buffer_rotated(struct metronomefb_par *par)
512 {
513 int x, y;
514 int xstep, ystep;
515 int i, j;
516 uint16_t cksum = 0;
517 uint8_t *buf = par->info->screen_base;
518 uint32_t *img = (uint32_t *)(par->metromem_img);
519 int fw = par->epd_frame->fw;
520 int fh = par->epd_frame->fh;
521 int fw_buf = fw / 4;
522 uint32_t *fxbuckets = par->fxbuckets;
523 uint32_t *fybuckets = par->fybuckets;
524 uint32_t diff;
525 uint32_t tmp;
526
527 switch (par->info->var.rotate) {
528 case FB_ROTATE_CW:
529 xstep = -fh;
530 ystep = fw * fh + 1;
531 j = (fw - 1) * fh;
532 break;
533 case FB_ROTATE_UD:
534 xstep = -1;
535 ystep = 0;
536 j = fw * fh - 1;
537 break;
538 case FB_ROTATE_CCW:
539 xstep = fh;
540 ystep = -fw * fh - 1;
541 j = fh - 1;
542 break;
543 default:
544 BUG();
545 break;
546 }
547
548 memset(fxbuckets, 0, fw_buf * sizeof(*fxbuckets));
549 memset(fybuckets, 0, fh * sizeof(*fybuckets));
550
551 i = 0;
552 for (y = 0; y < fh; y++) {
553 for(x = 0; x < fw_buf; x++, i++) {
554 if (j < 0 || j >= fw * fh) {
555 printk("moo: %d %d %d %d %d\n", j, x, y, fw_buf, fh);
556 return 0;
557 }
558 tmp = (buf[j] << 5);
559 j += xstep;
560 tmp |= (buf[j] << 13);
561 j += xstep;
562 tmp |= (buf[j] << 21);
563 j += xstep;
564 tmp |= (buf[j] << 29);
565 j += xstep;
566 tmp &= 0xe0e0e0e0;
567
568 img[i] &= 0xf0f0f0f0;
569 diff = img[i] ^ tmp;
570
571 fxbuckets[x] |= diff;
572 fybuckets[y] |= diff;
573
574 img[i] = (img[i] >> 4) | tmp;
575 cksum += img[i] & 0x0000ffff;
576 cksum += (img[i] >> 16);
577
578 }
579 j += ystep;
580 }
581
582 return cksum;
583 }
584
585 static uint16_t metronomefb_update_img_buffer_normal(struct metronomefb_par *par)
586 {
587 int x, y, i;
588 uint16_t cksum = 0;
589 uint32_t *buf = (uint32_t __force *)par->info->screen_base;
590 uint32_t *img = (uint32_t *)(par->metromem_img);
591 uint32_t diff;
592 uint32_t tmp;
593 int fw = par->epd_frame->fw;
594 int fh = par->epd_frame->fh;
595 int fw_buf = fw / sizeof(*buf);
596 uint32_t *fxbuckets = par->fxbuckets;
597 uint32_t *fybuckets = par->fybuckets;
598
599 memset(fxbuckets, 0, fw_buf * sizeof(*fxbuckets));
600 memset(fybuckets, 0, fh * sizeof(*fybuckets));
601
602 i = 0;
603 for (y = 0; y < fh; y++) {
604 for(x = 0; x < fw_buf; x++, i++) {
605 tmp = (buf[i] << 5) & 0xe0e0e0e0;
606 img[i] &= 0xf0f0f0f0;
607 diff = img[i] ^ tmp;
608
609 fxbuckets[x] |= diff;
610 fybuckets[y] |= diff;
611
612 img[i] = (img[i] >> 4) | tmp;
613 cksum += img[i] & 0x0000ffff;
614 cksum += (img[i] >> 16);
615 }
616 }
617
618 return cksum;
619 }
620
621 static unsigned int metronomefb_get_change_count(struct metronomefb_par *par)
622 {
623 int min_x;
624 int max_x;
625 int min_y;
626 int max_y;
627 int fw = par->epd_frame->fw / 4;
628 int fh = par->epd_frame->fh;
629 unsigned int change_count;
630 uint32_t *fxbuckets = par->fxbuckets;
631 uint32_t *fybuckets = par->fybuckets;
632
633 for (min_x = 0; min_x < fw; ++min_x) {
634 if(fxbuckets[min_x])
635 break;
636 }
637
638 for (max_x = fw - 1; max_x >= 0; --max_x) {
639 if(fxbuckets[max_x])
640 break;
641 }
642
643 for (min_y = 0; min_y < fh; min_y++) {
644 if(fybuckets[min_y])
645 break;
646 }
647
648 for (max_y = fh - 1; max_y >= 0; --max_y) {
649 if(fybuckets[max_y])
650 break;
651 }
652
653 if ((min_x > max_x) || (min_y > max_y))
654 change_count = 0;
655 else
656 change_count = (max_x - min_x + 1) * (max_y - min_y + 1) * 4;
657
658 dev_dbg(&par->pdev->dev, "min_x = %d, max_x = %d, min_y = %d, max_y = %d\n",
659 min_x, max_x, min_y, max_y);
660
661 return change_count;
662 }
663
664 static void metronomefb_dpy_update(struct metronomefb_par *par, int clear_all)
665 {
666 unsigned int fbsize = par->info->fix.smem_len;
667 uint16_t cksum;
668 int m;
669
670 wait_for_rdy(par);
671
672 if (par->info->var.rotate == 0)
673 cksum = metronomefb_update_img_buffer_normal(par);
674 else
675 cksum = metronomefb_update_img_buffer_rotated(par);
676
677 *par->metromem_img_csum = __cpu_to_le16(cksum);
678
679 if (clear_all || par->is_first_update ||
680 (par->partial_updates_count == par->partial_autorefresh_interval)) {
681 m = WF_MODE_GC;
682 par->partial_updates_count = 0;
683 } else {
684 int change_count = metronomefb_get_change_count(par);
685 if (change_count < fbsize / 100 * par->manual_refresh_threshold)
686 m = WF_MODE_GU;
687 else
688 m = WF_MODE_GC;
689
690 dev_dbg(&par->pdev->dev, "change_count = %u, treshold = %u%% (%u pixels)\n",
691 change_count, par->manual_refresh_threshold,
692 fbsize / 100 * par->manual_refresh_threshold);
693 ++par->partial_updates_count;
694 }
695
696 if (m != par->current_wf_mode)
697 load_waveform((u8 *) par->firmware->data, par->firmware->size,
698 m, par->current_wf_temp, par);
699
700 again:
701 metronome_display_cmd(par);
702 wait_for_rdy(par);
703 if (unlikely(check_err(par))) {
704 par->board->set_stdby(par, 0);
705 printk("Resetting Metronome\n");
706 par->board->set_rst(par, 0);
707 mdelay(1);
708 if (par->board->power_ctl)
709 par->board->power_ctl(par, METRONOME_POWER_OFF);
710
711 mdelay(1);
712 load_waveform((u8 *) par->firmware->data, par->firmware->size,
713 WF_MODE_GC, par->current_wf_temp, par);
714
715 if (par->board->power_ctl)
716 par->board->power_ctl(par, METRONOME_POWER_ON);
717 metronome_bootup(par);
718
719 goto again;
720 }
721
722 par->is_first_update = 0;
723 }
724
725 /* this is called back from the deferred io workqueue */
726 static void metronomefb_dpy_deferred_io(struct fb_info *info,
727 struct list_head *pagelist)
728 {
729 struct metronomefb_par *par = info->par;
730
731 /* We will update entire display because we need to change
732 * 'previous image' field in pixels which was changed at
733 * previous refresh
734 */
735 mutex_lock(&par->lock);
736 metronomefb_dpy_update(par, 0);
737 mutex_unlock(&par->lock);
738 }
739
740 static void metronomefb_fillrect(struct fb_info *info,
741 const struct fb_fillrect *rect)
742 {
743 struct metronomefb_par *par = info->par;
744
745 mutex_lock(&par->lock);
746 sys_fillrect(info, rect);
747 metronomefb_dpy_update(par, 0);
748 mutex_unlock(&par->lock);
749 }
750
751 static void metronomefb_copyarea(struct fb_info *info,
752 const struct fb_copyarea *area)
753 {
754 struct metronomefb_par *par = info->par;
755
756 mutex_lock(&par->lock);
757 sys_copyarea(info, area);
758 metronomefb_dpy_update(par, 0);
759 mutex_unlock(&par->lock);
760 }
761
762 static void metronomefb_imageblit(struct fb_info *info,
763 const struct fb_image *image)
764 {
765 struct metronomefb_par *par = info->par;
766
767 mutex_lock(&par->lock);
768 sys_imageblit(info, image);
769 metronomefb_dpy_update(par, 0);
770 mutex_unlock(&par->lock);
771 }
772
773 /*
774 * this is the slow path from userspace. they can seek and write to
775 * the fb. it is based on fb_sys_write
776 */
777 static ssize_t metronomefb_write(struct fb_info *info, const char __user *buf,
778 size_t count, loff_t *ppos)
779 {
780 struct metronomefb_par *par = info->par;
781 unsigned long p = *ppos;
782 void *dst;
783 int err = 0;
784 unsigned long total_size;
785
786 if (info->state != FBINFO_STATE_RUNNING)
787 return -EPERM;
788
789 total_size = info->fix.smem_len;
790
791 if (p > total_size)
792 return -EFBIG;
793
794 if (count > total_size) {
795 err = -EFBIG;
796 count = total_size;
797 }
798
799 if (count + p > total_size) {
800 if (!err)
801 err = -ENOSPC;
802
803 count = total_size - p;
804 }
805
806 dst = (void __force *)(info->screen_base + p);
807
808 mutex_lock(&par->lock);
809
810 if (copy_from_user(dst, buf, count))
811 err = -EFAULT;
812
813 if (!err)
814 *ppos += count;
815
816 metronomefb_dpy_update(par, 0);
817 mutex_unlock(&par->lock);
818
819 return (err) ? err : count;
820 }
821
822 static int metronome_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
823 {
824 struct metronomefb_par *par = info->par;
825
826 if (par->epd_frame->fw == var->xres && par->epd_frame->fh == var->yres)
827 return 0;
828
829 return -EINVAL;
830 }
831
832 static int metronomefb_set_par(struct fb_info *info)
833 {
834 struct metronomefb_par *par = info->par;
835
836 switch (info->var.rotate) {
837 case FB_ROTATE_CW:
838 case FB_ROTATE_CCW:
839 info->fix.line_length = info->var.yres;
840 break;
841 case FB_ROTATE_UD:
842 default:
843 info->fix.line_length = info->var.xres;
844 break;
845 }
846
847 mutex_lock(&par->lock);
848 metronomefb_dpy_update(info->par, 1);
849 mutex_unlock(&par->lock);
850
851 return 0;
852 }
853
854 static struct fb_ops metronomefb_ops = {
855 .owner = THIS_MODULE,
856 .fb_write = metronomefb_write,
857 .fb_fillrect = metronomefb_fillrect,
858 .fb_copyarea = metronomefb_copyarea,
859 .fb_imageblit = metronomefb_imageblit,
860 .fb_check_var = metronome_check_var,
861 .fb_set_par = metronomefb_set_par,
862 };
863
864 static struct fb_deferred_io metronomefb_defio = {
865 .delay = HZ / 4,
866 .deferred_io = metronomefb_dpy_deferred_io,
867 };
868
869 static ssize_t metronomefb_defio_delay_show(struct device *dev,
870 struct device_attribute *attr, char *buf)
871 {
872 struct fb_info *info = dev_get_drvdata(dev);
873
874 sprintf(buf, "%lu\n", info->fbdefio->delay * 1000 / HZ);
875 return strlen(buf) + 1;
876 }
877
878 static ssize_t metronomefb_defio_delay_store(struct device *dev,
879 struct device_attribute *attr, const char *buf, size_t size)
880 {
881 struct fb_info *info = dev_get_drvdata(dev);
882 char *after;
883 unsigned long state = simple_strtoul(buf, &after, 10);
884 size_t count = after - buf;
885 ssize_t ret = -EINVAL;
886
887 if (*after && isspace(*after))
888 count++;
889
890 state = state * HZ / 1000;
891
892 if (!state)
893 state = 1;
894
895 if (count == size) {
896 ret = count;
897 info->fbdefio->delay = state;
898 }
899
900 return ret;
901 }
902
903 static ssize_t metronomefb_manual_refresh_thr_show(struct device *dev,
904 struct device_attribute *attr, char *buf)
905 {
906 struct fb_info *info = dev_get_drvdata(dev);
907 struct metronomefb_par *par = info->par;
908
909 return sprintf(buf, "%u\n", par->manual_refresh_threshold);
910 }
911
912 static ssize_t metronomefb_manual_refresh_thr_store(struct device *dev,
913 struct device_attribute *attr, const char *buf, size_t size)
914 {
915 struct fb_info *info = dev_get_drvdata(dev);
916 struct metronomefb_par *par = info->par;
917 char *after;
918 unsigned long val = simple_strtoul(buf, &after, 10);
919 size_t count = after - buf;
920 ssize_t ret = -EINVAL;
921
922 if (*after && isspace(*after))
923 count++;
924
925 if (val > 100)
926 return -EINVAL;
927
928
929 if (count == size) {
930 ret = count;
931 par->manual_refresh_threshold = val;
932 }
933
934 return ret;
935 }
936
937 static ssize_t metronomefb_autorefresh_interval_show(struct device *dev,
938 struct device_attribute *attr, char *buf)
939 {
940 struct fb_info *info = dev_get_drvdata(dev);
941 struct metronomefb_par *par = info->par;
942
943 return sprintf(buf, "%u\n", par->partial_autorefresh_interval);
944 }
945
946 static ssize_t metronomefb_autorefresh_interval_store(struct device *dev,
947 struct device_attribute *attr, const char *buf, size_t size)
948 {
949 struct fb_info *info = dev_get_drvdata(dev);
950 struct metronomefb_par *par = info->par;
951 char *after;
952 unsigned long val = simple_strtoul(buf, &after, 10);
953 size_t count = after - buf;
954 ssize_t ret = -EINVAL;
955
956 if (*after && isspace(*after))
957 count++;
958
959 if (val > 100)
960 return -EINVAL;
961
962
963 if (count == size) {
964 ret = count;
965 par->partial_autorefresh_interval = val;
966 }
967
968 return ret;
969 }
970
971 static ssize_t metronomefb_temp_show(struct device *dev,
972 struct device_attribute *attr, char *buf)
973 {
974 struct fb_info *info = dev_get_drvdata(dev);
975 struct metronomefb_par *par = info->par;
976
977 return sprintf(buf, "%u\n", par->current_wf_temp);
978 }
979
980 static ssize_t metronomefb_temp_store(struct device *dev,
981 struct device_attribute *attr, const char *buf, size_t size)
982 {
983 struct fb_info *info = dev_get_drvdata(dev);
984 struct metronomefb_par *par = info->par;
985 char *after;
986 unsigned long val = simple_strtoul(buf, &after, 10);
987 size_t count = after - buf;
988 ssize_t ret = -EINVAL;
989
990 if (*after && isspace(*after))
991 count++;
992
993 if (val > 100)
994 return -EINVAL;
995
996
997 if (count == size) {
998 ret = count;
999 if (val != par->current_wf_temp)
1000 load_waveform((u8 *) par->firmware->data, par->firmware->size,
1001 par->current_wf_mode, val, par);
1002 }
1003
1004 return ret;
1005 }
1006
1007 DEVICE_ATTR(defio_delay, 0644,
1008 metronomefb_defio_delay_show, metronomefb_defio_delay_store);
1009 DEVICE_ATTR(manual_refresh_threshold, 0644,
1010 metronomefb_manual_refresh_thr_show, metronomefb_manual_refresh_thr_store);
1011 DEVICE_ATTR(temp, 0644,
1012 metronomefb_temp_show, metronomefb_temp_store);
1013 DEVICE_ATTR(autorefresh_interval, 0644,
1014 metronomefb_autorefresh_interval_show, metronomefb_autorefresh_interval_store);
1015
1016
1017 static int __devinit metronomefb_probe(struct platform_device *dev)
1018 {
1019 struct fb_info *info;
1020 struct metronome_board *board;
1021 int retval = -ENOMEM;
1022 int videomemorysize;
1023 unsigned char *videomemory;
1024 struct metronomefb_par *par;
1025 const struct firmware *fw_entry;
1026 int i;
1027 int panel_type;
1028 int fw, fh;
1029 int epd_dt_index;
1030
1031 /* pick up board specific routines */
1032 board = dev->dev.platform_data;
1033 if (!board)
1034 return -EINVAL;
1035
1036 /* try to count device specific driver, if can't, platform recalls */
1037 if (!try_module_get(board->owner))
1038 return -ENODEV;
1039
1040 info = framebuffer_alloc(sizeof(struct metronomefb_par), &dev->dev);
1041 if (!info)
1042 goto err;
1043
1044 /* we have two blocks of memory.
1045 info->screen_base which is vm, and is the fb used by apps.
1046 par->metromem which is physically contiguous memory and
1047 contains the display controller commands, waveform,
1048 processed image data and padding. this is the data pulled
1049 by the device's LCD controller and pushed to Metronome.
1050 the metromem memory is allocated by the board driver and
1051 is provided to us */
1052
1053 panel_type = board->get_panel_type();
1054 switch (panel_type) {
1055 case 5:
1056 epd_dt_index = 3;
1057 break;
1058 case 6:
1059 epd_dt_index = 0;
1060 break;
1061 case 8:
1062 epd_dt_index = 1;
1063 break;
1064 case 97:
1065 epd_dt_index = 2;
1066 break;
1067 default:
1068 dev_err(&dev->dev, "Unexpected panel type. Defaulting to 6\n");
1069 epd_dt_index = 0;
1070 break;
1071 }
1072
1073 fw = epd_frame_table[epd_dt_index].fw;
1074 fh = epd_frame_table[epd_dt_index].fh;
1075
1076 /* we need to add a spare page because our csum caching scheme walks
1077 * to the end of the page */
1078 videomemorysize = PAGE_SIZE + (fw * fh);
1079 videomemory = vmalloc(videomemorysize);
1080 if (!videomemory)
1081 goto err_fb_rel;
1082
1083 memset(videomemory, 0xff, videomemorysize);
1084
1085 info->screen_base = (char __force __iomem *)videomemory;
1086 info->fbops = &metronomefb_ops;
1087
1088 info->var = metronomefb_var;
1089 info->var.xres = fw;
1090 info->var.yres = fh;
1091 info->var.xres_virtual = fw;
1092 info->var.yres_virtual = fh;
1093 info->fix = metronomefb_fix;
1094 info->fix.line_length = fw;
1095 info->fix.smem_len = fw * fh; /* Real size of image area */
1096 par = info->par;
1097 par->info = info;
1098 par->board = board;
1099 par->epd_frame = &epd_frame_table[epd_dt_index];
1100 par->pdev = dev;
1101
1102 par->fxbuckets = kmalloc((fw / 4 + 1) * sizeof(*par->fxbuckets), GFP_KERNEL);
1103 if (!par->fxbuckets)
1104 goto err_vfree;
1105
1106 par->fybuckets = kmalloc(fh * sizeof(*par->fybuckets), GFP_KERNEL);
1107 if (!par->fybuckets)
1108 goto err_fxbuckets;
1109
1110 init_waitqueue_head(&par->waitq);
1111 par->manual_refresh_threshold = 60;
1112 par->partial_autorefresh_interval = 256;
1113 par->partial_updates_count = 0;
1114 par->is_first_update = 1;
1115 mutex_init(&par->lock);
1116
1117 /* this table caches per page csum values. */
1118 par->csum_table = vmalloc(videomemorysize/PAGE_SIZE);
1119 if (!par->csum_table)
1120 goto err_fybuckets;
1121
1122 /* the physical framebuffer that we use is setup by
1123 * the platform device driver. It will provide us
1124 * with cmd, wfm and image memory in a contiguous area. */
1125 retval = board->setup_fb(par);
1126 if (retval) {
1127 dev_err(&dev->dev, "Failed to setup fb\n");
1128 goto err_csum_table;
1129 }
1130
1131 /* after this point we should have a framebuffer */
1132 if ((!par->metromem_wfm) || (!par->metromem_img) ||
1133 (!par->metromem_dma)) {
1134 dev_err(&dev->dev, "fb access failure\n");
1135 retval = -EINVAL;
1136 goto err_csum_table;
1137 }
1138
1139 info->fix.smem_start = par->metromem_dma;
1140
1141 /* load the waveform in. assume mode 3, temp 31 for now
1142 a) request the waveform file from userspace
1143 b) process waveform and decode into metromem */
1144 retval = request_firmware(&fw_entry, "metronome.wbf", &dev->dev);
1145 if (retval < 0) {
1146 dev_err(&dev->dev, "Failed to get waveform\n");
1147 goto err_csum_table;
1148 }
1149
1150 retval = load_waveform((u8 *) fw_entry->data, fw_entry->size, WF_MODE_GC, temp,
1151 par);
1152 if (retval < 0) {
1153 dev_err(&dev->dev, "Failed processing waveform\n");
1154 goto err_csum_table;
1155 }
1156 par->firmware = fw_entry;
1157
1158 retval = board->setup_io(par);
1159 if (retval) {
1160 dev_err(&dev->dev, "metronomefb: setup_io() failed\n");
1161 goto err_csum_table;
1162 }
1163
1164 if (board->setup_irq(info))
1165 goto err_csum_table;
1166
1167 retval = metronome_init_regs(par);
1168 if (retval < 0)
1169 goto err_free_irq;
1170
1171 info->flags = FBINFO_FLAG_DEFAULT;
1172
1173 info->fbdefio = &metronomefb_defio;
1174 fb_deferred_io_init(info);
1175
1176 retval = fb_alloc_cmap(&info->cmap, 8, 0);
1177 if (retval < 0) {
1178 dev_err(&dev->dev, "Failed to allocate colormap\n");
1179 goto err_free_irq;
1180 }
1181
1182 /* set cmap */
1183 for (i = 0; i < 8; i++)
1184 info->cmap.red[i] = ((2 * i + 1)*(0xFFFF))/16;
1185 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*8);
1186 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*8);
1187
1188 retval = register_framebuffer(info);
1189 if (retval < 0)
1190 goto err_cmap;
1191
1192 platform_set_drvdata(dev, info);
1193
1194 retval = device_create_file(info->dev, &dev_attr_defio_delay);
1195 if (retval)
1196 goto err_devattr_defio_delay;
1197
1198 retval = device_create_file(info->dev, &dev_attr_manual_refresh_threshold);
1199 if (retval)
1200 goto err_devattr_manual_refresh_thr;
1201
1202 retval = device_create_file(info->dev, &dev_attr_temp);
1203 if (retval)
1204 goto err_devattr_temp;
1205
1206 retval = device_create_file(info->dev, &dev_attr_autorefresh_interval);
1207 if (retval)
1208 goto err_devattr_autorefresh;
1209
1210 dev_info(&dev->dev,
1211 "fb%d: Metronome frame buffer device, using %dK of video"
1212 " memory\n", info->node, videomemorysize >> 10);
1213
1214 return 0;
1215
1216 device_remove_file(info->dev, &dev_attr_autorefresh_interval);
1217 err_devattr_autorefresh:
1218 device_remove_file(info->dev, &dev_attr_temp);
1219 err_devattr_temp:
1220 device_remove_file(info->dev, &dev_attr_manual_refresh_threshold);
1221 err_devattr_manual_refresh_thr:
1222 device_remove_file(info->dev, &dev_attr_defio_delay);
1223 err_devattr_defio_delay:
1224 unregister_framebuffer(info);
1225 err_cmap:
1226 fb_dealloc_cmap(&info->cmap);
1227 err_free_irq:
1228 board->cleanup(par);
1229 err_csum_table:
1230 vfree(par->csum_table);
1231 err_fybuckets:
1232 kfree(par->fybuckets);
1233 err_fxbuckets:
1234 kfree(par->fxbuckets);
1235 err_vfree:
1236 vfree(videomemory);
1237 err_fb_rel:
1238 framebuffer_release(info);
1239 err:
1240 module_put(board->owner);
1241 return retval;
1242 }
1243
1244 static int __devexit metronomefb_remove(struct platform_device *dev)
1245 {
1246 struct fb_info *info = platform_get_drvdata(dev);
1247
1248 if (info) {
1249 struct metronomefb_par *par = info->par;
1250
1251 par->board->set_stdby(par, 0);
1252 mdelay(1);
1253 if (par->board->power_ctl)
1254 par->board->power_ctl(par, METRONOME_POWER_OFF);
1255
1256 device_remove_file(info->dev, &dev_attr_autorefresh_interval);
1257 device_remove_file(info->dev, &dev_attr_temp);
1258 device_remove_file(info->dev, &dev_attr_manual_refresh_threshold);
1259 device_remove_file(info->dev, &dev_attr_defio_delay);
1260 unregister_framebuffer(info);
1261 fb_deferred_io_cleanup(info);
1262 fb_dealloc_cmap(&info->cmap);
1263 par->board->cleanup(par);
1264 vfree(par->csum_table);
1265 kfree(par->fybuckets);
1266 kfree(par->fxbuckets);
1267 vfree((void __force *)info->screen_base);
1268 module_put(par->board->owner);
1269 release_firmware(par->firmware);
1270 dev_dbg(&dev->dev, "calling release\n");
1271 framebuffer_release(info);
1272 }
1273 return 0;
1274 }
1275
1276 #ifdef CONFIG_PM
1277 static int metronomefb_suspend(struct platform_device *pdev, pm_message_t message)
1278 {
1279 struct fb_info *info = platform_get_drvdata(pdev);
1280 struct metronomefb_par *par = info->par;
1281
1282 par->board->set_stdby(par, 0);
1283 par->board->set_rst(par, 0);
1284 if (par->board->power_ctl)
1285 par->board->power_ctl(par, METRONOME_POWER_OFF);
1286
1287
1288 return 0;
1289 }
1290
1291 static int metronomefb_resume(struct platform_device *pdev)
1292 {
1293 struct fb_info *info = platform_get_drvdata(pdev);
1294 struct metronomefb_par *par = info->par;
1295
1296 if (par->board->power_ctl)
1297 par->board->power_ctl(par, METRONOME_POWER_ON);
1298
1299 mutex_lock(&par->lock);
1300 metronome_bootup(par);
1301 mutex_unlock(&par->lock);
1302
1303 return 0;
1304 }
1305
1306 #else
1307 #define metronomefb_suspend NULL
1308 #define metronomefb_resume NULL
1309 #endif
1310
1311
1312 static struct platform_driver metronomefb_driver = {
1313 .driver = {
1314 .owner = THIS_MODULE,
1315 .name = "metronomefb",
1316 },
1317 .probe = metronomefb_probe,
1318 .remove = __devexit_p(metronomefb_remove),
1319 .suspend = metronomefb_suspend,
1320 .resume = metronomefb_resume,
1321 };
1322
1323 static int __init metronomefb_init(void)
1324 {
1325 return platform_driver_register(&metronomefb_driver);
1326 }
1327
1328 static void __exit metronomefb_exit(void)
1329 {
1330 platform_driver_unregister(&metronomefb_driver);
1331 }
1332
1333 module_param(temp, int, 0);
1334 MODULE_PARM_DESC(temp, "Set current temperature");
1335
1336 module_init(metronomefb_init);
1337 module_exit(metronomefb_exit);
1338
1339 MODULE_DESCRIPTION("fbdev driver for Metronome controller");
1340 MODULE_AUTHOR("Jaya Kumar");
1341 MODULE_LICENSE("GPL");