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 */ 38struct panel_info { 39 int w; 40 int h; 41 u16 sdcfg; 42 u16 gdcfg; 43 u16 lutfmt; 44 u16 fsynclen; 45 u16 fendfbegin; 46 u16 lsynclen; 47 u16 lendlbegin; 48 u16 pixclk; 49}; 50 51/* table of panel specific parameters to be indexed into by the board drivers */ 52static struct panel_info panel_table[] = { 53 { /* standard 6" on TFT backplane */ 54 .w = 800, 55 .h = 600, 56 .sdcfg = (100 | (1 << 8) | (1 << 9)), 57 .gdcfg = 2, 58 .lutfmt = (4 | (1 << 7)), 59 .fsynclen = 4, 60 .fendfbegin = (10 << 8) | 4, 61 .lsynclen = 10, 62 .lendlbegin = (100 << 8) | 4, 63 .pixclk = 6, 64 }, 65 { /* custom 3.7" flexible on PET or steel */ 66 .w = 320, 67 .h = 240, 68 .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)), 69 .gdcfg = 3, 70 .lutfmt = (4 | (1 << 7)), 71 .fsynclen = 0, 72 .fendfbegin = (80 << 8) | 4, 73 .lsynclen = 10, 74 .lendlbegin = (80 << 8) | 20, 75 .pixclk = 14, 76 }, 77 { /* standard 9.7" on TFT backplane */ 78 .w = 1200, 79 .h = 825, 80 .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)), 81 .gdcfg = 2, 82 .lutfmt = (4 | (1 << 7)), 83 .fsynclen = 0, 84 .fendfbegin = (4 << 8) | 4, 85 .lsynclen = 4, 86 .lendlbegin = (60 << 8) | 10, 87 .pixclk = 3, 88 }, 89}; 90 91#define DPY_W 800 92#define DPY_H 600 93 94static 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 105static 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 */ 119static 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 126static 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 132static 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 142static 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 158static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, 159 int argc, u16 *argv) 160{ 161 int i; 162 163 par->board->mmio_write(par, BS_MMIO_CMD, cmd); 164 165 for (i = 0; i < argc; i++) 166 par->board->mmio_write(par, BS_MMIO_DATA, argv[i]); 167} 168 169static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data) 170{ 171 if (par->board->mmio_write) 172 par->board->mmio_write(par, BS_MMIO_CMD, data); 173 else 174 broadsheet_gpio_send_command(par, data); 175} 176 177static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd, 178 int argc, u16 *argv) 179{ 180 if (par->board->mmio_write) 181 broadsheet_mmio_send_cmdargs(par, cmd, argc, argv); 182 else 183 broadsheet_gpio_send_cmdargs(par, cmd, argc, argv); 184} 185 186static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size, 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 206static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size, 207 u16 *data) 208{ 209 int i; 210 u16 tmp; 211 212 for (i = 0; i < size; i++) { 213 tmp = (data[i] & 0x0F) << 4; 214 tmp |= (data[i] & 0x0F00) << 4; 215 par->board->mmio_write(par, BS_MMIO_DATA, tmp); 216 } 217 218} 219 220static void broadsheet_burst_write(struct broadsheetfb_par *par, int size, 221 u16 *data) 222{ 223 if (par->board->mmio_write) 224 broadsheet_mmio_burst_write(par, size, data); 225 else 226 broadsheet_gpio_burst_write(par, size, data); 227} 228 229static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par) 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 250static u16 broadsheet_get_data(struct broadsheetfb_par *par) 251{ 252 if (par->board->mmio_read) 253 return par->board->mmio_read(par); 254 else 255 return broadsheet_gpio_get_data(par); 256} 257 258static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg, 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 277static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg, 278 u16 data) 279{ 280 par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG); 281 par->board->mmio_write(par, BS_MMIO_DATA, reg); 282 par->board->mmio_write(par, BS_MMIO_DATA, data); 283 284} 285 286static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg, 287 u16 data) 288{ 289 if (par->board->mmio_write) 290 broadsheet_mmio_write_reg(par, reg, data); 291 else 292 broadsheet_gpio_write_reg(par, reg, data); 293} 294 295static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg, 296 u32 data) 297{ 298 broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF); 299 broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF); 300} 301 302 303static 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 */ 311static int is_broadsheet_pll_locked(struct broadsheetfb_par *par) 312{ 313 return broadsheet_read_reg(par, 0x000A) & 0x0001; 314} 315 316static int broadsheet_setup_plls(struct broadsheetfb_par *par) 317{ 318 int retry_count = 0; 319 u16 tmp; 320 321 /* disable arral saemipu mode */ 322 broadsheet_write_reg(par, 0x0006, 0x0000); 323 324 broadsheet_write_reg(par, 0x0010, 0x0004); 325 broadsheet_write_reg(par, 0x0012, 0x5949); 326 broadsheet_write_reg(par, 0x0014, 0x0040); 327 broadsheet_write_reg(par, 0x0016, 0x0000); 328 329 do { 330 if (retry_count++ > 100) 331 return -ETIMEDOUT; 332 mdelay(1); 333 } while (!is_broadsheet_pll_locked(par)); 334 335 tmp = broadsheet_read_reg(par, 0x0006); 336 tmp &= ~0x1; 337 broadsheet_write_reg(par, 0x0006, tmp); 338 339 return 0; 340} 341 342static int broadsheet_setup_spi(struct broadsheetfb_par *par) 343{ 344 345 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); 346 broadsheet_write_reg(par, 0x0208, 0x0001); 347 348 return 0; 349} 350 351static int broadsheet_setup_spiflash(struct broadsheetfb_par *par, 352 u16 *orig_sfmcd) 353{ 354 355 *orig_sfmcd = broadsheet_read_reg(par, 0x0204); 356 broadsheet_write_reg(par, 0x0208, 0); 357 broadsheet_write_reg(par, 0x0204, 0); 358 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1)); 359 360 return 0; 361} 362 363static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par, 364 u16 reg, int bitnum, int val, 365 int timeout) 366{ 367 u16 tmp; 368 369 do { 370 tmp = broadsheet_read_reg(par, reg); 371 if (((tmp >> bitnum) & 1) == val) 372 return 0; 373 mdelay(1); 374 } while (timeout--); 375 376 return -ETIMEDOUT; 377} 378 379static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data) 380{ 381 broadsheet_write_reg(par, 0x0202, (data | 0x100)); 382 383 return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); 384} 385 386static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data) 387{ 388 int err; 389 u16 tmp; 390 391 broadsheet_write_reg(par, 0x0202, 0); 392 393 err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100); 394 if (err) 395 return err; 396 397 tmp = broadsheet_read_reg(par, 0x200); 398 399 *data = tmp & 0xFF; 400 401 return 0; 402} 403 404static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par, 405 int timeout) 406{ 407 u8 tmp; 408 int err; 409 410 do { 411 broadsheet_write_reg(par, 0x0208, 1); 412 413 err = broadsheet_spiflash_write_byte(par, 0x05); 414 if (err) 415 goto failout; 416 417 err = broadsheet_spiflash_read_byte(par, &tmp); 418 if (err) 419 goto failout; 420 421 broadsheet_write_reg(par, 0x0208, 0); 422 423 if (!(tmp & 0x1)) 424 return 0; 425 426 mdelay(5); 427 } while (timeout--); 428 429 dev_err(par->info->device, "Timed out waiting for spiflash status\n"); 430 return -ETIMEDOUT; 431 432failout: 433 broadsheet_write_reg(par, 0x0208, 0); 434 return err; 435} 436 437static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par, 438 u8 op, u32 addr) 439{ 440 int i; 441 u8 tmp; 442 int err; 443 444 broadsheet_write_reg(par, 0x0208, 1); 445 446 err = broadsheet_spiflash_write_byte(par, op); 447 if (err) 448 return err; 449 450 for (i = 2; i >= 0; i--) { 451 tmp = ((addr >> (i * 8)) & 0xFF); 452 err = broadsheet_spiflash_write_byte(par, tmp); 453 if (err) 454 return err; 455 } 456 457 return err; 458} 459 460static int broadsheet_verify_spiflash(struct broadsheetfb_par *par, 461 int *flash_type) 462{ 463 int err = 0; 464 u8 sig; 465 466 err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000); 467 if (err) 468 goto failout; 469 470 err = broadsheet_spiflash_read_byte(par, &sig); 471 if (err) 472 goto failout; 473 474 if ((sig != 0x10) && (sig != 0x11)) { 475 dev_err(par->info->device, "Unexpected flash type\n"); 476 err = -EINVAL; 477 goto failout; 478 } 479 480 *flash_type = sig; 481 482failout: 483 broadsheet_write_reg(par, 0x0208, 0); 484 return err; 485} 486 487static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par, 488 u16 *initial_sfmcd, int *flash_type) 489 490{ 491 int err; 492 493 err = broadsheet_setup_plls(par); 494 if (err) 495 return err; 496 497 broadsheet_write_reg(par, 0x0106, 0x0203); 498 499 err = broadsheet_setup_spi(par); 500 if (err) 501 return err; 502 503 err = broadsheet_setup_spiflash(par, initial_sfmcd); 504 if (err) 505 return err; 506 507 return broadsheet_verify_spiflash(par, flash_type); 508} 509 510static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par, 511 int mode) 512{ 513 int err; 514 515 broadsheet_write_reg(par, 0x0208, 1); 516 if (mode) 517 err = broadsheet_spiflash_write_byte(par, 0x06); 518 else 519 err = broadsheet_spiflash_write_byte(par, 0x04); 520 521 broadsheet_write_reg(par, 0x0208, 0); 522 return err; 523} 524 525static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par, 526 int addr) 527{ 528 int err; 529 530 broadsheet_spiflash_write_control(par, 1); 531 532 err = broadsheet_spiflash_op_on_address(par, 0xD8, addr); 533 534 broadsheet_write_reg(par, 0x0208, 0); 535 536 if (err) 537 return err; 538 539 err = broadsheet_spiflash_wait_for_status(par, 1000); 540 541 return err; 542} 543 544static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par, 545 int addr, int size, char *data) 546{ 547 int err; 548 int i; 549 550 err = broadsheet_spiflash_op_on_address(par, 0x03, addr); 551 if (err) 552 goto failout; 553 554 for (i = 0; i < size; i++) { 555 err = broadsheet_spiflash_read_byte(par, &data[i]); 556 if (err) 557 goto failout; 558 } 559 560failout: 561 broadsheet_write_reg(par, 0x0208, 0); 562 return err; 563} 564 565#define BS_SPIFLASH_PAGE_SIZE 256 566static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par, 567 int addr, const char *data) 568{ 569 int err; 570 int i; 571 572 broadsheet_spiflash_write_control(par, 1); 573 574 err = broadsheet_spiflash_op_on_address(par, 0x02, addr); 575 if (err) 576 goto failout; 577 578 for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) { 579 err = broadsheet_spiflash_write_byte(par, data[i]); 580 if (err) 581 goto failout; 582 } 583 584 broadsheet_write_reg(par, 0x0208, 0); 585 586 err = broadsheet_spiflash_wait_for_status(par, 100); 587 588failout: 589 return err; 590} 591 592static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par, 593 int addr, const char *data, int sector_size) 594{ 595 int i; 596 int err; 597 598 for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) { 599 err = broadsheet_spiflash_write_page(par, addr + i, &data[i]); 600 if (err) 601 return err; 602 } 603 return 0; 604} 605 606/* 607 * The caller must guarantee that the data to be rewritten is entirely 608 * contained within this sector. That is, data_start_addr + data_len 609 * must be less than sector_start_addr + sector_size. 610 */ 611static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par, 612 int sector_size, int data_start_addr, 613 int data_len, const char *data) 614{ 615 int err; 616 char *sector_buffer; 617 int tail_start_addr; 618 int start_sector_addr; 619 620 sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL); 621 if (!sector_buffer) 622 return -ENOMEM; 623 624 /* the start address of the sector is the 0th byte of that sector */ 625 start_sector_addr = (data_start_addr / sector_size) * sector_size; 626 627 /* 628 * check if there is head data that we need to readback into our sector 629 * buffer first 630 */ 631 if (data_start_addr != start_sector_addr) { 632 /* 633 * we need to read every byte up till the start address of our 634 * data and we put it into our sector buffer. 635 */ 636 err = broadsheet_spiflash_read_range(par, start_sector_addr, 637 data_start_addr, sector_buffer); 638 if (err) 639 return err; 640 } 641 642 /* now we copy our data into the right place in the sector buffer */ 643 memcpy(sector_buffer + data_start_addr, data, data_len); 644 645 /* 646 * now we check if there is a tail section of the sector that we need to 647 * readback. 648 */ 649 tail_start_addr = (data_start_addr + data_len) % sector_size; 650 651 if (tail_start_addr) { 652 int tail_len; 653 654 tail_len = sector_size - tail_start_addr; 655 656 /* now we read this tail into our sector buffer */ 657 err = broadsheet_spiflash_read_range(par, tail_start_addr, 658 tail_len, sector_buffer + tail_start_addr); 659 if (err) 660 return err; 661 } 662 663 /* if we got here we have the full sector that we want to rewrite. */ 664 665 /* first erase the sector */ 666 err = broadsheet_spiflash_erase_sector(par, start_sector_addr); 667 if (err) 668 return err; 669 670 /* now write it */ 671 err = broadsheet_spiflash_write_sector(par, start_sector_addr, 672 sector_buffer, sector_size); 673 return err; 674} 675 676static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr, 677 const u8 *wfm, int bytecount, int flash_type) 678{ 679 int sector_size; 680 int err; 681 int cur_addr; 682 int writecount; 683 int maxlen; 684 int offset = 0; 685 686 switch (flash_type) { 687 case 0x10: 688 sector_size = 32*1024; 689 break; 690 case 0x11: 691 default: 692 sector_size = 64*1024; 693 break; 694 } 695 696 while (bytecount) { 697 cur_addr = wfm_addr + offset; 698 maxlen = roundup(cur_addr, sector_size) - cur_addr; 699 writecount = min(bytecount, maxlen); 700 701 err = broadsheet_spiflash_rewrite_sector(par, sector_size, 702 cur_addr, writecount, wfm + offset); 703 if (err) 704 return err; 705 706 offset += writecount; 707 bytecount -= writecount; 708 } 709 710 return 0; 711} 712 713static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par, 714 const u8 *wfm, size_t wfm_size) 715{ 716 int err = 0; 717 u16 initial_sfmcd = 0; 718 int flash_type = 0; 719 720 err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type); 721 if (err) 722 goto failout; 723 724 err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type); 725 726failout: 727 broadsheet_write_reg(par, 0x0204, initial_sfmcd); 728 return err; 729} 730 731static ssize_t broadsheet_loadstore_waveform(struct device *dev, 732 struct device_attribute *attr, 733 const char *buf, size_t len) 734{ 735 int err; 736 struct fb_info *info = dev_get_drvdata(dev); 737 struct broadsheetfb_par *par = info->par; 738 const struct firmware *fw_entry; 739 740 if (len < 1) 741 return -EINVAL; 742 743 err = request_firmware(&fw_entry, "broadsheet.wbf", dev); 744 if (err < 0) { 745 dev_err(dev, "Failed to get broadsheet waveform\n"); 746 goto err_failed; 747 } 748 749 /* try to enforce reasonable min max on waveform */ 750 if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) { 751 dev_err(dev, "Invalid waveform\n"); 752 err = -EINVAL; 753 goto err_failed; 754 } 755 756 mutex_lock(&(par->io_lock)); 757 err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data, 758 fw_entry->size); 759 760 mutex_unlock(&(par->io_lock)); 761 if (err < 0) { 762 dev_err(dev, "Failed to store broadsheet waveform\n"); 763 goto err_failed; 764 } 765 766 dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size); 767 768 return len; 769 770err_failed: 771 return err; 772} 773static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL, 774 broadsheet_loadstore_waveform); 775 776/* upper level functions that manipulate the display and other stuff */ 777static void broadsheet_init_display(struct broadsheetfb_par *par) 778{ 779 u16 args[5]; 780 int xres = par->info->var.xres; 781 int yres = par->info->var.yres; 782 783 args[0] = panel_table[par->panel_index].w; 784 args[1] = panel_table[par->panel_index].h; 785 args[2] = panel_table[par->panel_index].sdcfg; 786 args[3] = panel_table[par->panel_index].gdcfg; 787 args[4] = panel_table[par->panel_index].lutfmt; 788 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 789 790 /* did the controller really set it? */ 791 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args); 792 793 args[0] = panel_table[par->panel_index].fsynclen; 794 args[1] = panel_table[par->panel_index].fendfbegin; 795 args[2] = panel_table[par->panel_index].lsynclen; 796 args[3] = panel_table[par->panel_index].lendlbegin; 797 args[4] = panel_table[par->panel_index].pixclk; 798 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args); 799 800 broadsheet_write_reg32(par, 0x310, xres*yres*2); 801 802 /* setup waveform */ 803 args[0] = 0x886; 804 args[1] = 0; 805 broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args); 806 807 broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR); 808 809 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 810 811 broadsheet_write_reg(par, 0x330, 0x84); 812 813 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 814 815 args[0] = (0x3 << 4); 816 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 817 818 args[0] = 0x154; 819 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 820 821 broadsheet_burst_write(par, (panel_table[par->panel_index].w * 822 panel_table[par->panel_index].h)/2, 823 (u16 *) par->info->screen_base); 824 825 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 826 827 args[0] = 0x4300; 828 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 829 830 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 831 832 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 833 834 par->board->wait_for_rdy(par); 835} 836 837static void broadsheet_identify(struct broadsheetfb_par *par) 838{ 839 u16 rev, prc; 840 struct device *dev = par->info->device; 841 842 rev = broadsheet_read_reg(par, BS_REG_REV); 843 prc = broadsheet_read_reg(par, BS_REG_PRC); 844 dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc); 845 846 if (prc != 0x0047) 847 dev_warn(dev, "Unrecognized Broadsheet Product Code\n"); 848 if (rev != 0x0100) 849 dev_warn(dev, "Unrecognized Broadsheet Revision\n"); 850} 851 852static void broadsheet_init(struct broadsheetfb_par *par) 853{ 854 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN); 855 /* the controller needs a second */ 856 msleep(1000); 857 broadsheet_init_display(par); 858} 859 860static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par, 861 u16 y1, u16 y2) 862{ 863 u16 args[5]; 864 unsigned char *buf = (unsigned char *)par->info->screen_base; 865 866 mutex_lock(&(par->io_lock)); 867 /* y1 must be a multiple of 4 so drop the lower bits */ 868 y1 &= 0xFFFC; 869 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */ 870 y2 |= 0x0003; 871 872 args[0] = 0x3 << 4; 873 args[1] = 0; 874 args[2] = y1; 875 args[3] = cpu_to_le16(par->info->var.xres); 876 args[4] = y2; 877 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args); 878 879 args[0] = 0x154; 880 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 881 882 buf += y1 * par->info->var.xres; 883 broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2, 884 (u16 *) buf); 885 886 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 887 888 args[0] = 0x4300; 889 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 890 891 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 892 893 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 894 895 par->board->wait_for_rdy(par); 896 mutex_unlock(&(par->io_lock)); 897 898} 899 900static void broadsheetfb_dpy_update(struct broadsheetfb_par *par) 901{ 902 u16 args[5]; 903 904 mutex_lock(&(par->io_lock)); 905 args[0] = 0x3 << 4; 906 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args); 907 908 args[0] = 0x154; 909 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args); 910 broadsheet_burst_write(par, (panel_table[par->panel_index].w * 911 panel_table[par->panel_index].h)/2, 912 (u16 *) par->info->screen_base); 913 914 broadsheet_send_command(par, BS_CMD_LD_IMG_END); 915 916 args[0] = 0x4300; 917 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args); 918 919 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG); 920 921 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND); 922 923 par->board->wait_for_rdy(par); 924 mutex_unlock(&(par->io_lock)); 925} 926 927/* this is called back from the deferred io workqueue */ 928static void broadsheetfb_dpy_deferred_io(struct fb_info *info, 929 struct list_head *pagelist) 930{ 931 u16 y1 = 0, h = 0; 932 int prev_index = -1; 933 struct page *cur; 934 struct fb_deferred_io *fbdefio = info->fbdefio; 935 int h_inc; 936 u16 yres = info->var.yres; 937 u16 xres = info->var.xres; 938 939 /* height increment is fixed per page */ 940 h_inc = DIV_ROUND_UP(PAGE_SIZE , xres); 941 942 /* walk the written page list and swizzle the data */ 943 list_for_each_entry(cur, &fbdefio->pagelist, lru) { 944 if (prev_index < 0) { 945 /* just starting so assign first page */ 946 y1 = (cur->index << PAGE_SHIFT) / xres; 947 h = h_inc; 948 } else if ((prev_index + 1) == cur->index) { 949 /* this page is consecutive so increase our height */ 950 h += h_inc; 951 } else { 952 /* page not consecutive, issue previous update first */ 953 broadsheetfb_dpy_update_pages(info->par, y1, y1 + h); 954 /* start over with our non consecutive page */ 955 y1 = (cur->index << PAGE_SHIFT) / xres; 956 h = h_inc; 957 } 958 prev_index = cur->index; 959 } 960 961 /* if we still have any pages to update we do so now */ 962 if (h >= yres) { 963 /* its a full screen update, just do it */ 964 broadsheetfb_dpy_update(info->par); 965 } else { 966 broadsheetfb_dpy_update_pages(info->par, y1, 967 min((u16) (y1 + h), yres)); 968 } 969} 970 971static void broadsheetfb_fillrect(struct fb_info *info, 972 const struct fb_fillrect *rect) 973{ 974 struct broadsheetfb_par *par = info->par; 975 976 sys_fillrect(info, rect); 977 978 broadsheetfb_dpy_update(par); 979} 980 981static void broadsheetfb_copyarea(struct fb_info *info, 982 const struct fb_copyarea *area) 983{ 984 struct broadsheetfb_par *par = info->par; 985 986 sys_copyarea(info, area); 987 988 broadsheetfb_dpy_update(par); 989} 990 991static void broadsheetfb_imageblit(struct fb_info *info, 992 const struct fb_image *image) 993{ 994 struct broadsheetfb_par *par = info->par; 995 996 sys_imageblit(info, image); 997 998 broadsheetfb_dpy_update(par); 999} 1000 1001/* 1002 * this is the slow path from userspace. they can seek and write to 1003 * the fb. it's inefficient to do anything less than a full screen draw 1004 */ 1005static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf, 1006 size_t count, loff_t *ppos) 1007{ 1008 struct broadsheetfb_par *par = info->par; 1009 unsigned long p = *ppos; 1010 void *dst; 1011 int err = 0; 1012 unsigned long total_size; 1013 1014 if (info->state != FBINFO_STATE_RUNNING) 1015 return -EPERM; 1016 1017 total_size = info->fix.smem_len; 1018 1019 if (p > total_size) 1020 return -EFBIG; 1021 1022 if (count > total_size) { 1023 err = -EFBIG; 1024 count = total_size; 1025 } 1026 1027 if (count + p > total_size) { 1028 if (!err) 1029 err = -ENOSPC; 1030 1031 count = total_size - p; 1032 } 1033 1034 dst = (void *)(info->screen_base + p); 1035 1036 if (copy_from_user(dst, buf, count)) 1037 err = -EFAULT; 1038 1039 if (!err) 1040 *ppos += count; 1041 1042 broadsheetfb_dpy_update(par); 1043 1044 return (err) ? err : count; 1045} 1046 1047static struct fb_ops broadsheetfb_ops = { 1048 .owner = THIS_MODULE, 1049 .fb_read = fb_sys_read, 1050 .fb_write = broadsheetfb_write, 1051 .fb_fillrect = broadsheetfb_fillrect, 1052 .fb_copyarea = broadsheetfb_copyarea, 1053 .fb_imageblit = broadsheetfb_imageblit, 1054}; 1055 1056static struct fb_deferred_io broadsheetfb_defio = { 1057 .delay = HZ/4, 1058 .deferred_io = broadsheetfb_dpy_deferred_io, 1059}; 1060 1061static int broadsheetfb_probe(struct platform_device *dev) 1062{ 1063 struct fb_info *info; 1064 struct broadsheet_board *board; 1065 int retval = -ENOMEM; 1066 int videomemorysize; 1067 unsigned char *videomemory; 1068 struct broadsheetfb_par *par; 1069 int i; 1070 int dpyw, dpyh; 1071 int panel_index; 1072 1073 /* pick up board specific routines */ 1074 board = dev->dev.platform_data; 1075 if (!board) 1076 return -EINVAL; 1077 1078 /* try to count device specific driver, if can't, platform recalls */ 1079 if (!try_module_get(board->owner)) 1080 return -ENODEV; 1081 1082 info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev); 1083 if (!info) 1084 goto err; 1085 1086 switch (board->get_panel_type()) { 1087 case 37: 1088 panel_index = 1; 1089 break; 1090 case 97: 1091 panel_index = 2; 1092 break; 1093 case 6: 1094 default: 1095 panel_index = 0; 1096 break; 1097 } 1098 1099 dpyw = panel_table[panel_index].w; 1100 dpyh = panel_table[panel_index].h; 1101 1102 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE); 1103 1104 videomemory = vzalloc(videomemorysize); 1105 if (!videomemory) 1106 goto err_fb_rel; 1107 1108 info->screen_base = (char *)videomemory; 1109 info->fbops = &broadsheetfb_ops; 1110 1111 broadsheetfb_var.xres = dpyw; 1112 broadsheetfb_var.yres = dpyh; 1113 broadsheetfb_var.xres_virtual = dpyw; 1114 broadsheetfb_var.yres_virtual = dpyh; 1115 info->var = broadsheetfb_var; 1116 1117 broadsheetfb_fix.line_length = dpyw; 1118 info->fix = broadsheetfb_fix; 1119 info->fix.smem_len = videomemorysize; 1120 par = info->par; 1121 par->panel_index = panel_index; 1122 par->info = info; 1123 par->board = board; 1124 par->write_reg = broadsheet_write_reg; 1125 par->read_reg = broadsheet_read_reg; 1126 init_waitqueue_head(&par->waitq); 1127 1128 mutex_init(&par->io_lock); 1129 1130 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; 1131 1132 info->fbdefio = &broadsheetfb_defio; 1133 fb_deferred_io_init(info); 1134 1135 retval = fb_alloc_cmap(&info->cmap, 16, 0); 1136 if (retval < 0) { 1137 dev_err(&dev->dev, "Failed to allocate colormap\n"); 1138 goto err_vfree; 1139 } 1140 1141 /* set cmap */ 1142 for (i = 0; i < 16; i++) 1143 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32; 1144 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16); 1145 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16); 1146 1147 retval = par->board->setup_irq(info); 1148 if (retval < 0) 1149 goto err_cmap; 1150 1151 /* this inits the dpy */ 1152 retval = board->init(par); 1153 if (retval < 0) 1154 goto err_free_irq; 1155 1156 broadsheet_identify(par); 1157 1158 broadsheet_init(par); 1159 1160 retval = register_framebuffer(info); 1161 if (retval < 0) 1162 goto err_free_irq; 1163 1164 platform_set_drvdata(dev, info); 1165 1166 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform); 1167 if (retval < 0) 1168 goto err_unreg_fb; 1169 1170 fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n", 1171 videomemorysize >> 10); 1172 1173 1174 return 0; 1175 1176err_unreg_fb: 1177 unregister_framebuffer(info); 1178err_free_irq: 1179 board->cleanup(par); 1180err_cmap: 1181 fb_dealloc_cmap(&info->cmap); 1182err_vfree: 1183 vfree(videomemory); 1184err_fb_rel: 1185 framebuffer_release(info); 1186err: 1187 module_put(board->owner); 1188 return retval; 1189 1190} 1191 1192static int broadsheetfb_remove(struct platform_device *dev) 1193{ 1194 struct fb_info *info = platform_get_drvdata(dev); 1195 1196 if (info) { 1197 struct broadsheetfb_par *par = info->par; 1198 1199 device_remove_file(info->dev, &dev_attr_loadstore_waveform); 1200 unregister_framebuffer(info); 1201 fb_deferred_io_cleanup(info); 1202 par->board->cleanup(par); 1203 fb_dealloc_cmap(&info->cmap); 1204 vfree((void *)info->screen_base); 1205 module_put(par->board->owner); 1206 framebuffer_release(info); 1207 } 1208 return 0; 1209} 1210 1211static struct platform_driver broadsheetfb_driver = { 1212 .probe = broadsheetfb_probe, 1213 .remove = broadsheetfb_remove, 1214 .driver = { 1215 .owner = THIS_MODULE, 1216 .name = "broadsheetfb", 1217 }, 1218}; 1219module_platform_driver(broadsheetfb_driver); 1220 1221MODULE_DESCRIPTION("fbdev driver for Broadsheet controller"); 1222MODULE_AUTHOR("Jaya Kumar"); 1223MODULE_LICENSE("GPL"); 1224