Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
0003  *
0004  * Copyright (C) 2008, Jaya Kumar
0005  *
0006  * This file is subject to the terms and conditions of the GNU General Public
0007  * License. See the file COPYING in the main directory of this archive for
0008  * more details.
0009  *
0010  * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
0011  *
0012  * This driver is written to be used with the Broadsheet display controller.
0013  *
0014  * It is intended to be architecture independent. A board specific driver
0015  * must be used to perform all the physical IO interactions.
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 /* track panel specific parameters */
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 /* table of panel specific parameters to be indexed into by the board drivers */
0052 static struct panel_info panel_table[] = {
0053     {   /* standard 6" on TFT backplane */
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     {   /* custom 3.7" flexible on PET or steel */
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     {   /* standard 9.7" on TFT backplane */
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 /* main broadsheetfb functions */
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     /* wait for ready to go hi. (lo is busy) */
0233     par->board->wait_for_rdy(par);
0234 
0235     /* cs lo, dc lo for cmd, we lo for each data, db as usual */
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     /* strobe wr */
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     /* wait for ready to go hi. (lo is busy) */
0262     par->board->wait_for_rdy(par);
0263 
0264     /* cs lo, dc lo for cmd, we lo for each data, db as usual */
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, &reg);
0306     par->board->wait_for_rdy(par);
0307     return broadsheet_get_data(par);
0308 }
0309 
0310 /* functions for waveform manipulation */
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     /* disable arral saemipu mode */
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  * The caller must guarantee that the data to be rewritten is entirely
0608  * contained within this sector. That is, data_start_addr + data_len
0609  * must be less than sector_start_addr + sector_size.
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     /* the start address of the sector is the 0th byte of that sector */
0625     start_sector_addr = (data_start_addr / sector_size) * sector_size;
0626 
0627     /*
0628      * check if there is head data that we need to readback into our sector
0629      * buffer first
0630      */
0631     if (data_start_addr != start_sector_addr) {
0632         /*
0633          * we need to read every byte up till the start address of our
0634          * data and we put it into our sector buffer.
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     /* now we copy our data into the right place in the sector buffer */
0643     memcpy(sector_buffer + data_start_addr, data, data_len);
0644 
0645     /*
0646      * now we check if there is a tail section of the sector that we need to
0647      * readback.
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         /* now we read this tail into our sector buffer */
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     /* if we got here we have the full sector that we want to rewrite. */
0664 
0665     /* first erase the sector */
0666     err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
0667     if (err)
0668         goto out;
0669 
0670     /* now write it */
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     /* try to enforce reasonable min max on waveform */
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 /* upper level functions that manipulate the display and other stuff */
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     /* did the controller really set it? */
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     /* setup waveform */
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     /* the controller needs a second */
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     /* y1 must be a multiple of 4 so drop the lower bits */
0872     y1 &= 0xFFFC;
0873     /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
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 /* this is called back from the deferred io workqueue */
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     /* height increment is fixed per page */
0942     h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
0943 
0944     /* walk the written page list and swizzle the data */
0945     list_for_each_entry(pageref, pagereflist, list) {
0946         if (prev_offset == ULONG_MAX) {
0947             /* just starting so assign first page */
0948             y1 = pageref->offset / xres;
0949             h = h_inc;
0950         } else if ((prev_offset + PAGE_SIZE) == pageref->offset) {
0951             /* this page is consecutive so increase our height */
0952             h += h_inc;
0953         } else {
0954             /* page not consecutive, issue previous update first */
0955             broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
0956             /* start over with our non consecutive page */
0957             y1 = pageref->offset / xres;
0958             h = h_inc;
0959         }
0960         prev_offset = pageref->offset;
0961     }
0962 
0963     /* if we still have any pages to update we do so now */
0964     if (h >= yres) {
0965         /* its a full screen update, just do it */
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  * 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 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     /* pick up board specific routines */
1078     board = dev->dev.platform_data;
1079     if (!board)
1080         return -EINVAL;
1081 
1082     /* try to count device specific driver, if can't, platform recalls */
1083     if (!try_module_get(board->owner))
1084         return -ENODEV;
1085 
1086     info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1087     if (!info)
1088         goto err;
1089 
1090     switch (board->get_panel_type()) {
1091     case 37:
1092         panel_index = 1;
1093         break;
1094     case 97:
1095         panel_index = 2;
1096         break;
1097     case 6:
1098     default:
1099         panel_index = 0;
1100         break;
1101     }
1102 
1103     dpyw = panel_table[panel_index].w;
1104     dpyh = panel_table[panel_index].h;
1105 
1106     videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1107 
1108     videomemory = vzalloc(videomemorysize);
1109     if (!videomemory)
1110         goto err_fb_rel;
1111 
1112     info->screen_base = (char *)videomemory;
1113     info->fbops = &broadsheetfb_ops;
1114 
1115     broadsheetfb_var.xres = dpyw;
1116     broadsheetfb_var.yres = dpyh;
1117     broadsheetfb_var.xres_virtual = dpyw;
1118     broadsheetfb_var.yres_virtual = dpyh;
1119     info->var = broadsheetfb_var;
1120 
1121     broadsheetfb_fix.line_length = dpyw;
1122     info->fix = broadsheetfb_fix;
1123     info->fix.smem_len = videomemorysize;
1124     par = info->par;
1125     par->panel_index = panel_index;
1126     par->info = info;
1127     par->board = board;
1128     par->write_reg = broadsheet_write_reg;
1129     par->read_reg = broadsheet_read_reg;
1130     init_waitqueue_head(&par->waitq);
1131 
1132     mutex_init(&par->io_lock);
1133 
1134     info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
1135 
1136     info->fbdefio = &broadsheetfb_defio;
1137     fb_deferred_io_init(info);
1138 
1139     retval = fb_alloc_cmap(&info->cmap, 16, 0);
1140     if (retval < 0) {
1141         dev_err(&dev->dev, "Failed to allocate colormap\n");
1142         goto err_vfree;
1143     }
1144 
1145     /* set cmap */
1146     for (i = 0; i < 16; i++)
1147         info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1148     memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1149     memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1150 
1151     retval = par->board->setup_irq(info);
1152     if (retval < 0)
1153         goto err_cmap;
1154 
1155     /* this inits the dpy */
1156     retval = board->init(par);
1157     if (retval < 0)
1158         goto err_free_irq;
1159 
1160     broadsheet_identify(par);
1161 
1162     broadsheet_init(par);
1163 
1164     retval = register_framebuffer(info);
1165     if (retval < 0)
1166         goto err_free_irq;
1167 
1168     platform_set_drvdata(dev, info);
1169 
1170     retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1171     if (retval < 0)
1172         goto err_unreg_fb;
1173 
1174     fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
1175         videomemorysize >> 10);
1176 
1177 
1178     return 0;
1179 
1180 err_unreg_fb:
1181     unregister_framebuffer(info);
1182 err_free_irq:
1183     board->cleanup(par);
1184 err_cmap:
1185     fb_dealloc_cmap(&info->cmap);
1186 err_vfree:
1187     vfree(videomemory);
1188 err_fb_rel:
1189     framebuffer_release(info);
1190 err:
1191     module_put(board->owner);
1192     return retval;
1193 
1194 }
1195 
1196 static int broadsheetfb_remove(struct platform_device *dev)
1197 {
1198     struct fb_info *info = platform_get_drvdata(dev);
1199 
1200     if (info) {
1201         struct broadsheetfb_par *par = info->par;
1202 
1203         device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1204         unregister_framebuffer(info);
1205         fb_deferred_io_cleanup(info);
1206         par->board->cleanup(par);
1207         fb_dealloc_cmap(&info->cmap);
1208         vfree((void *)info->screen_base);
1209         module_put(par->board->owner);
1210         framebuffer_release(info);
1211     }
1212     return 0;
1213 }
1214 
1215 static struct platform_driver broadsheetfb_driver = {
1216     .probe  = broadsheetfb_probe,
1217     .remove = broadsheetfb_remove,
1218     .driver = {
1219         .name   = "broadsheetfb",
1220     },
1221 };
1222 module_platform_driver(broadsheetfb_driver);
1223 
1224 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1225 MODULE_AUTHOR("Jaya Kumar");
1226 MODULE_LICENSE("GPL");