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(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 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_failed; 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_failed; 766 } 767 768 dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size); 769 770 return len; 771 772 err_failed: 773 return err; 774 } 775 static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL, 776 broadsheet_loadstore_waveform); 777 778 /* upper level functions that manipulate the display and other stuff */ 779 static void broadsheet_init_display(struct broadsheetfb_par *par) 780 { 781 u16 args[5]; 782 int xres = par->info->var.xres; 783 int yres = par->info->var.yres; 784 785 args[0] = panel_table[par->panel_index].w; 786 args[1] = panel_table[par->panel_index].h; 787 args[2] = panel_table[par->panel_index].sdcfg; 788 args[3] = panel_table[par->panel_index].gdcfg; 789 args[4] = panel_table[par->panel_index].lutfmt; 790 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 791 792 /* did the controller really set it? */ 793 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 794 795 args[0] = panel_table[par->panel_index].fsynclen; 796 args[1] = panel_table[par->panel_index].fendfbegin; 797 args[2] = panel_table[par->panel_index].lsynclen; 798 args[3] = panel_table[par->panel_index].lendlbegin; 799 args[4] = panel_table[par->panel_index].pixclk; 800 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); 801 802 broadsheet_write_reg32(par, 0x310, xres*yres*2); 803 804 /* setup waveform */ 805 args[0] = 0x886; 806 args[1] = 0; 807 broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args); 808 809 broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR); 810 811 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 812 813 broadsheet_write_reg(par, 0x330, 0x84); 814 815 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 816 817 args[0] = (0x3 << 4); 818 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 819 820 args[0] = 0x154; 821 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 822 823 broadsheet_burst_write(par, (panel_table[par->panel_index].w * 824 panel_table[par->panel_index].h)/2, 825 (u16 *) par->info->screen_base); 826 827 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 828 829 args[0] = 0x4300; 830 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 831 832 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 833 834 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 835 836 par->board->wait_for_rdy(par); 837 } 838 839 static void broadsheet_identify(struct broadsheetfb_par *par) 840 { 841 u16 rev, prc; 842 struct device *dev = par->info->device; 843 844 rev = broadsheet_read_reg(par, BS_REG_REV); 845 prc = broadsheet_read_reg(par, BS_REG_PRC); 846 dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc); 847 848 if (prc != 0x0047) 849 dev_warn(dev, "Unrecognized Broadsheet Product Code\n"); 850 if (rev != 0x0100) 851 dev_warn(dev, "Unrecognized Broadsheet Revision\n"); 852 } 853 854 static void broadsheet_init(struct broadsheetfb_par *par) 855 { 856 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); 857 /* the controller needs a second */ 858 msleep(1000); 859 broadsheet_init_display(par); 860 } 861 862 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, 863 u16 y1, u16 y2) 864 { 865 u16 args[5]; 866 unsigned char *buf = (unsigned char *)par->info->screen_base; 867 868 mutex_lock(&(par->io_lock)); 869 /* y1 must be a multiple of 4 so drop the lower bits */ 870 y1 &= 0xFFFC; 871 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ 872 y2 |= 0x0003; 873 874 args[0] = 0x3 << 4; 875 args[1] = 0; 876 args[2] = y1; 877 args[3] = cpu_to_le16(par->info->var.xres); 878 args[4] = y2; 879 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args); 880 881 args[0] = 0x154; 882 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 883 884 buf += y1 * par->info->var.xres; 885 broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2, 886 (u16 *) buf); 887 888 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 889 890 args[0] = 0x4300; 891 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 892 893 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 894 895 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 896 897 par->board->wait_for_rdy(par); 898 mutex_unlock(&(par->io_lock)); 899 900 } 901 902 static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) 903 { 904 u16 args[5]; 905 906 mutex_lock(&(par->io_lock)); 907 args[0] = 0x3 << 4; 908 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 909 910 args[0] = 0x154; 911 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 912 broadsheet_burst_write(par, (panel_table[par->panel_index].w * 913 panel_table[par->panel_index].h)/2, 914 (u16 *) par->info->screen_base); 915 916 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 917 918 args[0] = 0x4300; 919 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 920 921 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 922 923 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 924 925 par->board->wait_for_rdy(par); 926 mutex_unlock(&(par->io_lock)); 927 } 928 929 /* this is called back from the deferred io workqueue */ 930 static void broadsheetfb_dpy_deferred_io(struct fb_info *info, 931 struct list_head *pagelist) 932 { 933 u16 y1 = 0, h = 0; 934 int prev_index = -1; 935 struct page *cur; 936 struct fb_deferred_io *fbdefio = info->fbdefio; 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(cur, &fbdefio->pagelist, lru) { 946 if (prev_index < 0) { 947 /* just starting so assign first page */ 948 y1 = (cur->index << PAGE_SHIFT) / xres; 949 h = h_inc; 950 } else if ((prev_index + 1) == cur->index) { 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 = (cur->index << PAGE_SHIFT) / xres; 958 h = h_inc; 959 } 960 prev_index = cur->index; 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_fillrect(struct fb_info *info, 974 const struct fb_fillrect *rect) 975 { 976 struct broadsheetfb_par *par = info->par; 977 978 sys_fillrect(info, rect); 979 980 broadsheetfb_dpy_update(par); 981 } 982 983 static void broadsheetfb_copyarea(struct fb_info *info, 984 const struct fb_copyarea *area) 985 { 986 struct broadsheetfb_par *par = info->par; 987 988 sys_copyarea(info, area); 989 990 broadsheetfb_dpy_update(par); 991 } 992 993 static void broadsheetfb_imageblit(struct fb_info *info, 994 const struct fb_image *image) 995 { 996 struct broadsheetfb_par *par = info->par; 997 998 sys_imageblit(info, image); 999 1000 broadsheetfb_dpy_update(par); 1001 } 1002 1003 /* 1004 * this is the slow path from userspace. they can seek and write to 1005 * the fb. it's inefficient to do anything less than a full screen draw 1006 */ 1007 static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf, 1008 size_t count, loff_t *ppos) 1009 { 1010 struct broadsheetfb_par *par = info->par; 1011 unsigned long p = *ppos; 1012 void *dst; 1013 int err = 0; 1014 unsigned long total_size; 1015 1016 if (info->state != FBINFO_STATE_RUNNING) 1017 return -EPERM; 1018 1019 total_size = info->fix.smem_len; 1020 1021 if (p > total_size) 1022 return -EFBIG; 1023 1024 if (count > total_size) { 1025 err = -EFBIG; 1026 count = total_size; 1027 } 1028 1029 if (count + p > total_size) { 1030 if (!err) 1031 err = -ENOSPC; 1032 1033 count = total_size - p; 1034 } 1035 1036 dst = (void *)(info->screen_base + p); 1037 1038 if (copy_from_user(dst, buf, count)) 1039 err = -EFAULT; 1040 1041 if (!err) 1042 *ppos += count; 1043 1044 broadsheetfb_dpy_update(par); 1045 1046 return (err) ? err : count; 1047 } 1048 1049 static struct fb_ops broadsheetfb_ops = { 1050 .owner = THIS_MODULE, 1051 .fb_read = fb_sys_read, 1052 .fb_write = broadsheetfb_write, 1053 .fb_fillrect = broadsheetfb_fillrect, 1054 .fb_copyarea = broadsheetfb_copyarea, 1055 .fb_imageblit = broadsheetfb_imageblit, 1056 }; 1057 1058 static struct fb_deferred_io broadsheetfb_defio = { 1059 .delay = HZ/4, 1060 .deferred_io = broadsheetfb_dpy_deferred_io, 1061 }; 1062 1063 static int broadsheetfb_probe(struct platform_device *dev) 1064 { 1065 struct fb_info *info; 1066 struct broadsheet_board *board; 1067 int retval = -ENOMEM; 1068 int videomemorysize; 1069 unsigned char *videomemory; 1070 struct broadsheetfb_par *par; 1071 int i; 1072 int dpyw, dpyh; 1073 int panel_index; 1074 1075 /* pick up board specific routines */ 1076 board = dev->dev.platform_data; 1077 if (!board) 1078 return -EINVAL; 1079 1080 /* try to count device specific driver, if can't, platform recalls */ 1081 if (!try_module_get(board->owner)) 1082 return -ENODEV; 1083 1084 info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev); 1085 if (!info) 1086 goto err; 1087 1088 switch (board->get_panel_type()) { 1089 case 37: 1090 panel_index = 1; 1091 break; 1092 case 97: 1093 panel_index = 2; 1094 break; 1095 case 6: 1096 default: 1097 panel_index = 0; 1098 break; 1099 } 1100 1101 dpyw = panel_table[panel_index].w; 1102 dpyh = panel_table[panel_index].h; 1103 1104 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); 1105 1106 videomemory = vzalloc(videomemorysize); 1107 if (!videomemory) 1108 goto err_fb_rel; 1109 1110 info->screen_base = (char *)videomemory; 1111 info->fbops = &broadsheetfb_ops; 1112 1113 broadsheetfb_var.xres = dpyw; 1114 broadsheetfb_var.yres = dpyh; 1115 broadsheetfb_var.xres_virtual = dpyw; 1116 broadsheetfb_var.yres_virtual = dpyh; 1117 info->var = broadsheetfb_var; 1118 1119 broadsheetfb_fix.line_length = dpyw; 1120 info->fix = broadsheetfb_fix; 1121 info->fix.smem_len = videomemorysize; 1122 par = info->par; 1123 par->panel_index = panel_index; 1124 par->info = info; 1125 par->board = board; 1126 par->write_reg = broadsheet_write_reg; 1127 par->read_reg = broadsheet_read_reg; 1128 init_waitqueue_head(&par->waitq); 1129 1130 mutex_init(&par->io_lock); 1131 1132 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; 1133 1134 info->fbdefio = &broadsheetfb_defio; 1135 fb_deferred_io_init(info); 1136 1137 retval = fb_alloc_cmap(&info->cmap, 16, 0); 1138 if (retval < 0) { 1139 dev_err(&dev->dev, "Failed to allocate colormap\n"); 1140 goto err_vfree; 1141 } 1142 1143 /* set cmap */ 1144 for (i = 0; i < 16; i++) 1145 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32; 1146 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16); 1147 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16); 1148 1149 retval = par->board->setup_irq(info); 1150 if (retval < 0) 1151 goto err_cmap; 1152 1153 /* this inits the dpy */ 1154 retval = board->init(par); 1155 if (retval < 0) 1156 goto err_free_irq; 1157 1158 broadsheet_identify(par); 1159 1160 broadsheet_init(par); 1161 1162 retval = register_framebuffer(info); 1163 if (retval < 0) 1164 goto err_free_irq; 1165 1166 platform_set_drvdata(dev, info); 1167 1168 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); 1169 if (retval < 0) 1170 goto err_unreg_fb; 1171 1172 fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n", 1173 videomemorysize >> 10); 1174 1175 1176 return 0; 1177 1178 err_unreg_fb: 1179 unregister_framebuffer(info); 1180 err_free_irq: 1181 board->cleanup(par); 1182 err_cmap: 1183 fb_dealloc_cmap(&info->cmap); 1184 err_vfree: 1185 vfree(videomemory); 1186 err_fb_rel: 1187 framebuffer_release(info); 1188 err: 1189 module_put(board->owner); 1190 return retval; 1191 1192 } 1193 1194 static int broadsheetfb_remove(struct platform_device *dev) 1195 { 1196 struct fb_info *info = platform_get_drvdata(dev); 1197 1198 if (info) { 1199 struct broadsheetfb_par *par = info->par; 1200 1201 device_remove_file(info->dev, &dev_attr_loadstore_waveform); 1202 unregister_framebuffer(info); 1203 fb_deferred_io_cleanup(info); 1204 par->board->cleanup(par); 1205 fb_dealloc_cmap(&info->cmap); 1206 vfree((void *)info->screen_base); 1207 module_put(par->board->owner); 1208 framebuffer_release(info); 1209 } 1210 return 0; 1211 } 1212 1213 static struct platform_driver broadsheetfb_driver = { 1214 .probe = broadsheetfb_probe, 1215 .remove = broadsheetfb_remove, 1216 .driver = { 1217 .name = "broadsheetfb", 1218 }, 1219 }; 1220 module_platform_driver(broadsheetfb_driver); 1221 1222 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller"); 1223 MODULE_AUTHOR("Jaya Kumar"); 1224 MODULE_LICENSE("GPL"); 1225