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