aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/broadsheetfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/broadsheetfb.c')
-rw-r--r--drivers/video/broadsheetfb.c738
1 files changed, 704 insertions, 34 deletions
diff --git a/drivers/video/broadsheetfb.c b/drivers/video/broadsheetfb.c
index df9ccb901d86..ebda6876d3a9 100644
--- a/drivers/video/broadsheetfb.c
+++ b/drivers/video/broadsheetfb.c
@@ -29,11 +29,65 @@
29#include <linux/init.h> 29#include <linux/init.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/list.h> 31#include <linux/list.h>
32#include <linux/firmware.h>
32#include <linux/uaccess.h> 33#include <linux/uaccess.h>
33 34
34#include <video/broadsheetfb.h> 35#include <video/broadsheetfb.h>
35 36
36/* Display specific information */ 37/* track panel specific parameters */
38struct 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 */
52static 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
37#define DPY_W 800 91#define DPY_W 800
38#define DPY_H 600 92#define DPY_H 600
39 93
@@ -62,30 +116,30 @@ static struct fb_var_screeninfo broadsheetfb_var __devinitdata = {
62}; 116};
63 117
64/* main broadsheetfb functions */ 118/* main broadsheetfb functions */
65static void broadsheet_issue_data(struct broadsheetfb_par *par, u16 data) 119static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
66{ 120{
67 par->board->set_ctl(par, BS_WR, 0); 121 par->board->set_ctl(par, BS_WR, 0);
68 par->board->set_hdb(par, data); 122 par->board->set_hdb(par, data);
69 par->board->set_ctl(par, BS_WR, 1); 123 par->board->set_ctl(par, BS_WR, 1);
70} 124}
71 125
72static void broadsheet_issue_cmd(struct broadsheetfb_par *par, u16 data) 126static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
73{ 127{
74 par->board->set_ctl(par, BS_DC, 0); 128 par->board->set_ctl(par, BS_DC, 0);
75 broadsheet_issue_data(par, data); 129 broadsheet_gpio_issue_data(par, data);
76} 130}
77 131
78static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) 132static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
79{ 133{
80 par->board->wait_for_rdy(par); 134 par->board->wait_for_rdy(par);
81 135
82 par->board->set_ctl(par, BS_CS, 0); 136 par->board->set_ctl(par, BS_CS, 0);
83 broadsheet_issue_cmd(par, data); 137 broadsheet_gpio_issue_cmd(par, data);
84 par->board->set_ctl(par, BS_DC, 1); 138 par->board->set_ctl(par, BS_DC, 1);
85 par->board->set_ctl(par, BS_CS, 1); 139 par->board->set_ctl(par, BS_CS, 1);
86} 140}
87 141
88static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, 142static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
89 int argc, u16 *argv) 143 int argc, u16 *argv)
90{ 144{
91 int i; 145 int i;
@@ -93,15 +147,43 @@ static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
93 par->board->wait_for_rdy(par); 147 par->board->wait_for_rdy(par);
94 148
95 par->board->set_ctl(par, BS_CS, 0); 149 par->board->set_ctl(par, BS_CS, 0);
96 broadsheet_issue_cmd(par, cmd); 150 broadsheet_gpio_issue_cmd(par, cmd);
97 par->board->set_ctl(par, BS_DC, 1); 151 par->board->set_ctl(par, BS_DC, 1);
98 152
99 for (i = 0; i < argc; i++) 153 for (i = 0; i < argc; i++)
100 broadsheet_issue_data(par, argv[i]); 154 broadsheet_gpio_issue_data(par, argv[i]);
101 par->board->set_ctl(par, BS_CS, 1); 155 par->board->set_ctl(par, BS_CS, 1);
102} 156}
103 157
104static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, 158static 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
169static 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
177static 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
186static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
105 u16 *data) 187 u16 *data)
106{ 188{
107 int i; 189 int i;
@@ -121,7 +203,30 @@ static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
121 par->board->set_ctl(par, BS_CS, 1); 203 par->board->set_ctl(par, BS_CS, 1);
122} 204}
123 205
124static u16 broadsheet_get_data(struct broadsheetfb_par *par) 206static 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
220static 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
229static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
125{ 230{
126 u16 res; 231 u16 res;
127 /* wait for ready to go hi. (lo is busy) */ 232 /* wait for ready to go hi. (lo is busy) */
@@ -141,7 +246,16 @@ static u16 broadsheet_get_data(struct broadsheetfb_par *par)
141 return res; 246 return res;
142} 247}
143 248
144static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, 249
250static 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
258static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
145 u16 data) 259 u16 data)
146{ 260{
147 /* wait for ready to go hi. (lo is busy) */ 261 /* wait for ready to go hi. (lo is busy) */
@@ -150,44 +264,541 @@ static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
150 /* cs lo, dc lo for cmd, we lo for each data, db as usual */ 264 /* cs lo, dc lo for cmd, we lo for each data, db as usual */
151 par->board->set_ctl(par, BS_CS, 0); 265 par->board->set_ctl(par, BS_CS, 0);
152 266
153 broadsheet_issue_cmd(par, BS_CMD_WR_REG); 267 broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
154 268
155 par->board->set_ctl(par, BS_DC, 1); 269 par->board->set_ctl(par, BS_DC, 1);
156 270
157 broadsheet_issue_data(par, reg); 271 broadsheet_gpio_issue_data(par, reg);
158 broadsheet_issue_data(par, data); 272 broadsheet_gpio_issue_data(par, data);
159 273
160 par->board->set_ctl(par, BS_CS, 1); 274 par->board->set_ctl(par, BS_CS, 1);
161} 275}
162 276
277static 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
286static 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
295static 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
163static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg) 303static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
164{ 304{
165 broadsheet_send_command(par, reg); 305 broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
166 msleep(100); 306 par->board->wait_for_rdy(par);
167 return broadsheet_get_data(par); 307 return broadsheet_get_data(par);
168} 308}
169 309
310/* functions for waveform manipulation */
311static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
312{
313 return broadsheet_read_reg(par, 0x000A) & 0x0001;
314}
315
316static 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
342static 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
351static 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
363static 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
379static 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
386static 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
404static 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
432failout:
433 broadsheet_write_reg(par, 0x0208, 0);
434 return err;
435}
436
437static 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
460static 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
482failout:
483 broadsheet_write_reg(par, 0x0208, 0);
484 return err;
485}
486
487static 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
510static 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
525static 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
544static 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
560failout:
561 broadsheet_write_reg(par, 0x0208, 0);
562 return err;
563}
564
565#define BS_SPIFLASH_PAGE_SIZE 256
566static 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
588failout:
589 return err;
590}
591
592static 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 */
611static 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
676static 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
713static 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
726failout:
727 broadsheet_write_reg(par, 0x0204, initial_sfmcd);
728 return err;
729}
730
731static 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
770err_failed:
771 return err;
772}
773static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
774 broadsheet_loadstore_waveform);
775
776/* upper level functions that manipulate the display and other stuff */
170static void __devinit broadsheet_init_display(struct broadsheetfb_par *par) 777static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
171{ 778{
172 u16 args[5]; 779 u16 args[5];
173 780 int xres = par->info->var.xres;
174 args[0] = DPY_W; 781 int yres = par->info->var.yres;
175 args[1] = DPY_H; 782
176 args[2] = (100 | (1 << 8) | (1 << 9)); /* sdcfg */ 783 args[0] = panel_table[par->panel_index].w;
177 args[3] = 2; /* gdrv cfg */ 784 args[1] = panel_table[par->panel_index].h;
178 args[4] = (4 | (1 << 7)); /* lut index format */ 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;
179 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 788 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
180 789
181 /* did the controller really set it? */ 790 /* did the controller really set it? */
182 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 791 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
183 792
184 args[0] = 4; /* fsync len */ 793 args[0] = panel_table[par->panel_index].fsynclen;
185 args[1] = (10 << 8) | 4; /* fend/fbegin len */ 794 args[1] = panel_table[par->panel_index].fendfbegin;
186 args[2] = 10; /* line sync len */ 795 args[2] = panel_table[par->panel_index].lsynclen;
187 args[3] = (100 << 8) | 4; /* line end/begin len */ 796 args[3] = panel_table[par->panel_index].lendlbegin;
188 args[4] = 6; /* pixel clock cfg */ 797 args[4] = panel_table[par->panel_index].pixclk;
189 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); 798 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
190 799
800 broadsheet_write_reg32(par, 0x310, xres*yres*2);
801
191 /* setup waveform */ 802 /* setup waveform */
192 args[0] = 0x886; 803 args[0] = 0x886;
193 args[1] = 0; 804 args[1] = 0;
@@ -207,8 +818,9 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
207 args[0] = 0x154; 818 args[0] = 0x154;
208 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 819 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
209 820
210 broadsheet_burst_write(par, DPY_W*DPY_H/2, 821 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
211 (u16 *) par->info->screen_base); 822 panel_table[par->panel_index].h)/2,
823 (u16 *) par->info->screen_base);
212 824
213 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 825 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
214 826
@@ -222,6 +834,21 @@ static void __devinit broadsheet_init_display(struct broadsheetfb_par *par)
222 par->board->wait_for_rdy(par); 834 par->board->wait_for_rdy(par);
223} 835}
224 836
837static 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
225static void __devinit broadsheet_init(struct broadsheetfb_par *par) 852static void __devinit broadsheet_init(struct broadsheetfb_par *par)
226{ 853{
227 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); 854 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
@@ -236,6 +863,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
236 u16 args[5]; 863 u16 args[5];
237 unsigned char *buf = (unsigned char *)par->info->screen_base; 864 unsigned char *buf = (unsigned char *)par->info->screen_base;
238 865
866 mutex_lock(&(par->io_lock));
239 /* y1 must be a multiple of 4 so drop the lower bits */ 867 /* y1 must be a multiple of 4 so drop the lower bits */
240 y1 &= 0xFFFC; 868 y1 &= 0xFFFC;
241 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ 869 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
@@ -265,6 +893,7 @@ static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
265 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 893 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
266 894
267 par->board->wait_for_rdy(par); 895 par->board->wait_for_rdy(par);
896 mutex_unlock(&(par->io_lock));
268 897
269} 898}
270 899
@@ -272,13 +901,15 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
272{ 901{
273 u16 args[5]; 902 u16 args[5];
274 903
904 mutex_lock(&(par->io_lock));
275 args[0] = 0x3 << 4; 905 args[0] = 0x3 << 4;
276 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 906 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
277 907
278 args[0] = 0x154; 908 args[0] = 0x154;
279 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 909 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
280 broadsheet_burst_write(par, DPY_W*DPY_H/2, 910 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
281 (u16 *) par->info->screen_base); 911 panel_table[par->panel_index].h)/2,
912 (u16 *) par->info->screen_base);
282 913
283 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 914 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
284 915
@@ -290,7 +921,7 @@ static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
290 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 921 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
291 922
292 par->board->wait_for_rdy(par); 923 par->board->wait_for_rdy(par);
293 924 mutex_unlock(&(par->io_lock));
294} 925}
295 926
296/* this is called back from the deferred io workqueue */ 927/* this is called back from the deferred io workqueue */
@@ -436,6 +1067,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
436 unsigned char *videomemory; 1067 unsigned char *videomemory;
437 struct broadsheetfb_par *par; 1068 struct broadsheetfb_par *par;
438 int i; 1069 int i;
1070 int dpyw, dpyh;
1071 int panel_index;
439 1072
440 /* pick up board specific routines */ 1073 /* pick up board specific routines */
441 board = dev->dev.platform_data; 1074 board = dev->dev.platform_data;
@@ -450,7 +1083,24 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
450 if (!info) 1083 if (!info)
451 goto err; 1084 goto err;
452 1085
453 videomemorysize = (DPY_W*DPY_H); 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
454 videomemory = vmalloc(videomemorysize); 1104 videomemory = vmalloc(videomemorysize);
455 if (!videomemory) 1105 if (!videomemory)
456 goto err_fb_rel; 1106 goto err_fb_rel;
@@ -460,16 +1110,25 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
460 info->screen_base = (char *)videomemory; 1110 info->screen_base = (char *)videomemory;
461 info->fbops = &broadsheetfb_ops; 1111 info->fbops = &broadsheetfb_ops;
462 1112
1113 broadsheetfb_var.xres = dpyw;
1114 broadsheetfb_var.yres = dpyh;
1115 broadsheetfb_var.xres_virtual = dpyw;
1116 broadsheetfb_var.yres_virtual = dpyh;
463 info->var = broadsheetfb_var; 1117 info->var = broadsheetfb_var;
1118
1119 broadsheetfb_fix.line_length = dpyw;
464 info->fix = broadsheetfb_fix; 1120 info->fix = broadsheetfb_fix;
465 info->fix.smem_len = videomemorysize; 1121 info->fix.smem_len = videomemorysize;
466 par = info->par; 1122 par = info->par;
1123 par->panel_index = panel_index;
467 par->info = info; 1124 par->info = info;
468 par->board = board; 1125 par->board = board;
469 par->write_reg = broadsheet_write_reg; 1126 par->write_reg = broadsheet_write_reg;
470 par->read_reg = broadsheet_read_reg; 1127 par->read_reg = broadsheet_read_reg;
471 init_waitqueue_head(&par->waitq); 1128 init_waitqueue_head(&par->waitq);
472 1129
1130 mutex_init(&par->io_lock);
1131
473 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; 1132 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
474 1133
475 info->fbdefio = &broadsheetfb_defio; 1134 info->fbdefio = &broadsheetfb_defio;
@@ -496,13 +1155,20 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
496 if (retval < 0) 1155 if (retval < 0)
497 goto err_free_irq; 1156 goto err_free_irq;
498 1157
1158 broadsheet_identify(par);
1159
499 broadsheet_init(par); 1160 broadsheet_init(par);
500 1161
501 retval = register_framebuffer(info); 1162 retval = register_framebuffer(info);
502 if (retval < 0) 1163 if (retval < 0)
503 goto err_free_irq; 1164 goto err_free_irq;
1165
504 platform_set_drvdata(dev, info); 1166 platform_set_drvdata(dev, info);
505 1167
1168 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1169 if (retval < 0)
1170 goto err_unreg_fb;
1171
506 printk(KERN_INFO 1172 printk(KERN_INFO
507 "fb%d: Broadsheet frame buffer, using %dK of video memory\n", 1173 "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
508 info->node, videomemorysize >> 10); 1174 info->node, videomemorysize >> 10);
@@ -510,6 +1176,8 @@ static int __devinit broadsheetfb_probe(struct platform_device *dev)
510 1176
511 return 0; 1177 return 0;
512 1178
1179err_unreg_fb:
1180 unregister_framebuffer(info);
513err_free_irq: 1181err_free_irq:
514 board->cleanup(par); 1182 board->cleanup(par);
515err_cmap: 1183err_cmap:
@@ -530,6 +1198,8 @@ static int __devexit broadsheetfb_remove(struct platform_device *dev)
530 1198
531 if (info) { 1199 if (info) {
532 struct broadsheetfb_par *par = info->par; 1200 struct broadsheetfb_par *par = info->par;
1201
1202 device_remove_file(info->dev, &dev_attr_loadstore_waveform);
533 unregister_framebuffer(info); 1203 unregister_framebuffer(info);
534 fb_deferred_io_cleanup(info); 1204 fb_deferred_io_cleanup(info);
535 par->board->cleanup(par); 1205 par->board->cleanup(par);