root/drivers/video/fbdev/broadsheetfb.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. broadsheet_gpio_issue_data
  2. broadsheet_gpio_issue_cmd
  3. broadsheet_gpio_send_command
  4. broadsheet_gpio_send_cmdargs
  5. broadsheet_mmio_send_cmdargs
  6. broadsheet_send_command
  7. broadsheet_send_cmdargs
  8. broadsheet_gpio_burst_write
  9. broadsheet_mmio_burst_write
  10. broadsheet_burst_write
  11. broadsheet_gpio_get_data
  12. broadsheet_get_data
  13. broadsheet_gpio_write_reg
  14. broadsheet_mmio_write_reg
  15. broadsheet_write_reg
  16. broadsheet_write_reg32
  17. broadsheet_read_reg
  18. is_broadsheet_pll_locked
  19. broadsheet_setup_plls
  20. broadsheet_setup_spi
  21. broadsheet_setup_spiflash
  22. broadsheet_spiflash_wait_for_bit
  23. broadsheet_spiflash_write_byte
  24. broadsheet_spiflash_read_byte
  25. broadsheet_spiflash_wait_for_status
  26. broadsheet_spiflash_op_on_address
  27. broadsheet_verify_spiflash
  28. broadsheet_setup_for_wfm_write
  29. broadsheet_spiflash_write_control
  30. broadsheet_spiflash_erase_sector
  31. broadsheet_spiflash_read_range
  32. broadsheet_spiflash_write_page
  33. broadsheet_spiflash_write_sector
  34. broadsheet_spiflash_rewrite_sector
  35. broadsheet_write_spiflash
  36. broadsheet_store_waveform_to_spiflash
  37. broadsheet_loadstore_waveform
  38. broadsheet_init_display
  39. broadsheet_identify
  40. broadsheet_init
  41. broadsheetfb_dpy_update_pages
  42. broadsheetfb_dpy_update
  43. broadsheetfb_dpy_deferred_io
  44. broadsheetfb_fillrect
  45. broadsheetfb_copyarea
  46. broadsheetfb_imageblit
  47. broadsheetfb_write
  48. broadsheetfb_probe
  49. broadsheetfb_remove

   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 = {
  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 = {
 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(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                         goto out;
 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                         goto out;
 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                 goto out;
 669 
 670         /* now write it */
 671         err = broadsheet_spiflash_write_sector(par, start_sector_addr,
 672                                         sector_buffer, sector_size);
 673 out:
 674         kfree(sector_buffer);
 675         return err;
 676 }
 677 
 678 static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
 679                                 const u8 *wfm, int bytecount, int flash_type)
 680 {
 681         int sector_size;
 682         int err;
 683         int cur_addr;
 684         int writecount;
 685         int maxlen;
 686         int offset = 0;
 687 
 688         switch (flash_type) {
 689         case 0x10:
 690                 sector_size = 32*1024;
 691                 break;
 692         case 0x11:
 693         default:
 694                 sector_size = 64*1024;
 695                 break;
 696         }
 697 
 698         while (bytecount) {
 699                 cur_addr = wfm_addr + offset;
 700                 maxlen = roundup(cur_addr, sector_size) - cur_addr;
 701                 writecount = min(bytecount, maxlen);
 702 
 703                 err = broadsheet_spiflash_rewrite_sector(par, sector_size,
 704                                 cur_addr, writecount, wfm + offset);
 705                 if (err)
 706                         return err;
 707 
 708                 offset += writecount;
 709                 bytecount -= writecount;
 710         }
 711 
 712         return 0;
 713 }
 714 
 715 static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
 716                                                 const u8 *wfm, size_t wfm_size)
 717 {
 718         int err = 0;
 719         u16 initial_sfmcd = 0;
 720         int flash_type = 0;
 721 
 722         err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
 723         if (err)
 724                 goto failout;
 725 
 726         err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
 727 
 728 failout:
 729         broadsheet_write_reg(par, 0x0204, initial_sfmcd);
 730         return err;
 731 }
 732 
 733 static ssize_t broadsheet_loadstore_waveform(struct device *dev,
 734                                                 struct device_attribute *attr,
 735                                                 const char *buf, size_t len)
 736 {
 737         int err;
 738         struct fb_info *info = dev_get_drvdata(dev);
 739         struct broadsheetfb_par *par = info->par;
 740         const struct firmware *fw_entry;
 741 
 742         if (len < 1)
 743                 return -EINVAL;
 744 
 745         err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
 746         if (err < 0) {
 747                 dev_err(dev, "Failed to get broadsheet waveform\n");
 748                 goto err_failed;
 749         }
 750 
 751         /* try to enforce reasonable min max on waveform */
 752         if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
 753                 dev_err(dev, "Invalid waveform\n");
 754                 err = -EINVAL;
 755                 goto err_fw;
 756         }
 757 
 758         mutex_lock(&(par->io_lock));
 759         err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
 760                                                         fw_entry->size);
 761 
 762         mutex_unlock(&(par->io_lock));
 763         if (err < 0) {
 764                 dev_err(dev, "Failed to store broadsheet waveform\n");
 765                 goto err_fw;
 766         }
 767 
 768         dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
 769 
 770         err = len;
 771 
 772 err_fw:
 773         release_firmware(fw_entry);
 774 err_failed:
 775         return err;
 776 }
 777 static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
 778                         broadsheet_loadstore_waveform);
 779 
 780 /* upper level functions that manipulate the display and other stuff */
 781 static void broadsheet_init_display(struct broadsheetfb_par *par)
 782 {
 783         u16 args[5];
 784         int xres = par->info->var.xres;
 785         int yres = par->info->var.yres;
 786 
 787         args[0] = panel_table[par->panel_index].w;
 788         args[1] = panel_table[par->panel_index].h;
 789         args[2] = panel_table[par->panel_index].sdcfg;
 790         args[3] = panel_table[par->panel_index].gdcfg;
 791         args[4] = panel_table[par->panel_index].lutfmt;
 792         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
 793 
 794         /* did the controller really set it? */
 795         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
 796 
 797         args[0] = panel_table[par->panel_index].fsynclen;
 798         args[1] = panel_table[par->panel_index].fendfbegin;
 799         args[2] = panel_table[par->panel_index].lsynclen;
 800         args[3] = panel_table[par->panel_index].lendlbegin;
 801         args[4] = panel_table[par->panel_index].pixclk;
 802         broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
 803 
 804         broadsheet_write_reg32(par, 0x310, xres*yres*2);
 805 
 806         /* setup waveform */
 807         args[0] = 0x886;
 808         args[1] = 0;
 809         broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
 810 
 811         broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
 812 
 813         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
 814 
 815         broadsheet_write_reg(par, 0x330, 0x84);
 816 
 817         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
 818 
 819         args[0] = (0x3 << 4);
 820         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
 821 
 822         args[0] = 0x154;
 823         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
 824 
 825         broadsheet_burst_write(par, (panel_table[par->panel_index].w *
 826                                         panel_table[par->panel_index].h)/2,
 827                                         (u16 *) par->info->screen_base);
 828 
 829         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
 830 
 831         args[0] = 0x4300;
 832         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
 833 
 834         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
 835 
 836         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
 837 
 838         par->board->wait_for_rdy(par);
 839 }
 840 
 841 static void broadsheet_identify(struct broadsheetfb_par *par)
 842 {
 843         u16 rev, prc;
 844         struct device *dev = par->info->device;
 845 
 846         rev = broadsheet_read_reg(par, BS_REG_REV);
 847         prc = broadsheet_read_reg(par, BS_REG_PRC);
 848         dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
 849 
 850         if (prc != 0x0047)
 851                 dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
 852         if (rev != 0x0100)
 853                 dev_warn(dev, "Unrecognized Broadsheet Revision\n");
 854 }
 855 
 856 static void broadsheet_init(struct broadsheetfb_par *par)
 857 {
 858         broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
 859         /* the controller needs a second */
 860         msleep(1000);
 861         broadsheet_init_display(par);
 862 }
 863 
 864 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
 865                                                 u16 y1, u16 y2)
 866 {
 867         u16 args[5];
 868         unsigned char *buf = (unsigned char *)par->info->screen_base;
 869 
 870         mutex_lock(&(par->io_lock));
 871         /* y1 must be a multiple of 4 so drop the lower bits */
 872         y1 &= 0xFFFC;
 873         /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
 874         y2 |= 0x0003;
 875 
 876         args[0] = 0x3 << 4;
 877         args[1] = 0;
 878         args[2] = y1;
 879         args[3] = cpu_to_le16(par->info->var.xres);
 880         args[4] = y2;
 881         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
 882 
 883         args[0] = 0x154;
 884         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
 885 
 886         buf += y1 * par->info->var.xres;
 887         broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
 888                                 (u16 *) buf);
 889 
 890         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
 891 
 892         args[0] = 0x4300;
 893         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
 894 
 895         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
 896 
 897         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
 898 
 899         par->board->wait_for_rdy(par);
 900         mutex_unlock(&(par->io_lock));
 901 
 902 }
 903 
 904 static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
 905 {
 906         u16 args[5];
 907 
 908         mutex_lock(&(par->io_lock));
 909         args[0] = 0x3 << 4;
 910         broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
 911 
 912         args[0] = 0x154;
 913         broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
 914         broadsheet_burst_write(par, (panel_table[par->panel_index].w *
 915                                         panel_table[par->panel_index].h)/2,
 916                                         (u16 *) par->info->screen_base);
 917 
 918         broadsheet_send_command(par, BS_CMD_LD_IMG_END);
 919 
 920         args[0] = 0x4300;
 921         broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
 922 
 923         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
 924 
 925         broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
 926 
 927         par->board->wait_for_rdy(par);
 928         mutex_unlock(&(par->io_lock));
 929 }
 930 
 931 /* this is called back from the deferred io workqueue */
 932 static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
 933                                 struct list_head *pagelist)
 934 {
 935         u16 y1 = 0, h = 0;
 936         int prev_index = -1;
 937         struct page *cur;
 938         struct fb_deferred_io *fbdefio = info->fbdefio;
 939         int h_inc;
 940         u16 yres = info->var.yres;
 941         u16 xres = info->var.xres;
 942 
 943         /* height increment is fixed per page */
 944         h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
 945 
 946         /* walk the written page list and swizzle the data */
 947         list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 948                 if (prev_index < 0) {
 949                         /* just starting so assign first page */
 950                         y1 = (cur->index << PAGE_SHIFT) / xres;
 951                         h = h_inc;
 952                 } else if ((prev_index + 1) == cur->index) {
 953                         /* this page is consecutive so increase our height */
 954                         h += h_inc;
 955                 } else {
 956                         /* page not consecutive, issue previous update first */
 957                         broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
 958                         /* start over with our non consecutive page */
 959                         y1 = (cur->index << PAGE_SHIFT) / xres;
 960                         h = h_inc;
 961                 }
 962                 prev_index = cur->index;
 963         }
 964 
 965         /* if we still have any pages to update we do so now */
 966         if (h >= yres) {
 967                 /* its a full screen update, just do it */
 968                 broadsheetfb_dpy_update(info->par);
 969         } else {
 970                 broadsheetfb_dpy_update_pages(info->par, y1,
 971                                                 min((u16) (y1 + h), yres));
 972         }
 973 }
 974 
 975 static void broadsheetfb_fillrect(struct fb_info *info,
 976                                    const struct fb_fillrect *rect)
 977 {
 978         struct broadsheetfb_par *par = info->par;
 979 
 980         sys_fillrect(info, rect);
 981 
 982         broadsheetfb_dpy_update(par);
 983 }
 984 
 985 static void broadsheetfb_copyarea(struct fb_info *info,
 986                                    const struct fb_copyarea *area)
 987 {
 988         struct broadsheetfb_par *par = info->par;
 989 
 990         sys_copyarea(info, area);
 991 
 992         broadsheetfb_dpy_update(par);
 993 }
 994 
 995 static void broadsheetfb_imageblit(struct fb_info *info,
 996                                 const struct fb_image *image)
 997 {
 998         struct broadsheetfb_par *par = info->par;
 999 
1000         sys_imageblit(info, image);
1001 
1002         broadsheetfb_dpy_update(par);
1003 }
1004 
1005 /*
1006  * this is the slow path from userspace. they can seek and write to
1007  * the fb. it's inefficient to do anything less than a full screen draw
1008  */
1009 static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
1010                                 size_t count, loff_t *ppos)
1011 {
1012         struct broadsheetfb_par *par = info->par;
1013         unsigned long p = *ppos;
1014         void *dst;
1015         int err = 0;
1016         unsigned long total_size;
1017 
1018         if (info->state != FBINFO_STATE_RUNNING)
1019                 return -EPERM;
1020 
1021         total_size = info->fix.smem_len;
1022 
1023         if (p > total_size)
1024                 return -EFBIG;
1025 
1026         if (count > total_size) {
1027                 err = -EFBIG;
1028                 count = total_size;
1029         }
1030 
1031         if (count + p > total_size) {
1032                 if (!err)
1033                         err = -ENOSPC;
1034 
1035                 count = total_size - p;
1036         }
1037 
1038         dst = (void *)(info->screen_base + p);
1039 
1040         if (copy_from_user(dst, buf, count))
1041                 err = -EFAULT;
1042 
1043         if  (!err)
1044                 *ppos += count;
1045 
1046         broadsheetfb_dpy_update(par);
1047 
1048         return (err) ? err : count;
1049 }
1050 
1051 static struct fb_ops broadsheetfb_ops = {
1052         .owner          = THIS_MODULE,
1053         .fb_read        = fb_sys_read,
1054         .fb_write       = broadsheetfb_write,
1055         .fb_fillrect    = broadsheetfb_fillrect,
1056         .fb_copyarea    = broadsheetfb_copyarea,
1057         .fb_imageblit   = broadsheetfb_imageblit,
1058 };
1059 
1060 static struct fb_deferred_io broadsheetfb_defio = {
1061         .delay          = HZ/4,
1062         .deferred_io    = broadsheetfb_dpy_deferred_io,
1063 };
1064 
1065 static int broadsheetfb_probe(struct platform_device *dev)
1066 {
1067         struct fb_info *info;
1068         struct broadsheet_board *board;
1069         int retval = -ENOMEM;
1070         int videomemorysize;
1071         unsigned char *videomemory;
1072         struct broadsheetfb_par *par;
1073         int i;
1074         int dpyw, dpyh;
1075         int panel_index;
1076 
1077         /* pick up board specific routines */
1078         board = dev->dev.platform_data;
1079         if (!board)
1080                 return -EINVAL;
1081 
1082         /* try to count device specific driver, if can't, platform recalls */
1083         if (!try_module_get(board->owner))
1084                 return -ENODEV;
1085 
1086         info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1087         if (!info)
1088                 goto err;
1089 
1090         switch (board->get_panel_type()) {
1091         case 37:
1092                 panel_index = 1;
1093                 break;
1094         case 97:
1095                 panel_index = 2;
1096                 break;
1097         case 6:
1098         default:
1099                 panel_index = 0;
1100                 break;
1101         }
1102 
1103         dpyw = panel_table[panel_index].w;
1104         dpyh = panel_table[panel_index].h;
1105 
1106         videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1107 
1108         videomemory = vzalloc(videomemorysize);
1109         if (!videomemory)
1110                 goto err_fb_rel;
1111 
1112         info->screen_base = (char *)videomemory;
1113         info->fbops = &broadsheetfb_ops;
1114 
1115         broadsheetfb_var.xres = dpyw;
1116         broadsheetfb_var.yres = dpyh;
1117         broadsheetfb_var.xres_virtual = dpyw;
1118         broadsheetfb_var.yres_virtual = dpyh;
1119         info->var = broadsheetfb_var;
1120 
1121         broadsheetfb_fix.line_length = dpyw;
1122         info->fix = broadsheetfb_fix;
1123         info->fix.smem_len = videomemorysize;
1124         par = info->par;
1125         par->panel_index = panel_index;
1126         par->info = info;
1127         par->board = board;
1128         par->write_reg = broadsheet_write_reg;
1129         par->read_reg = broadsheet_read_reg;
1130         init_waitqueue_head(&par->waitq);
1131 
1132         mutex_init(&par->io_lock);
1133 
1134         info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
1135 
1136         info->fbdefio = &broadsheetfb_defio;
1137         fb_deferred_io_init(info);
1138 
1139         retval = fb_alloc_cmap(&info->cmap, 16, 0);
1140         if (retval < 0) {
1141                 dev_err(&dev->dev, "Failed to allocate colormap\n");
1142                 goto err_vfree;
1143         }
1144 
1145         /* set cmap */
1146         for (i = 0; i < 16; i++)
1147                 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1148         memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1149         memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1150 
1151         retval = par->board->setup_irq(info);
1152         if (retval < 0)
1153                 goto err_cmap;
1154 
1155         /* this inits the dpy */
1156         retval = board->init(par);
1157         if (retval < 0)
1158                 goto err_free_irq;
1159 
1160         broadsheet_identify(par);
1161 
1162         broadsheet_init(par);
1163 
1164         retval = register_framebuffer(info);
1165         if (retval < 0)
1166                 goto err_free_irq;
1167 
1168         platform_set_drvdata(dev, info);
1169 
1170         retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1171         if (retval < 0)
1172                 goto err_unreg_fb;
1173 
1174         fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
1175                 videomemorysize >> 10);
1176 
1177 
1178         return 0;
1179 
1180 err_unreg_fb:
1181         unregister_framebuffer(info);
1182 err_free_irq:
1183         board->cleanup(par);
1184 err_cmap:
1185         fb_dealloc_cmap(&info->cmap);
1186 err_vfree:
1187         vfree(videomemory);
1188 err_fb_rel:
1189         framebuffer_release(info);
1190 err:
1191         module_put(board->owner);
1192         return retval;
1193 
1194 }
1195 
1196 static int broadsheetfb_remove(struct platform_device *dev)
1197 {
1198         struct fb_info *info = platform_get_drvdata(dev);
1199 
1200         if (info) {
1201                 struct broadsheetfb_par *par = info->par;
1202 
1203                 device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1204                 unregister_framebuffer(info);
1205                 fb_deferred_io_cleanup(info);
1206                 par->board->cleanup(par);
1207                 fb_dealloc_cmap(&info->cmap);
1208                 vfree((void *)info->screen_base);
1209                 module_put(par->board->owner);
1210                 framebuffer_release(info);
1211         }
1212         return 0;
1213 }
1214 
1215 static struct platform_driver broadsheetfb_driver = {
1216         .probe  = broadsheetfb_probe,
1217         .remove = broadsheetfb_remove,
1218         .driver = {
1219                 .name   = "broadsheetfb",
1220         },
1221 };
1222 module_platform_driver(broadsheetfb_driver);
1223 
1224 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1225 MODULE_AUTHOR("Jaya Kumar");
1226 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */