0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/module.h>
0020 #include <linux/kernel.h>
0021 #include <linux/errno.h>
0022 #include <linux/string.h>
0023 #include <linux/mm.h>
0024 #include <linux/slab.h>
0025 #include <linux/vmalloc.h>
0026 #include <linux/delay.h>
0027 #include <linux/interrupt.h>
0028 #include <linux/fb.h>
0029 #include <linux/init.h>
0030 #include <linux/platform_device.h>
0031 #include <linux/list.h>
0032 #include <linux/firmware.h>
0033 #include <linux/uaccess.h>
0034
0035 #include <video/broadsheetfb.h>
0036
0037
0038 struct panel_info {
0039 int w;
0040 int h;
0041 u16 sdcfg;
0042 u16 gdcfg;
0043 u16 lutfmt;
0044 u16 fsynclen;
0045 u16 fendfbegin;
0046 u16 lsynclen;
0047 u16 lendlbegin;
0048 u16 pixclk;
0049 };
0050
0051
0052 static struct panel_info panel_table[] = {
0053 {
0054 .w = 800,
0055 .h = 600,
0056 .sdcfg = (100 | (1 << 8) | (1 << 9)),
0057 .gdcfg = 2,
0058 .lutfmt = (4 | (1 << 7)),
0059 .fsynclen = 4,
0060 .fendfbegin = (10 << 8) | 4,
0061 .lsynclen = 10,
0062 .lendlbegin = (100 << 8) | 4,
0063 .pixclk = 6,
0064 },
0065 {
0066 .w = 320,
0067 .h = 240,
0068 .sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
0069 .gdcfg = 3,
0070 .lutfmt = (4 | (1 << 7)),
0071 .fsynclen = 0,
0072 .fendfbegin = (80 << 8) | 4,
0073 .lsynclen = 10,
0074 .lendlbegin = (80 << 8) | 20,
0075 .pixclk = 14,
0076 },
0077 {
0078 .w = 1200,
0079 .h = 825,
0080 .sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
0081 .gdcfg = 2,
0082 .lutfmt = (4 | (1 << 7)),
0083 .fsynclen = 0,
0084 .fendfbegin = (4 << 8) | 4,
0085 .lsynclen = 4,
0086 .lendlbegin = (60 << 8) | 10,
0087 .pixclk = 3,
0088 },
0089 };
0090
0091 #define DPY_W 800
0092 #define DPY_H 600
0093
0094 static struct fb_fix_screeninfo broadsheetfb_fix = {
0095 .id = "broadsheetfb",
0096 .type = FB_TYPE_PACKED_PIXELS,
0097 .visual = FB_VISUAL_STATIC_PSEUDOCOLOR,
0098 .xpanstep = 0,
0099 .ypanstep = 0,
0100 .ywrapstep = 0,
0101 .line_length = DPY_W,
0102 .accel = FB_ACCEL_NONE,
0103 };
0104
0105 static struct fb_var_screeninfo broadsheetfb_var = {
0106 .xres = DPY_W,
0107 .yres = DPY_H,
0108 .xres_virtual = DPY_W,
0109 .yres_virtual = DPY_H,
0110 .bits_per_pixel = 8,
0111 .grayscale = 1,
0112 .red = { 0, 4, 0 },
0113 .green = { 0, 4, 0 },
0114 .blue = { 0, 4, 0 },
0115 .transp = { 0, 0, 0 },
0116 };
0117
0118
0119 static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
0120 {
0121 par->board->set_ctl(par, BS_WR, 0);
0122 par->board->set_hdb(par, data);
0123 par->board->set_ctl(par, BS_WR, 1);
0124 }
0125
0126 static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
0127 {
0128 par->board->set_ctl(par, BS_DC, 0);
0129 broadsheet_gpio_issue_data(par, data);
0130 }
0131
0132 static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
0133 {
0134 par->board->wait_for_rdy(par);
0135
0136 par->board->set_ctl(par, BS_CS, 0);
0137 broadsheet_gpio_issue_cmd(par, data);
0138 par->board->set_ctl(par, BS_DC, 1);
0139 par->board->set_ctl(par, BS_CS, 1);
0140 }
0141
0142 static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
0143 int argc, u16 *argv)
0144 {
0145 int i;
0146
0147 par->board->wait_for_rdy(par);
0148
0149 par->board->set_ctl(par, BS_CS, 0);
0150 broadsheet_gpio_issue_cmd(par, cmd);
0151 par->board->set_ctl(par, BS_DC, 1);
0152
0153 for (i = 0; i < argc; i++)
0154 broadsheet_gpio_issue_data(par, argv[i]);
0155 par->board->set_ctl(par, BS_CS, 1);
0156 }
0157
0158 static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
0159 int argc, u16 *argv)
0160 {
0161 int i;
0162
0163 par->board->mmio_write(par, BS_MMIO_CMD, cmd);
0164
0165 for (i = 0; i < argc; i++)
0166 par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
0167 }
0168
0169 static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
0170 {
0171 if (par->board->mmio_write)
0172 par->board->mmio_write(par, BS_MMIO_CMD, data);
0173 else
0174 broadsheet_gpio_send_command(par, data);
0175 }
0176
0177 static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
0178 int argc, u16 *argv)
0179 {
0180 if (par->board->mmio_write)
0181 broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
0182 else
0183 broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
0184 }
0185
0186 static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
0187 u16 *data)
0188 {
0189 int i;
0190 u16 tmp;
0191
0192 par->board->set_ctl(par, BS_CS, 0);
0193 par->board->set_ctl(par, BS_DC, 1);
0194
0195 for (i = 0; i < size; i++) {
0196 par->board->set_ctl(par, BS_WR, 0);
0197 tmp = (data[i] & 0x0F) << 4;
0198 tmp |= (data[i] & 0x0F00) << 4;
0199 par->board->set_hdb(par, tmp);
0200 par->board->set_ctl(par, BS_WR, 1);
0201 }
0202
0203 par->board->set_ctl(par, BS_CS, 1);
0204 }
0205
0206 static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
0207 u16 *data)
0208 {
0209 int i;
0210 u16 tmp;
0211
0212 for (i = 0; i < size; i++) {
0213 tmp = (data[i] & 0x0F) << 4;
0214 tmp |= (data[i] & 0x0F00) << 4;
0215 par->board->mmio_write(par, BS_MMIO_DATA, tmp);
0216 }
0217
0218 }
0219
0220 static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
0221 u16 *data)
0222 {
0223 if (par->board->mmio_write)
0224 broadsheet_mmio_burst_write(par, size, data);
0225 else
0226 broadsheet_gpio_burst_write(par, size, data);
0227 }
0228
0229 static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
0230 {
0231 u16 res;
0232
0233 par->board->wait_for_rdy(par);
0234
0235
0236 par->board->set_ctl(par, BS_DC, 1);
0237 par->board->set_ctl(par, BS_CS, 0);
0238 par->board->set_ctl(par, BS_WR, 0);
0239
0240 res = par->board->get_hdb(par);
0241
0242
0243 par->board->set_ctl(par, BS_WR, 1);
0244 par->board->set_ctl(par, BS_CS, 1);
0245
0246 return res;
0247 }
0248
0249
0250 static u16 broadsheet_get_data(struct broadsheetfb_par *par)
0251 {
0252 if (par->board->mmio_read)
0253 return par->board->mmio_read(par);
0254 else
0255 return broadsheet_gpio_get_data(par);
0256 }
0257
0258 static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
0259 u16 data)
0260 {
0261
0262 par->board->wait_for_rdy(par);
0263
0264
0265 par->board->set_ctl(par, BS_CS, 0);
0266
0267 broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
0268
0269 par->board->set_ctl(par, BS_DC, 1);
0270
0271 broadsheet_gpio_issue_data(par, reg);
0272 broadsheet_gpio_issue_data(par, data);
0273
0274 par->board->set_ctl(par, BS_CS, 1);
0275 }
0276
0277 static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
0278 u16 data)
0279 {
0280 par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
0281 par->board->mmio_write(par, BS_MMIO_DATA, reg);
0282 par->board->mmio_write(par, BS_MMIO_DATA, data);
0283
0284 }
0285
0286 static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
0287 u16 data)
0288 {
0289 if (par->board->mmio_write)
0290 broadsheet_mmio_write_reg(par, reg, data);
0291 else
0292 broadsheet_gpio_write_reg(par, reg, data);
0293 }
0294
0295 static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
0296 u32 data)
0297 {
0298 broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
0299 broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
0300 }
0301
0302
0303 static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
0304 {
0305 broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, ®);
0306 par->board->wait_for_rdy(par);
0307 return broadsheet_get_data(par);
0308 }
0309
0310
0311 static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
0312 {
0313 return broadsheet_read_reg(par, 0x000A) & 0x0001;
0314 }
0315
0316 static int broadsheet_setup_plls(struct broadsheetfb_par *par)
0317 {
0318 int retry_count = 0;
0319 u16 tmp;
0320
0321
0322 broadsheet_write_reg(par, 0x0006, 0x0000);
0323
0324 broadsheet_write_reg(par, 0x0010, 0x0004);
0325 broadsheet_write_reg(par, 0x0012, 0x5949);
0326 broadsheet_write_reg(par, 0x0014, 0x0040);
0327 broadsheet_write_reg(par, 0x0016, 0x0000);
0328
0329 do {
0330 if (retry_count++ > 100)
0331 return -ETIMEDOUT;
0332 mdelay(1);
0333 } while (!is_broadsheet_pll_locked(par));
0334
0335 tmp = broadsheet_read_reg(par, 0x0006);
0336 tmp &= ~0x1;
0337 broadsheet_write_reg(par, 0x0006, tmp);
0338
0339 return 0;
0340 }
0341
0342 static int broadsheet_setup_spi(struct broadsheetfb_par *par)
0343 {
0344
0345 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
0346 broadsheet_write_reg(par, 0x0208, 0x0001);
0347
0348 return 0;
0349 }
0350
0351 static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
0352 u16 *orig_sfmcd)
0353 {
0354
0355 *orig_sfmcd = broadsheet_read_reg(par, 0x0204);
0356 broadsheet_write_reg(par, 0x0208, 0);
0357 broadsheet_write_reg(par, 0x0204, 0);
0358 broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
0359
0360 return 0;
0361 }
0362
0363 static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
0364 u16 reg, int bitnum, int val,
0365 int timeout)
0366 {
0367 u16 tmp;
0368
0369 do {
0370 tmp = broadsheet_read_reg(par, reg);
0371 if (((tmp >> bitnum) & 1) == val)
0372 return 0;
0373 mdelay(1);
0374 } while (timeout--);
0375
0376 return -ETIMEDOUT;
0377 }
0378
0379 static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
0380 {
0381 broadsheet_write_reg(par, 0x0202, (data | 0x100));
0382
0383 return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
0384 }
0385
0386 static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
0387 {
0388 int err;
0389 u16 tmp;
0390
0391 broadsheet_write_reg(par, 0x0202, 0);
0392
0393 err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
0394 if (err)
0395 return err;
0396
0397 tmp = broadsheet_read_reg(par, 0x200);
0398
0399 *data = tmp & 0xFF;
0400
0401 return 0;
0402 }
0403
0404 static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
0405 int timeout)
0406 {
0407 u8 tmp;
0408 int err;
0409
0410 do {
0411 broadsheet_write_reg(par, 0x0208, 1);
0412
0413 err = broadsheet_spiflash_write_byte(par, 0x05);
0414 if (err)
0415 goto failout;
0416
0417 err = broadsheet_spiflash_read_byte(par, &tmp);
0418 if (err)
0419 goto failout;
0420
0421 broadsheet_write_reg(par, 0x0208, 0);
0422
0423 if (!(tmp & 0x1))
0424 return 0;
0425
0426 mdelay(5);
0427 } while (timeout--);
0428
0429 dev_err(par->info->device, "Timed out waiting for spiflash status\n");
0430 return -ETIMEDOUT;
0431
0432 failout:
0433 broadsheet_write_reg(par, 0x0208, 0);
0434 return err;
0435 }
0436
0437 static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
0438 u8 op, u32 addr)
0439 {
0440 int i;
0441 u8 tmp;
0442 int err;
0443
0444 broadsheet_write_reg(par, 0x0208, 1);
0445
0446 err = broadsheet_spiflash_write_byte(par, op);
0447 if (err)
0448 return err;
0449
0450 for (i = 2; i >= 0; i--) {
0451 tmp = ((addr >> (i * 8)) & 0xFF);
0452 err = broadsheet_spiflash_write_byte(par, tmp);
0453 if (err)
0454 return err;
0455 }
0456
0457 return err;
0458 }
0459
0460 static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
0461 int *flash_type)
0462 {
0463 int err = 0;
0464 u8 sig;
0465
0466 err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
0467 if (err)
0468 goto failout;
0469
0470 err = broadsheet_spiflash_read_byte(par, &sig);
0471 if (err)
0472 goto failout;
0473
0474 if ((sig != 0x10) && (sig != 0x11)) {
0475 dev_err(par->info->device, "Unexpected flash type\n");
0476 err = -EINVAL;
0477 goto failout;
0478 }
0479
0480 *flash_type = sig;
0481
0482 failout:
0483 broadsheet_write_reg(par, 0x0208, 0);
0484 return err;
0485 }
0486
0487 static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
0488 u16 *initial_sfmcd, int *flash_type)
0489
0490 {
0491 int err;
0492
0493 err = broadsheet_setup_plls(par);
0494 if (err)
0495 return err;
0496
0497 broadsheet_write_reg(par, 0x0106, 0x0203);
0498
0499 err = broadsheet_setup_spi(par);
0500 if (err)
0501 return err;
0502
0503 err = broadsheet_setup_spiflash(par, initial_sfmcd);
0504 if (err)
0505 return err;
0506
0507 return broadsheet_verify_spiflash(par, flash_type);
0508 }
0509
0510 static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
0511 int mode)
0512 {
0513 int err;
0514
0515 broadsheet_write_reg(par, 0x0208, 1);
0516 if (mode)
0517 err = broadsheet_spiflash_write_byte(par, 0x06);
0518 else
0519 err = broadsheet_spiflash_write_byte(par, 0x04);
0520
0521 broadsheet_write_reg(par, 0x0208, 0);
0522 return err;
0523 }
0524
0525 static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
0526 int addr)
0527 {
0528 int err;
0529
0530 broadsheet_spiflash_write_control(par, 1);
0531
0532 err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
0533
0534 broadsheet_write_reg(par, 0x0208, 0);
0535
0536 if (err)
0537 return err;
0538
0539 err = broadsheet_spiflash_wait_for_status(par, 1000);
0540
0541 return err;
0542 }
0543
0544 static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
0545 int addr, int size, char *data)
0546 {
0547 int err;
0548 int i;
0549
0550 err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
0551 if (err)
0552 goto failout;
0553
0554 for (i = 0; i < size; i++) {
0555 err = broadsheet_spiflash_read_byte(par, &data[i]);
0556 if (err)
0557 goto failout;
0558 }
0559
0560 failout:
0561 broadsheet_write_reg(par, 0x0208, 0);
0562 return err;
0563 }
0564
0565 #define BS_SPIFLASH_PAGE_SIZE 256
0566 static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
0567 int addr, const char *data)
0568 {
0569 int err;
0570 int i;
0571
0572 broadsheet_spiflash_write_control(par, 1);
0573
0574 err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
0575 if (err)
0576 goto failout;
0577
0578 for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
0579 err = broadsheet_spiflash_write_byte(par, data[i]);
0580 if (err)
0581 goto failout;
0582 }
0583
0584 broadsheet_write_reg(par, 0x0208, 0);
0585
0586 err = broadsheet_spiflash_wait_for_status(par, 100);
0587
0588 failout:
0589 return err;
0590 }
0591
0592 static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
0593 int addr, const char *data, int sector_size)
0594 {
0595 int i;
0596 int err;
0597
0598 for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
0599 err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
0600 if (err)
0601 return err;
0602 }
0603 return 0;
0604 }
0605
0606
0607
0608
0609
0610
0611 static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
0612 int sector_size, int data_start_addr,
0613 int data_len, const char *data)
0614 {
0615 int err;
0616 char *sector_buffer;
0617 int tail_start_addr;
0618 int start_sector_addr;
0619
0620 sector_buffer = kzalloc(sector_size, GFP_KERNEL);
0621 if (!sector_buffer)
0622 return -ENOMEM;
0623
0624
0625 start_sector_addr = (data_start_addr / sector_size) * sector_size;
0626
0627
0628
0629
0630
0631 if (data_start_addr != start_sector_addr) {
0632
0633
0634
0635
0636 err = broadsheet_spiflash_read_range(par, start_sector_addr,
0637 data_start_addr, sector_buffer);
0638 if (err)
0639 goto out;
0640 }
0641
0642
0643 memcpy(sector_buffer + data_start_addr, data, data_len);
0644
0645
0646
0647
0648
0649 tail_start_addr = (data_start_addr + data_len) % sector_size;
0650
0651 if (tail_start_addr) {
0652 int tail_len;
0653
0654 tail_len = sector_size - tail_start_addr;
0655
0656
0657 err = broadsheet_spiflash_read_range(par, tail_start_addr,
0658 tail_len, sector_buffer + tail_start_addr);
0659 if (err)
0660 goto out;
0661 }
0662
0663
0664
0665
0666 err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
0667 if (err)
0668 goto out;
0669
0670
0671 err = broadsheet_spiflash_write_sector(par, start_sector_addr,
0672 sector_buffer, sector_size);
0673 out:
0674 kfree(sector_buffer);
0675 return err;
0676 }
0677
0678 static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
0679 const u8 *wfm, int bytecount, int flash_type)
0680 {
0681 int sector_size;
0682 int err;
0683 int cur_addr;
0684 int writecount;
0685 int maxlen;
0686 int offset = 0;
0687
0688 switch (flash_type) {
0689 case 0x10:
0690 sector_size = 32*1024;
0691 break;
0692 case 0x11:
0693 default:
0694 sector_size = 64*1024;
0695 break;
0696 }
0697
0698 while (bytecount) {
0699 cur_addr = wfm_addr + offset;
0700 maxlen = roundup(cur_addr, sector_size) - cur_addr;
0701 writecount = min(bytecount, maxlen);
0702
0703 err = broadsheet_spiflash_rewrite_sector(par, sector_size,
0704 cur_addr, writecount, wfm + offset);
0705 if (err)
0706 return err;
0707
0708 offset += writecount;
0709 bytecount -= writecount;
0710 }
0711
0712 return 0;
0713 }
0714
0715 static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
0716 const u8 *wfm, size_t wfm_size)
0717 {
0718 int err = 0;
0719 u16 initial_sfmcd = 0;
0720 int flash_type = 0;
0721
0722 err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
0723 if (err)
0724 goto failout;
0725
0726 err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
0727
0728 failout:
0729 broadsheet_write_reg(par, 0x0204, initial_sfmcd);
0730 return err;
0731 }
0732
0733 static ssize_t broadsheet_loadstore_waveform(struct device *dev,
0734 struct device_attribute *attr,
0735 const char *buf, size_t len)
0736 {
0737 int err;
0738 struct fb_info *info = dev_get_drvdata(dev);
0739 struct broadsheetfb_par *par = info->par;
0740 const struct firmware *fw_entry;
0741
0742 if (len < 1)
0743 return -EINVAL;
0744
0745 err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
0746 if (err < 0) {
0747 dev_err(dev, "Failed to get broadsheet waveform\n");
0748 goto err_failed;
0749 }
0750
0751
0752 if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
0753 dev_err(dev, "Invalid waveform\n");
0754 err = -EINVAL;
0755 goto err_fw;
0756 }
0757
0758 mutex_lock(&(par->io_lock));
0759 err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
0760 fw_entry->size);
0761
0762 mutex_unlock(&(par->io_lock));
0763 if (err < 0) {
0764 dev_err(dev, "Failed to store broadsheet waveform\n");
0765 goto err_fw;
0766 }
0767
0768 dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
0769
0770 err = len;
0771
0772 err_fw:
0773 release_firmware(fw_entry);
0774 err_failed:
0775 return err;
0776 }
0777 static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
0778 broadsheet_loadstore_waveform);
0779
0780
0781 static void broadsheet_init_display(struct broadsheetfb_par *par)
0782 {
0783 u16 args[5];
0784 int xres = par->info->var.xres;
0785 int yres = par->info->var.yres;
0786
0787 args[0] = panel_table[par->panel_index].w;
0788 args[1] = panel_table[par->panel_index].h;
0789 args[2] = panel_table[par->panel_index].sdcfg;
0790 args[3] = panel_table[par->panel_index].gdcfg;
0791 args[4] = panel_table[par->panel_index].lutfmt;
0792 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
0793
0794
0795 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
0796
0797 args[0] = panel_table[par->panel_index].fsynclen;
0798 args[1] = panel_table[par->panel_index].fendfbegin;
0799 args[2] = panel_table[par->panel_index].lsynclen;
0800 args[3] = panel_table[par->panel_index].lendlbegin;
0801 args[4] = panel_table[par->panel_index].pixclk;
0802 broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
0803
0804 broadsheet_write_reg32(par, 0x310, xres*yres*2);
0805
0806
0807 args[0] = 0x886;
0808 args[1] = 0;
0809 broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
0810
0811 broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
0812
0813 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
0814
0815 broadsheet_write_reg(par, 0x330, 0x84);
0816
0817 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
0818
0819 args[0] = (0x3 << 4);
0820 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
0821
0822 args[0] = 0x154;
0823 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
0824
0825 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
0826 panel_table[par->panel_index].h)/2,
0827 (u16 *) par->info->screen_base);
0828
0829 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
0830
0831 args[0] = 0x4300;
0832 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
0833
0834 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
0835
0836 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
0837
0838 par->board->wait_for_rdy(par);
0839 }
0840
0841 static void broadsheet_identify(struct broadsheetfb_par *par)
0842 {
0843 u16 rev, prc;
0844 struct device *dev = par->info->device;
0845
0846 rev = broadsheet_read_reg(par, BS_REG_REV);
0847 prc = broadsheet_read_reg(par, BS_REG_PRC);
0848 dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
0849
0850 if (prc != 0x0047)
0851 dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
0852 if (rev != 0x0100)
0853 dev_warn(dev, "Unrecognized Broadsheet Revision\n");
0854 }
0855
0856 static void broadsheet_init(struct broadsheetfb_par *par)
0857 {
0858 broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
0859
0860 msleep(1000);
0861 broadsheet_init_display(par);
0862 }
0863
0864 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
0865 u16 y1, u16 y2)
0866 {
0867 u16 args[5];
0868 unsigned char *buf = (unsigned char *)par->info->screen_base;
0869
0870 mutex_lock(&(par->io_lock));
0871
0872 y1 &= 0xFFFC;
0873
0874 y2 |= 0x0003;
0875
0876 args[0] = 0x3 << 4;
0877 args[1] = 0;
0878 args[2] = y1;
0879 args[3] = cpu_to_le16(par->info->var.xres);
0880 args[4] = y2;
0881 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
0882
0883 args[0] = 0x154;
0884 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
0885
0886 buf += y1 * par->info->var.xres;
0887 broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
0888 (u16 *) buf);
0889
0890 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
0891
0892 args[0] = 0x4300;
0893 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
0894
0895 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
0896
0897 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
0898
0899 par->board->wait_for_rdy(par);
0900 mutex_unlock(&(par->io_lock));
0901
0902 }
0903
0904 static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
0905 {
0906 u16 args[5];
0907
0908 mutex_lock(&(par->io_lock));
0909 args[0] = 0x3 << 4;
0910 broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
0911
0912 args[0] = 0x154;
0913 broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
0914 broadsheet_burst_write(par, (panel_table[par->panel_index].w *
0915 panel_table[par->panel_index].h)/2,
0916 (u16 *) par->info->screen_base);
0917
0918 broadsheet_send_command(par, BS_CMD_LD_IMG_END);
0919
0920 args[0] = 0x4300;
0921 broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
0922
0923 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
0924
0925 broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
0926
0927 par->board->wait_for_rdy(par);
0928 mutex_unlock(&(par->io_lock));
0929 }
0930
0931
0932 static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist)
0933 {
0934 u16 y1 = 0, h = 0;
0935 unsigned long prev_offset = ULONG_MAX;
0936 struct fb_deferred_io_pageref *pageref;
0937 int h_inc;
0938 u16 yres = info->var.yres;
0939 u16 xres = info->var.xres;
0940
0941
0942 h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
0943
0944
0945 list_for_each_entry(pageref, pagereflist, list) {
0946 if (prev_offset == ULONG_MAX) {
0947
0948 y1 = pageref->offset / xres;
0949 h = h_inc;
0950 } else if ((prev_offset + PAGE_SIZE) == pageref->offset) {
0951
0952 h += h_inc;
0953 } else {
0954
0955 broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
0956
0957 y1 = pageref->offset / xres;
0958 h = h_inc;
0959 }
0960 prev_offset = pageref->offset;
0961 }
0962
0963
0964 if (h >= yres) {
0965
0966 broadsheetfb_dpy_update(info->par);
0967 } else {
0968 broadsheetfb_dpy_update_pages(info->par, y1,
0969 min((u16) (y1 + h), yres));
0970 }
0971 }
0972
0973 static void broadsheetfb_fillrect(struct fb_info *info,
0974 const struct fb_fillrect *rect)
0975 {
0976 struct broadsheetfb_par *par = info->par;
0977
0978 sys_fillrect(info, rect);
0979
0980 broadsheetfb_dpy_update(par);
0981 }
0982
0983 static void broadsheetfb_copyarea(struct fb_info *info,
0984 const struct fb_copyarea *area)
0985 {
0986 struct broadsheetfb_par *par = info->par;
0987
0988 sys_copyarea(info, area);
0989
0990 broadsheetfb_dpy_update(par);
0991 }
0992
0993 static void broadsheetfb_imageblit(struct fb_info *info,
0994 const struct fb_image *image)
0995 {
0996 struct broadsheetfb_par *par = info->par;
0997
0998 sys_imageblit(info, image);
0999
1000 broadsheetfb_dpy_update(par);
1001 }
1002
1003
1004
1005
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 const 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 .fb_mmap = fb_deferred_io_mmap,
1057 };
1058
1059 static struct fb_deferred_io broadsheetfb_defio = {
1060 .delay = HZ/4,
1061 .sort_pagereflist = true,
1062 .deferred_io = broadsheetfb_dpy_deferred_io,
1063 };
1064
1065 static int broadsheetfb_probe(struct platform_device *dev)
1066 {
1067 struct fb_info *info;
1068 struct broadsheet_board *board;
1069 int retval = -ENOMEM;
1070 int videomemorysize;
1071 unsigned char *videomemory;
1072 struct broadsheetfb_par *par;
1073 int i;
1074 int dpyw, dpyh;
1075 int panel_index;
1076
1077
1078 board = dev->dev.platform_data;
1079 if (!board)
1080 return -EINVAL;
1081
1082
1083 if (!try_module_get(board->owner))
1084 return -ENODEV;
1085
1086 info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1087 if (!info)
1088 goto err;
1089
1090 switch (board->get_panel_type()) {
1091 case 37:
1092 panel_index = 1;
1093 break;
1094 case 97:
1095 panel_index = 2;
1096 break;
1097 case 6:
1098 default:
1099 panel_index = 0;
1100 break;
1101 }
1102
1103 dpyw = panel_table[panel_index].w;
1104 dpyh = panel_table[panel_index].h;
1105
1106 videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1107
1108 videomemory = vzalloc(videomemorysize);
1109 if (!videomemory)
1110 goto err_fb_rel;
1111
1112 info->screen_base = (char *)videomemory;
1113 info->fbops = &broadsheetfb_ops;
1114
1115 broadsheetfb_var.xres = dpyw;
1116 broadsheetfb_var.yres = dpyh;
1117 broadsheetfb_var.xres_virtual = dpyw;
1118 broadsheetfb_var.yres_virtual = dpyh;
1119 info->var = broadsheetfb_var;
1120
1121 broadsheetfb_fix.line_length = dpyw;
1122 info->fix = broadsheetfb_fix;
1123 info->fix.smem_len = videomemorysize;
1124 par = info->par;
1125 par->panel_index = panel_index;
1126 par->info = info;
1127 par->board = board;
1128 par->write_reg = broadsheet_write_reg;
1129 par->read_reg = broadsheet_read_reg;
1130 init_waitqueue_head(&par->waitq);
1131
1132 mutex_init(&par->io_lock);
1133
1134 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
1135
1136 info->fbdefio = &broadsheetfb_defio;
1137 fb_deferred_io_init(info);
1138
1139 retval = fb_alloc_cmap(&info->cmap, 16, 0);
1140 if (retval < 0) {
1141 dev_err(&dev->dev, "Failed to allocate colormap\n");
1142 goto err_vfree;
1143 }
1144
1145
1146 for (i = 0; i < 16; i++)
1147 info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1148 memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1149 memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1150
1151 retval = par->board->setup_irq(info);
1152 if (retval < 0)
1153 goto err_cmap;
1154
1155
1156 retval = board->init(par);
1157 if (retval < 0)
1158 goto err_free_irq;
1159
1160 broadsheet_identify(par);
1161
1162 broadsheet_init(par);
1163
1164 retval = register_framebuffer(info);
1165 if (retval < 0)
1166 goto err_free_irq;
1167
1168 platform_set_drvdata(dev, info);
1169
1170 retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1171 if (retval < 0)
1172 goto err_unreg_fb;
1173
1174 fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
1175 videomemorysize >> 10);
1176
1177
1178 return 0;
1179
1180 err_unreg_fb:
1181 unregister_framebuffer(info);
1182 err_free_irq:
1183 board->cleanup(par);
1184 err_cmap:
1185 fb_dealloc_cmap(&info->cmap);
1186 err_vfree:
1187 vfree(videomemory);
1188 err_fb_rel:
1189 framebuffer_release(info);
1190 err:
1191 module_put(board->owner);
1192 return retval;
1193
1194 }
1195
1196 static int broadsheetfb_remove(struct platform_device *dev)
1197 {
1198 struct fb_info *info = platform_get_drvdata(dev);
1199
1200 if (info) {
1201 struct broadsheetfb_par *par = info->par;
1202
1203 device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1204 unregister_framebuffer(info);
1205 fb_deferred_io_cleanup(info);
1206 par->board->cleanup(par);
1207 fb_dealloc_cmap(&info->cmap);
1208 vfree((void *)info->screen_base);
1209 module_put(par->board->owner);
1210 framebuffer_release(info);
1211 }
1212 return 0;
1213 }
1214
1215 static struct platform_driver broadsheetfb_driver = {
1216 .probe = broadsheetfb_probe,
1217 .remove = broadsheetfb_remove,
1218 .driver = {
1219 .name = "broadsheetfb",
1220 },
1221 };
1222 module_platform_driver(broadsheetfb_driver);
1223
1224 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1225 MODULE_AUTHOR("Jaya Kumar");
1226 MODULE_LICENSE("GPL");