Root/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
50static int temp = 25;
51
52/* frame differs from image. frame includes non-visible pixels */
53struct epd_frame {
54    int fw; /* frame width */
55    int fh; /* frame height */
56    u16 config[4];
57    int wfm_size;
58};
59
60static 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
127static 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
137static 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 */
148struct 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 */
168static 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
179static 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 */
190static 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
333static 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
342static 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
352static 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
392static 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
426static 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
445static 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
472static 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
495finish:
496    return res;
497}
498
499static 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
511static 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
585static 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
621static 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
664static 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
700again:
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 */
726static 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
740static 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
751static 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
762static 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 */
777static 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
822static 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
832static 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
854static 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
864static struct fb_deferred_io metronomefb_defio = {
865    .delay = HZ / 4,
866    .deferred_io = metronomefb_dpy_deferred_io,
867};
868
869static 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
878static 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
903static 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
912static 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
937static 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
946static 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
971static 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
980static 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
1007DEVICE_ATTR(defio_delay, 0644,
1008        metronomefb_defio_delay_show, metronomefb_defio_delay_store);
1009DEVICE_ATTR(manual_refresh_threshold, 0644,
1010        metronomefb_manual_refresh_thr_show, metronomefb_manual_refresh_thr_store);
1011DEVICE_ATTR(temp, 0644,
1012        metronomefb_temp_show, metronomefb_temp_store);
1013DEVICE_ATTR(autorefresh_interval, 0644,
1014        metronomefb_autorefresh_interval_show, metronomefb_autorefresh_interval_store);
1015
1016
1017static 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);
1217err_devattr_autorefresh:
1218    device_remove_file(info->dev, &dev_attr_temp);
1219err_devattr_temp:
1220    device_remove_file(info->dev, &dev_attr_manual_refresh_threshold);
1221err_devattr_manual_refresh_thr:
1222    device_remove_file(info->dev, &dev_attr_defio_delay);
1223err_devattr_defio_delay:
1224    unregister_framebuffer(info);
1225err_cmap:
1226    fb_dealloc_cmap(&info->cmap);
1227err_free_irq:
1228    board->cleanup(par);
1229err_csum_table:
1230    vfree(par->csum_table);
1231err_fybuckets:
1232    kfree(par->fybuckets);
1233err_fxbuckets:
1234    kfree(par->fxbuckets);
1235err_vfree:
1236    vfree(videomemory);
1237err_fb_rel:
1238    framebuffer_release(info);
1239err:
1240    module_put(board->owner);
1241    return retval;
1242}
1243
1244static 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
1277static 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
1291static 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
1312static 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
1323static int __init metronomefb_init(void)
1324{
1325    return platform_driver_register(&metronomefb_driver);
1326}
1327
1328static void __exit metronomefb_exit(void)
1329{
1330    platform_driver_unregister(&metronomefb_driver);
1331}
1332
1333module_param(temp, int, 0);
1334MODULE_PARM_DESC(temp, "Set current temperature");
1335
1336module_init(metronomefb_init);
1337module_exit(metronomefb_exit);
1338
1339MODULE_DESCRIPTION("fbdev driver for Metronome controller");
1340MODULE_AUTHOR("Jaya Kumar");
1341MODULE_LICENSE("GPL");
1342

Archive Download this file



interactive