Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
[firefly-linux-kernel-4.4.55.git] / drivers / video / broadsheetfb.c
1 /*
2  * broadsheetfb.c -- FB driver for E-Ink Broadsheet 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 driver is written to be used with the Broadsheet display controller.
13  *
14  * It is intended to be architecture independent. A board specific driver
15  * must be used to perform all the physical IO interactions.
16  *
17  */
18
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/string.h>
23 #include <linux/mm.h>
24 #include <linux/slab.h>
25 #include <linux/vmalloc.h>
26 #include <linux/delay.h>
27 #include <linux/interrupt.h>
28 #include <linux/fb.h>
29 #include <linux/init.h>
30 #include <linux/platform_device.h>
31 #include <linux/list.h>
32 #include <linux/firmware.h>
33 #include <linux/uaccess.h>
34
35 #include <video/broadsheetfb.h>
36
37 /* track panel specific parameters */
38 struct panel_info {
39         int w;
40         int h;
41         u16 sdcfg;
42         u16 gdcfg;
43         u16 lutfmt;
44         u16 fsynclen;
45         u16 fendfbegin;
46         u16 lsynclen;
47         u16 lendlbegin;
48         u16 pixclk;
49 };
50
51 /* table of panel specific parameters to be indexed into by the board drivers */
52 static struct panel_info panel_table[] = {
53         {       /* standard 6" on TFT backplane */
54                 .w = 800,
55                 .h = 600,
56                 .sdcfg = (100 | (1 << 8) | (1 << 9)),
57                 .gdcfg = 2,
58                 .lutfmt = (4 | (1 << 7)),
59                 .fsynclen = 4,
60                 .fendfbegin = (10 << 8) | 4,
61                 .lsynclen = 10,
62                 .lendlbegin = (100 << 8) | 4,
63                 .pixclk = 6,
64         },
65         {       /* custom 3.7" flexible on PET or steel */
66                 .w = 320,
67                 .h = 240,
68                 .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
69                 .gdcfg = 3,
70                 .lutfmt = (4 | (1 << 7)),
71                 .fsynclen = 0,
72                 .fendfbegin = (80 << 8) | 4,
73                 .lsynclen = 10,
74                 .lendlbegin = (80 << 8) | 20,
75                 .pixclk = 14,
76         },
77         {       /* standard 9.7" on TFT backplane */
78                 .w = 1200,
79                 .h = 825,
80                 .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
81                 .gdcfg = 2,
82                 .lutfmt = (4 | (1 << 7)),
83                 .fsynclen = 0,
84                 .fendfbegin = (4 << 8) | 4,
85                 .lsynclen = 4,
86                 .lendlbegin = (60 << 8) | 10,
87                 .pixclk = 3,
88         },
89 };
90
91 #define DPY_W 800
92 #define DPY_H 600
93
94 static struct fb_fix_screeninfo broadsheetfb_fix __devinitdata = {
95         .id =           "broadsheetfb",
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 broadsheetfb_var __devinitdata = {
106         .xres           = DPY_W,
107         .yres           = DPY_H,
108         .xres_virtual   = DPY_W,
109         .yres_virtual   = DPY_H,
110         .bits_per_pixel = 8,
111         .grayscale      = 1,
112         .red =          { 0, 4, 0 },
113         .green =        { 0, 4, 0 },
114         .blue =         { 0, 4, 0 },
115         .transp =       { 0, 0, 0 },
116 };
117
118 /* main broadsheetfb functions */
119 static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
120 {
121         par->board->set_ctl(par, BS_WR, 0);
122         par->board->set_hdb(par, data);
123         par->board->set_ctl(par, BS_WR, 1);
124 }
125
126 static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
127 {
128         par->board->set_ctl(par, BS_DC, 0);
129         broadsheet_gpio_issue_data(par, data);
130 }
131
132 static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
133 {
134         par->board->wait_for_rdy(par);
135
136         par->board->set_ctl(par, BS_CS, 0);
137         broadsheet_gpio_issue_cmd(par, data);
138         par->board->set_ctl(par, BS_DC, 1);
139         par->board->set_ctl(par, BS_CS, 1);
140 }
141
142 static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
143                                         int argc, u16 *argv)
144 {
145         int i;
146
147         par->board->wait_for_rdy(par);
148
149         par->board->set_ctl(par, BS_CS, 0);
150         broadsheet_gpio_issue_cmd(par, cmd);
151         par->board->set_ctl(par, BS_DC, 1);
152
153         for (i = 0; i < argc; i++)
154                 broadsheet_gpio_issue_data(par, argv[i]);
155         par->board->set_ctl(par, BS_CS, 1);
156 }
157
158 static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
159                                     int argc, u16 *argv)
160 {
161         int i;
162
163         par->board->mmio_write(par, BS_MMIO_CMD, cmd);
164
165         for (i = 0; i < argc; i++)
166                 par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
167 }
168
169 static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
170 {
171         if (par->board->mmio_write)
172                 par->board->mmio_write(par, BS_MMIO_CMD, data);
173         else
174                 broadsheet_gpio_send_command(par, data);
175 }
176
177 static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
178                                     int argc, u16 *argv)
179 {
180         if (par->board->mmio_write)
181                 broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
182         else
183                 broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
184 }
185
186 static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
187                                         u16 *data)
188 {
189         int i;
190         u16 tmp;
191
192         par->board->set_ctl(par, BS_CS, 0);
193         par->board->set_ctl(par, BS_DC, 1);
194
195         for (i = 0; i < size; i++) {
196                 par->board->set_ctl(par, BS_WR, 0);
197                 tmp = (data[i] & 0x0F) << 4;
198                 tmp |= (data[i] & 0x0F00) << 4;
199                 par->board->set_hdb(par, tmp);
200                 par->board->set_ctl(par, BS_WR, 1);
201         }
202
203         par->board->set_ctl(par, BS_CS, 1);
204 }
205
206 static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
207                                    u16 *data)
208 {
209         int i;
210         u16 tmp;
211
212         for (i = 0; i < size; i++) {
213                 tmp = (data[i] & 0x0F) << 4;
214                 tmp |= (data[i] & 0x0F00) << 4;
215                 par->board->mmio_write(par, BS_MMIO_DATA, tmp);
216         }
217
218 }
219
220 static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
221                                    u16 *data)
222 {
223         if (par->board->mmio_write)
224                 broadsheet_mmio_burst_write(par, size, data);
225         else
226                 broadsheet_gpio_burst_write(par, size, data);
227 }
228
229 static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
230 {
231         u16 res;
232         /* wait for ready to go hi. (lo is busy) */
233         par->board->wait_for_rdy(par);
234
235         /* cs lo, dc lo for cmd, we lo for each data, db as usual */
236         par->board->set_ctl(par, BS_DC, 1);
237         par->board->set_ctl(par, BS_CS, 0);
238         par->board->set_ctl(par, BS_WR, 0);
239
240         res = par->board->get_hdb(par);
241
242         /* strobe wr */
243         par->board->set_ctl(par, BS_WR, 1);
244         par->board->set_ctl(par, BS_CS, 1);
245
246         return res;
247 }
248
249
250 static u16 broadsheet_get_data(struct broadsheetfb_par *par)
251 {
252         if (par->board->mmio_read)
253                 return par->board->mmio_read(par);
254         else
255                 return broadsheet_gpio_get_data(par);
256 }
257
258 static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
259                                         u16 data)
260 {
261         /* wait for ready to go hi. (lo is busy) */
262         par->board->wait_for_rdy(par);
263
264         /* cs lo, dc lo for cmd, we lo for each data, db as usual */
265         par->board->set_ctl(par, BS_CS, 0);
266
267         broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
268
269         par->board->set_ctl(par, BS_DC, 1);
270
271         broadsheet_gpio_issue_data(par, reg);
272         broadsheet_gpio_issue_data(par, data);
273
274         par->board->set_ctl(par, BS_CS, 1);
275 }
276
277 static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
278                                  u16 data)
279 {
280         par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
281         par->board->mmio_write(par, BS_MMIO_DATA, reg);
282         par->board->mmio_write(par, BS_MMIO_DATA, data);
283
284 }
285
286 static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
287                                         u16 data)
288 {
289         if (par->board->mmio_write)
290                 broadsheet_mmio_write_reg(par, reg, data);
291         else
292                 broadsheet_gpio_write_reg(par, reg, data);
293 }
294
295 static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
296                                         u32 data)
297 {
298         broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
299         broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
300 }
301
302
303 static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
304 {
305         broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
306         par->board->wait_for_rdy(par);
307         return broadsheet_get_data(par);
308 }
309
310 /* functions for waveform manipulation */
311 static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
312 {
313         return broadsheet_read_reg(par, 0x000A) & 0x0001;
314 }
315
316 static int broadsheet_setup_plls(struct broadsheetfb_par *par)
317 {
318         int retry_count = 0;
319         u16 tmp;
320
321         /* disable arral saemipu mode */
322         broadsheet_write_reg(par, 0x0006, 0x0000);
323
324         broadsheet_write_reg(par, 0x0010, 0x0004);
325         broadsheet_write_reg(par, 0x0012, 0x5949);
326         broadsheet_write_reg(par, 0x0014, 0x0040);
327         broadsheet_write_reg(par, 0x0016, 0x0000);
328
329         do {
330                 if (retry_count++ > 100)
331                         return -ETIMEDOUT;
332                 mdelay(1);
333         } while (!is_broadsheet_pll_locked(par));
334
335         tmp = broadsheet_read_reg(par, 0x0006);
336         tmp &= ~0x1;
337         broadsheet_write_reg(par, 0x0006, tmp);
338
339         return 0;
340 }
341
342 static int broadsheet_setup_spi(struct broadsheetfb_par *par)
343 {
344
345         broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
346         broadsheet_write_reg(par, 0x0208, 0x0001);
347
348         return 0;
349 }
350
351 static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
352                                                 u16 *orig_sfmcd)
353 {
354
355         *orig_sfmcd = broadsheet_read_reg(par, 0x0204);
356         broadsheet_write_reg(par, 0x0208, 0);
357         broadsheet_write_reg(par, 0x0204, 0);
358         broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
359
360         return 0;
361 }
362
363 static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
364                                                 u16 reg, int bitnum, int val,
365                                                 int timeout)
366 {
367         u16 tmp;
368
369         do {
370                 tmp = broadsheet_read_reg(par, reg);
371                 if (((tmp >> bitnum) & 1) == val)
372                         return 0;
373                 mdelay(1);
374         } while (timeout--);
375
376         return -ETIMEDOUT;
377 }
378
379 static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
380 {
381         broadsheet_write_reg(par, 0x0202, (data | 0x100));
382
383         return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
384 }
385
386 static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
387 {
388         int err;
389         u16 tmp;
390
391         broadsheet_write_reg(par, 0x0202, 0);
392
393         err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
394         if (err)
395                 return err;
396
397         tmp = broadsheet_read_reg(par, 0x200);
398
399         *data = tmp & 0xFF;
400
401         return 0;
402 }
403
404 static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
405                                                                 int timeout)
406 {
407         u8 tmp;
408         int err;
409
410         do {
411                 broadsheet_write_reg(par, 0x0208, 1);
412
413                 err = broadsheet_spiflash_write_byte(par, 0x05);
414                 if (err)
415                         goto failout;
416
417                 err = broadsheet_spiflash_read_byte(par, &tmp);
418                 if (err)
419                         goto failout;
420
421                 broadsheet_write_reg(par, 0x0208, 0);
422
423                 if (!(tmp & 0x1))
424                         return 0;
425
426                 mdelay(5);
427         } while (timeout--);
428
429         dev_err(par->info->device, "Timed out waiting for spiflash status\n");
430         return -ETIMEDOUT;
431
432 failout:
433         broadsheet_write_reg(par, 0x0208, 0);
434         return err;
435 }
436
437 static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
438                                                         u8 op, u32 addr)
439 {
440         int i;
441         u8 tmp;
442         int err;
443
444         broadsheet_write_reg(par, 0x0208, 1);
445
446         err = broadsheet_spiflash_write_byte(par, op);
447         if (err)
448                 return err;
449
450         for (i = 2; i >= 0; i--) {
451                 tmp = ((addr >> (i * 8)) & 0xFF);
452                 err = broadsheet_spiflash_write_byte(par, tmp);
453                 if (err)
454                         return err;
455         }
456
457         return err;
458 }
459
460 static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
461                                                 int *flash_type)
462 {
463         int err = 0;
464         u8 sig;
465
466         err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
467         if (err)
468                 goto failout;
469
470         err = broadsheet_spiflash_read_byte(par, &sig);
471         if (err)
472                 goto failout;
473
474         if ((sig != 0x10) && (sig != 0x11)) {
475                 dev_err(par->info->device, "Unexpected flash type\n");
476                 err = -EINVAL;
477                 goto failout;
478         }
479
480         *flash_type = sig;
481
482 failout:
483         broadsheet_write_reg(par, 0x0208, 0);
484         return err;
485 }
486
487 static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
488                                         u16 *initial_sfmcd, int *flash_type)
489
490 {
491         int err;
492
493         err = broadsheet_setup_plls(par);
494         if (err)
495                 return err;
496
497         broadsheet_write_reg(par, 0x0106, 0x0203);
498
499         err = broadsheet_setup_spi(par);
500         if (err)
501                 return err;
502
503         err = broadsheet_setup_spiflash(par, initial_sfmcd);
504         if (err)
505                 return err;
506
507         return broadsheet_verify_spiflash(par, flash_type);
508 }
509
510 static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
511                                                 int mode)
512 {
513         int err;
514
515         broadsheet_write_reg(par, 0x0208, 1);
516         if (mode)
517                 err = broadsheet_spiflash_write_byte(par, 0x06);
518         else
519                 err = broadsheet_spiflash_write_byte(par, 0x04);
520
521         broadsheet_write_reg(par, 0x0208, 0);
522         return err;
523 }
524
525 static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
526                                                 int addr)
527 {
528         int err;
529
530         broadsheet_spiflash_write_control(par, 1);
531
532         err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
533
534         broadsheet_write_reg(par, 0x0208, 0);
535
536         if (err)
537                 return err;
538
539         err = broadsheet_spiflash_wait_for_status(par, 1000);
540
541         return err;
542 }
543
544 static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
545                                                 int addr, int size, char *data)
546 {
547         int err;
548         int i;
549
550         err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
551         if (err)
552                 goto failout;
553
554         for (i = 0; i < size; i++) {
555                 err = broadsheet_spiflash_read_byte(par, &data[i]);
556                 if (err)
557                         goto failout;
558         }
559
560 failout:
561         broadsheet_write_reg(par, 0x0208, 0);
562         return err;
563 }
564
565 #define BS_SPIFLASH_PAGE_SIZE 256
566 static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
567                                                 int addr, const char *data)
568 {
569         int err;
570         int i;
571
572         broadsheet_spiflash_write_control(par, 1);
573
574         err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
575         if (err)
576                 goto failout;
577
578         for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
579                 err = broadsheet_spiflash_write_byte(par, data[i]);
580                 if (err)
581                         goto failout;
582         }
583
584         broadsheet_write_reg(par, 0x0208, 0);
585
586         err = broadsheet_spiflash_wait_for_status(par, 100);
587
588 failout:
589         return err;
590 }
591
592 static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
593                                 int addr, const char *data, int sector_size)
594 {
595         int i;
596         int err;
597
598         for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
599                 err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
600                 if (err)
601                         return err;
602         }
603         return 0;
604 }
605
606 /*
607  * The caller must guarantee that the data to be rewritten is entirely
608  * contained within this sector. That is, data_start_addr + data_len
609  * must be less than sector_start_addr + sector_size.
610  */
611 static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
612                                         int sector_size, int data_start_addr,
613                                         int data_len, const char *data)
614 {
615         int err;
616         char *sector_buffer;
617         int tail_start_addr;
618         int start_sector_addr;
619
620         sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
621         if (!sector_buffer)
622                 return -ENOMEM;
623
624         /* the start address of the sector is the 0th byte of that sector */
625         start_sector_addr = (data_start_addr / sector_size) * sector_size;
626
627         /*
628          * check if there is head data that we need to readback into our sector
629          * buffer first
630          */
631         if (data_start_addr != start_sector_addr) {
632                 /*
633                  * we need to read every byte up till the start address of our
634                  * data and we put it into our sector buffer.
635                  */
636                 err = broadsheet_spiflash_read_range(par, start_sector_addr,
637                                                 data_start_addr, sector_buffer);
638                 if (err)
639                         return err;
640         }
641
642         /* now we copy our data into the right place in the sector buffer */
643         memcpy(sector_buffer + data_start_addr, data, data_len);
644
645         /*
646          * now we check if there is a tail section of the sector that we need to
647          * readback.
648          */
649         tail_start_addr = (data_start_addr + data_len) % sector_size;
650
651         if (tail_start_addr) {
652                 int tail_len;
653
654                 tail_len = sector_size - tail_start_addr;
655
656                 /* now we read this tail into our sector buffer */
657                 err = broadsheet_spiflash_read_range(par, tail_start_addr,
658                         tail_len, sector_buffer + tail_start_addr);
659                 if (err)
660                         return err;
661         }
662
663         /* if we got here we have the full sector that we want to rewrite. */
664
665         /* first erase the sector */
666         err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
667         if (err)
668                 return err;
669
670         /* now write it */
671         err = broadsheet_spiflash_write_sector(par, start_sector_addr,
672                                         sector_buffer, sector_size);
673         return err;
674 }
675
676 static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
677                                 const u8 *wfm, int bytecount, int flash_type)
678 {
679         int sector_size;
680         int err;
681         int cur_addr;
682         int writecount;
683         int maxlen;
684         int offset = 0;
685
686         switch (flash_type) {
687         case 0x10:
688                 sector_size = 32*1024;
689                 break;
690         case 0x11:
691         default:
692                 sector_size = 64*1024;
693                 break;
694         }
695
696         while (bytecount) {
697                 cur_addr = wfm_addr + offset;
698                 maxlen = roundup(cur_addr, sector_size) - cur_addr;
699                 writecount = min(bytecount, maxlen);
700
701                 err = broadsheet_spiflash_rewrite_sector(par, sector_size,
702                                 cur_addr, writecount, wfm + offset);
703                 if (err)
704                         return err;
705
706                 offset += writecount;
707                 bytecount -= writecount;
708         }
709
710         return 0;
711 }
712
713 static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
714                                                 const u8 *wfm, size_t wfm_size)
715 {
716         int err = 0;
717         u16 initial_sfmcd = 0;
718         int flash_type = 0;
719
720         err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
721         if (err)
722                 goto failout;
723
724         err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
725
726 failout:
727         broadsheet_write_reg(par, 0x0204, initial_sfmcd);
728         return err;
729 }
730
731 static ssize_t broadsheet_loadstore_waveform(struct device *dev,
732                                                 struct device_attribute *attr,
733                                                 const char *buf, size_t len)
734 {
735         int err;
736         struct fb_info *info = dev_get_drvdata(dev);
737         struct broadsheetfb_par *par = info->par;
738         const struct firmware *fw_entry;
739
740         if (len < 1)
741                 return -EINVAL;
742
743         err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
744         if (err < 0) {
745                 dev_err(dev, "Failed to get broadsheet waveform\n");
746                 goto err_failed;
747         }
748
749         /* try to enforce reasonable min max on waveform */
750         if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
751                 dev_err(dev, "Invalid waveform\n");
752                 err = -EINVAL;
753                 goto err_failed;
754         }
755
756         mutex_lock(&(par->io_lock));
757         err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
758                                                         fw_entry->size);
759
760         mutex_unlock(&(par->io_lock));
761         if (err < 0) {
762                 dev_err(dev, "Failed to store broadsheet waveform\n");
763                 goto err_failed;
764         }
765
766         dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
767
768         return len;
769
770 err_failed:
771         return err;
772 }
773 static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
774                         broadsheet_loadstore_waveform);
775
776 /* upper level functions that manipulate the display and other stuff */
777 static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
778 {
779         u16 args[5];
780         int xres = par->info->var.xres;
781         int yres = par->info->var.yres;
782
783         args[0] = panel_table[par->panel_index].w;
784         args[1] = panel_table[par->panel_index].h;
785         args[2] = panel_table[par->panel_index].sdcfg;
786         args[3] = panel_table[par->panel_index].gdcfg;
787         args[4] = panel_table[par->panel_index].lutfmt;
788         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
789
790         /* did the controller really set it? */
791         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
792
793         args[0] = panel_table[par->panel_index].fsynclen;
794         args[1] = panel_table[par->panel_index].fendfbegin;
795         args[2] = panel_table[par->panel_index].lsynclen;
796         args[3] = panel_table[par->panel_index].lendlbegin;
797         args[4] = panel_table[par->panel_index].pixclk;
798         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
799
800         broadsheet_write_reg32(par, 0x310, xres*yres*2);
801
802         /* setup waveform */
803         args[0] = 0x886;
804         args[1] = 0;
805         broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
806
807         broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
808
809         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
810
811         broadsheet_write_reg(par, 0x330, 0x84);
812
813         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
814
815         args[0] = (0x3 << 4);
816         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
817
818         args[0] = 0x154;
819         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
820
821         broadsheet_burst_write(par, (panel_table[par->panel_index].w *
822                                         panel_table[par->panel_index].h)/2,
823                                         (u16 *) par->info->screen_base);
824
825         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
826
827         args[0] = 0x4300;
828         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
829
830         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
831
832         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
833
834         par->board->wait_for_rdy(par);
835 }
836
837 static void __devinit broadsheet_identify(struct broadsheetfb_par *par)
838 {
839         u16 rev, prc;
840         struct device *dev = par->info->device;
841
842         rev = broadsheet_read_reg(par, BS_REG_REV);
843         prc = broadsheet_read_reg(par, BS_REG_PRC);
844         dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
845
846         if (prc != 0x0047)
847                 dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
848         if (rev != 0x0100)
849                 dev_warn(dev, "Unrecognized Broadsheet Revision\n");
850 }
851
852 static void __devinit broadsheet_init(struct broadsheetfb_par *par)
853 {
854         broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
855         /* the controller needs a second */
856         msleep(1000);
857         broadsheet_init_display(par);
858 }
859
860 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
861                                                 u16 y1, u16 y2)
862 {
863         u16 args[5];
864         unsigned char *buf = (unsigned char *)par->info->screen_base;
865
866         mutex_lock(&(par->io_lock));
867         /* y1 must be a multiple of 4 so drop the lower bits */
868         y1 &= 0xFFFC;
869         /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
870         y2 |= 0x0003;
871
872         args[0] = 0x3 << 4;
873         args[1] = 0;
874         args[2] = y1;
875         args[3] = cpu_to_le16(par->info->var.xres);
876         args[4] = y2;
877         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
878
879         args[0] = 0x154;
880         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
881
882         buf += y1 * par->info->var.xres;
883         broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
884                                 (u16 *) buf);
885
886         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
887
888         args[0] = 0x4300;
889         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
890
891         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
892
893         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
894
895         par->board->wait_for_rdy(par);
896         mutex_unlock(&(par->io_lock));
897
898 }
899
900 static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
901 {
902         u16 args[5];
903
904         mutex_lock(&(par->io_lock));
905         args[0] = 0x3 << 4;
906         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
907
908         args[0] = 0x154;
909         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
910         broadsheet_burst_write(par, (panel_table[par->panel_index].w *
911                                         panel_table[par->panel_index].h)/2,
912                                         (u16 *) par->info->screen_base);
913
914         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
915
916         args[0] = 0x4300;
917         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
918
919         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
920
921         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
922
923         par->board->wait_for_rdy(par);
924         mutex_unlock(&(par->io_lock));
925 }
926
927 /* this is called back from the deferred io workqueue */
928 static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
929                                 struct list_head *pagelist)
930 {
931         u16 y1 = 0, h = 0;
932         int prev_index = -1;
933         struct page *cur;
934         struct fb_deferred_io *fbdefio = info->fbdefio;
935         int h_inc;
936         u16 yres = info->var.yres;
937         u16 xres = info->var.xres;
938
939         /* height increment is fixed per page */
940         h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
941
942         /* walk the written page list and swizzle the data */
943         list_for_each_entry(cur, &fbdefio->pagelist, lru) {
944                 if (prev_index < 0) {
945                         /* just starting so assign first page */
946                         y1 = (cur->index << PAGE_SHIFT) / xres;
947                         h = h_inc;
948                 } else if ((prev_index + 1) == cur->index) {
949                         /* this page is consecutive so increase our height */
950                         h += h_inc;
951                 } else {
952                         /* page not consecutive, issue previous update first */
953                         broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
954                         /* start over with our non consecutive page */
955                         y1 = (cur->index << PAGE_SHIFT) / xres;
956                         h = h_inc;
957                 }
958                 prev_index = cur->index;
959         }
960
961         /* if we still have any pages to update we do so now */
962         if (h >= yres) {
963                 /* its a full screen update, just do it */
964                 broadsheetfb_dpy_update(info->par);
965         } else {
966                 broadsheetfb_dpy_update_pages(info->par, y1,
967                                                 min((u16) (y1 + h), yres));
968         }
969 }
970
971 static void broadsheetfb_fillrect(struct fb_info *info,
972                                    const struct fb_fillrect *rect)
973 {
974         struct broadsheetfb_par *par = info->par;
975
976         sys_fillrect(info, rect);
977
978         broadsheetfb_dpy_update(par);
979 }
980
981 static void broadsheetfb_copyarea(struct fb_info *info,
982                                    const struct fb_copyarea *area)
983 {
984         struct broadsheetfb_par *par = info->par;
985
986         sys_copyarea(info, area);
987
988         broadsheetfb_dpy_update(par);
989 }
990
991 static void broadsheetfb_imageblit(struct fb_info *info,
992                                 const struct fb_image *image)
993 {
994         struct broadsheetfb_par *par = info->par;
995
996         sys_imageblit(info, image);
997
998         broadsheetfb_dpy_update(par);
999 }
1000
1001 /*
1002  * this is the slow path from userspace. they can seek and write to
1003  * the fb. it's inefficient to do anything less than a full screen draw
1004  */
1005 static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
1006                                 size_t count, loff_t *ppos)
1007 {
1008         struct broadsheetfb_par *par = info->par;
1009         unsigned long p = *ppos;
1010         void *dst;
1011         int err = 0;
1012         unsigned long total_size;
1013
1014         if (info->state != FBINFO_STATE_RUNNING)
1015                 return -EPERM;
1016
1017         total_size = info->fix.smem_len;
1018
1019         if (p > total_size)
1020                 return -EFBIG;
1021
1022         if (count > total_size) {
1023                 err = -EFBIG;
1024                 count = total_size;
1025         }
1026
1027         if (count + p > total_size) {
1028                 if (!err)
1029                         err = -ENOSPC;
1030
1031                 count = total_size - p;
1032         }
1033
1034         dst = (void *)(info->screen_base + p);
1035
1036         if (copy_from_user(dst, buf, count))
1037                 err = -EFAULT;
1038
1039         if  (!err)
1040                 *ppos += count;
1041
1042         broadsheetfb_dpy_update(par);
1043
1044         return (err) ? err : count;
1045 }
1046
1047 static struct fb_ops broadsheetfb_ops = {
1048         .owner          = THIS_MODULE,
1049         .fb_read        = fb_sys_read,
1050         .fb_write       = broadsheetfb_write,
1051         .fb_fillrect    = broadsheetfb_fillrect,
1052         .fb_copyarea    = broadsheetfb_copyarea,
1053         .fb_imageblit   = broadsheetfb_imageblit,
1054 };
1055
1056 static struct fb_deferred_io broadsheetfb_defio = {
1057         .delay          = HZ/4,
1058         .deferred_io    = broadsheetfb_dpy_deferred_io,
1059 };
1060
1061 static int __devinit broadsheetfb_probe(struct platform_device *dev)
1062 {
1063         struct fb_info *info;
1064         struct broadsheet_board *board;
1065         int retval = -ENOMEM;
1066         int videomemorysize;
1067         unsigned char *videomemory;
1068         struct broadsheetfb_par *par;
1069         int i;
1070         int dpyw, dpyh;
1071         int panel_index;
1072
1073         /* pick up board specific routines */
1074         board = dev->dev.platform_data;
1075         if (!board)
1076                 return -EINVAL;
1077
1078         /* try to count device specific driver, if can't, platform recalls */
1079         if (!try_module_get(board->owner))
1080                 return -ENODEV;
1081
1082         info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1083         if (!info)
1084                 goto err;
1085
1086         switch (board->get_panel_type()) {
1087         case 37:
1088                 panel_index = 1;
1089                 break;
1090         case 97:
1091                 panel_index = 2;
1092                 break;
1093         case 6:
1094         default:
1095                 panel_index = 0;
1096                 break;
1097         }
1098
1099         dpyw = panel_table[panel_index].w;
1100         dpyh = panel_table[panel_index].h;
1101
1102         videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1103
1104         videomemory = vmalloc(videomemorysize);
1105         if (!videomemory)
1106                 goto err_fb_rel;
1107
1108         memset(videomemory, 0, videomemorysize);
1109
1110         info->screen_base = (char *)videomemory;
1111         info->fbops = &broadsheetfb_ops;
1112
1113         broadsheetfb_var.xres = dpyw;
1114         broadsheetfb_var.yres = dpyh;
1115         broadsheetfb_var.xres_virtual = dpyw;
1116         broadsheetfb_var.yres_virtual = dpyh;
1117         info->var = broadsheetfb_var;
1118
1119         broadsheetfb_fix.line_length = dpyw;
1120         info->fix = broadsheetfb_fix;
1121         info->fix.smem_len = videomemorysize;
1122         par = info->par;
1123         par->panel_index = panel_index;
1124         par->info = info;
1125         par->board = board;
1126         par->write_reg = broadsheet_write_reg;
1127         par->read_reg = broadsheet_read_reg;
1128         init_waitqueue_head(&par->waitq);
1129
1130         mutex_init(&par->io_lock);
1131
1132         info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
1133
1134         info->fbdefio = &broadsheetfb_defio;
1135         fb_deferred_io_init(info);
1136
1137         retval = fb_alloc_cmap(&info->cmap, 16, 0);
1138         if (retval < 0) {
1139                 dev_err(&dev->dev, "Failed to allocate colormap\n");
1140                 goto err_vfree;
1141         }
1142
1143         /* set cmap */
1144         for (i = 0; i < 16; i++)
1145                 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1146         memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1147         memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1148
1149         retval = par->board->setup_irq(info);
1150         if (retval < 0)
1151                 goto err_cmap;
1152
1153         /* this inits the dpy */
1154         retval = board->init(par);
1155         if (retval < 0)
1156                 goto err_free_irq;
1157
1158         broadsheet_identify(par);
1159
1160         broadsheet_init(par);
1161
1162         retval = register_framebuffer(info);
1163         if (retval < 0)
1164                 goto err_free_irq;
1165
1166         platform_set_drvdata(dev, info);
1167
1168         retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1169         if (retval < 0)
1170                 goto err_unreg_fb;
1171
1172         printk(KERN_INFO
1173                "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
1174                info->node, videomemorysize >> 10);
1175
1176
1177         return 0;
1178
1179 err_unreg_fb:
1180         unregister_framebuffer(info);
1181 err_free_irq:
1182         board->cleanup(par);
1183 err_cmap:
1184         fb_dealloc_cmap(&info->cmap);
1185 err_vfree:
1186         vfree(videomemory);
1187 err_fb_rel:
1188         framebuffer_release(info);
1189 err:
1190         module_put(board->owner);
1191         return retval;
1192
1193 }
1194
1195 static int __devexit broadsheetfb_remove(struct platform_device *dev)
1196 {
1197         struct fb_info *info = platform_get_drvdata(dev);
1198
1199         if (info) {
1200                 struct broadsheetfb_par *par = info->par;
1201
1202                 device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1203                 unregister_framebuffer(info);
1204                 fb_deferred_io_cleanup(info);
1205                 par->board->cleanup(par);
1206                 fb_dealloc_cmap(&info->cmap);
1207                 vfree((void *)info->screen_base);
1208                 module_put(par->board->owner);
1209                 framebuffer_release(info);
1210         }
1211         return 0;
1212 }
1213
1214 static struct platform_driver broadsheetfb_driver = {
1215         .probe  = broadsheetfb_probe,
1216         .remove = broadsheetfb_remove,
1217         .driver = {
1218                 .owner  = THIS_MODULE,
1219                 .name   = "broadsheetfb",
1220         },
1221 };
1222
1223 static int __init broadsheetfb_init(void)
1224 {
1225         return platform_driver_register(&broadsheetfb_driver);
1226 }
1227
1228 static void __exit broadsheetfb_exit(void)
1229 {
1230         platform_driver_unregister(&broadsheetfb_driver);
1231 }
1232
1233 module_init(broadsheetfb_init);
1234 module_exit(broadsheetfb_exit);
1235
1236 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1237 MODULE_AUTHOR("Jaya Kumar");
1238 MODULE_LICENSE("GPL");