Root/target/linux/xburst/patches-2.6.37/440-metronome.patch

1From 057f6f13cff319e9f2fff39736371e95ff5ac47b Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Wed, 12 May 2010 14:24:46 +0200
4Subject: [PATCH 1/5] 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
1214

Archive Download this file



interactive