Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
broadsheetfb.c
Go to the documentation of this file.
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;
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,
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 = vzalloc(videomemorysize);
1105  if (!videomemory)
1106  goto err_fb_rel;
1107 
1108  info->screen_base = (char *)videomemory;
1109  info->fbops = &broadsheetfb_ops;
1110 
1111  broadsheetfb_var.xres = dpyw;
1112  broadsheetfb_var.yres = dpyh;
1113  broadsheetfb_var.xres_virtual = dpyw;
1114  broadsheetfb_var.yres_virtual = dpyh;
1115  info->var = broadsheetfb_var;
1116 
1117  broadsheetfb_fix.line_length = dpyw;
1118  info->fix = broadsheetfb_fix;
1119  info->fix.smem_len = videomemorysize;
1120  par = info->par;
1121  par->panel_index = panel_index;
1122  par->info = info;
1123  par->board = board;
1124  par->write_reg = broadsheet_write_reg;
1125  par->read_reg = broadsheet_read_reg;
1126  init_waitqueue_head(&par->waitq);
1127 
1128  mutex_init(&par->io_lock);
1129 
1131 
1132  info->fbdefio = &broadsheetfb_defio;
1133  fb_deferred_io_init(info);
1134 
1135  retval = fb_alloc_cmap(&info->cmap, 16, 0);
1136  if (retval < 0) {
1137  dev_err(&dev->dev, "Failed to allocate colormap\n");
1138  goto err_vfree;
1139  }
1140 
1141  /* set cmap */
1142  for (i = 0; i < 16; i++)
1143  info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1144  memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1145  memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1146 
1147  retval = par->board->setup_irq(info);
1148  if (retval < 0)
1149  goto err_cmap;
1150 
1151  /* this inits the dpy */
1152  retval = board->init(par);
1153  if (retval < 0)
1154  goto err_free_irq;
1155 
1156  broadsheet_identify(par);
1157 
1158  broadsheet_init(par);
1159 
1160  retval = register_framebuffer(info);
1161  if (retval < 0)
1162  goto err_free_irq;
1163 
1164  platform_set_drvdata(dev, info);
1165 
1166  retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1167  if (retval < 0)
1168  goto err_unreg_fb;
1169 
1171  "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
1172  info->node, videomemorysize >> 10);
1173 
1174 
1175  return 0;
1176 
1177 err_unreg_fb:
1178  unregister_framebuffer(info);
1179 err_free_irq:
1180  board->cleanup(par);
1181 err_cmap:
1182  fb_dealloc_cmap(&info->cmap);
1183 err_vfree:
1184  vfree(videomemory);
1185 err_fb_rel:
1186  framebuffer_release(info);
1187 err:
1188  module_put(board->owner);
1189  return retval;
1190 
1191 }
1192 
1193 static int __devexit broadsheetfb_remove(struct platform_device *dev)
1194 {
1195  struct fb_info *info = platform_get_drvdata(dev);
1196 
1197  if (info) {
1198  struct broadsheetfb_par *par = info->par;
1199 
1200  device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1201  unregister_framebuffer(info);
1202  fb_deferred_io_cleanup(info);
1203  par->board->cleanup(par);
1204  fb_dealloc_cmap(&info->cmap);
1205  vfree((void *)info->screen_base);
1206  module_put(par->board->owner);
1207  framebuffer_release(info);
1208  }
1209  return 0;
1210 }
1211 
1212 static struct platform_driver broadsheetfb_driver = {
1213  .probe = broadsheetfb_probe,
1214  .remove = __devexit_p(broadsheetfb_remove),
1215  .driver = {
1216  .owner = THIS_MODULE,
1217  .name = "broadsheetfb",
1218  },
1219 };
1220 
1221 static int __init broadsheetfb_init(void)
1222 {
1223  return platform_driver_register(&broadsheetfb_driver);
1224 }
1225 
1226 static void __exit broadsheetfb_exit(void)
1227 {
1228  platform_driver_unregister(&broadsheetfb_driver);
1229 }
1230 
1231 module_init(broadsheetfb_init);
1232 module_exit(broadsheetfb_exit);
1233 
1234 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1235 MODULE_AUTHOR("Jaya Kumar");
1236 MODULE_LICENSE("GPL");