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, ®); 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_buffer); 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 = par->info->screen_buffer; 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_buffer); 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, struct list_head *pagereflist) 933 { 934 u16 y1 = 0, h = 0; 935 unsigned long prev_offset = ULONG_MAX; 936 struct fb_deferred_io_pageref *pageref; 937 int h_inc; 938 u16 yres = info->var.yres; 939 u16 xres = info->var.xres; 940 941 /* height increment is fixed per page */ 942 h_inc = DIV_ROUND_UP(PAGE_SIZE , xres); 943 944 /* walk the written page list and swizzle the data */ 945 list_for_each_entry(pageref, pagereflist, list) { 946 if (prev_offset == ULONG_MAX) { 947 /* just starting so assign first page */ 948 y1 = pageref->offset / xres; 949 h = h_inc; 950 } else if ((prev_offset + PAGE_SIZE) == pageref->offset) { 951 /* this page is consecutive so increase our height */ 952 h += h_inc; 953 } else { 954 /* page not consecutive, issue previous update first */ 955 broadsheetfb_dpy_update_pages(info->par, y1, y1 + h); 956 /* start over with our non consecutive page */ 957 y1 = pageref->offset / xres; 958 h = h_inc; 959 } 960 prev_offset = pageref->offset; 961 } 962 963 /* if we still have any pages to update we do so now */ 964 if (h >= yres) { 965 /* its a full screen update, just do it */ 966 broadsheetfb_dpy_update(info->par); 967 } else { 968 broadsheetfb_dpy_update_pages(info->par, y1, 969 min((u16) (y1 + h), yres)); 970 } 971 } 972 973 static void broadsheetfb_defio_damage_range(struct fb_info *info, off_t off, size_t len) 974 { 975 struct broadsheetfb_par *par = info->par; 976 977 broadsheetfb_dpy_update(par); 978 } 979 980 static void broadsheetfb_defio_damage_area(struct fb_info *info, u32 x, u32 y, 981 u32 width, u32 height) 982 { 983 struct broadsheetfb_par *par = info->par; 984 985 broadsheetfb_dpy_update(par); 986 } 987 988 FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(broadsheetfb, 989 broadsheetfb_defio_damage_range, 990 broadsheetfb_defio_damage_area) 991 992 static const struct fb_ops broadsheetfb_ops = { 993 .owner = THIS_MODULE, 994 FB_DEFAULT_DEFERRED_OPS(broadsheetfb), 995 }; 996 997 static struct fb_deferred_io broadsheetfb_defio = { 998 .delay = HZ/4, 999 .sort_pagereflist = true, 1000 .deferred_io = broadsheetfb_dpy_deferred_io, 1001 }; 1002 1003 static int broadsheetfb_probe(struct platform_device *dev) 1004 { 1005 struct fb_info *info; 1006 struct broadsheet_board *board; 1007 int retval = -ENOMEM; 1008 int videomemorysize; 1009 unsigned char *videomemory; 1010 struct broadsheetfb_par *par; 1011 int i; 1012 int dpyw, dpyh; 1013 int panel_index; 1014 1015 /* pick up board specific routines */ 1016 board = dev->dev.platform_data; 1017 if (!board) 1018 return -EINVAL; 1019 1020 /* try to count device specific driver, if can't, platform recalls */ 1021 if (!try_module_get(board->owner)) 1022 return -ENODEV; 1023 1024 info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev); 1025 if (!info) 1026 goto err; 1027 1028 switch (board->get_panel_type()) { 1029 case 37: 1030 panel_index = 1; 1031 break; 1032 case 97: 1033 panel_index = 2; 1034 break; 1035 case 6: 1036 default: 1037 panel_index = 0; 1038 break; 1039 } 1040 1041 dpyw = panel_table[panel_index].w; 1042 dpyh = panel_table[panel_index].h; 1043 1044 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); 1045 1046 videomemory = vzalloc(videomemorysize); 1047 if (!videomemory) 1048 goto err_fb_rel; 1049 1050 info->screen_buffer = videomemory; 1051 info->fbops = &broadsheetfb_ops; 1052 1053 broadsheetfb_var.xres = dpyw; 1054 broadsheetfb_var.yres = dpyh; 1055 broadsheetfb_var.xres_virtual = dpyw; 1056 broadsheetfb_var.yres_virtual = dpyh; 1057 info->var = broadsheetfb_var; 1058 1059 broadsheetfb_fix.line_length = dpyw; 1060 info->fix = broadsheetfb_fix; 1061 info->fix.smem_len = videomemorysize; 1062 par = info->par; 1063 par->panel_index = panel_index; 1064 par->info = info; 1065 par->board = board; 1066 par->write_reg = broadsheet_write_reg; 1067 par->read_reg = broadsheet_read_reg; 1068 init_waitqueue_head(&par->waitq); 1069 1070 mutex_init(&par->io_lock); 1071 1072 info->flags = FBINFO_VIRTFB; 1073 1074 info->fbdefio = &broadsheetfb_defio; 1075 fb_deferred_io_init(info); 1076 1077 retval = fb_alloc_cmap(&info->cmap, 16, 0); 1078 if (retval < 0) { 1079 dev_err(&dev->dev, "Failed to allocate colormap\n"); 1080 goto err_vfree; 1081 } 1082 1083 /* set cmap */ 1084 for (i = 0; i < 16; i++) 1085 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32; 1086 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16); 1087 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16); 1088 1089 retval = par->board->setup_irq(info); 1090 if (retval < 0) 1091 goto err_cmap; 1092 1093 /* this inits the dpy */ 1094 retval = board->init(par); 1095 if (retval < 0) 1096 goto err_free_irq; 1097 1098 broadsheet_identify(par); 1099 1100 broadsheet_init(par); 1101 1102 retval = register_framebuffer(info); 1103 if (retval < 0) 1104 goto err_free_irq; 1105 1106 platform_set_drvdata(dev, info); 1107 1108 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); 1109 if (retval < 0) 1110 goto err_unreg_fb; 1111 1112 fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n", 1113 videomemorysize >> 10); 1114 1115 1116 return 0; 1117 1118 err_unreg_fb: 1119 unregister_framebuffer(info); 1120 err_free_irq: 1121 board->cleanup(par); 1122 err_cmap: 1123 fb_dealloc_cmap(&info->cmap); 1124 err_vfree: 1125 vfree(videomemory); 1126 err_fb_rel: 1127 framebuffer_release(info); 1128 err: 1129 module_put(board->owner); 1130 return retval; 1131 1132 } 1133 1134 static void broadsheetfb_remove(struct platform_device *dev) 1135 { 1136 struct fb_info *info = platform_get_drvdata(dev); 1137 1138 if (info) { 1139 struct broadsheetfb_par *par = info->par; 1140 1141 device_remove_file(info->device, &dev_attr_loadstore_waveform); 1142 unregister_framebuffer(info); 1143 fb_deferred_io_cleanup(info); 1144 par->board->cleanup(par); 1145 fb_dealloc_cmap(&info->cmap); 1146 vfree(info->screen_buffer); 1147 module_put(par->board->owner); 1148 framebuffer_release(info); 1149 } 1150 } 1151 1152 static struct platform_driver broadsheetfb_driver = { 1153 .probe = broadsheetfb_probe, 1154 .remove = broadsheetfb_remove, 1155 .driver = { 1156 .name = "broadsheetfb", 1157 }, 1158 }; 1159 module_platform_driver(broadsheetfb_driver); 1160 1161 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller"); 1162 MODULE_AUTHOR("Jaya Kumar"); 1163 MODULE_LICENSE("GPL"); 1164 1165 MODULE_FIRMWARE("broadsheet.wbf"); 1166