2 * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
4 * Copyright (C) 2008, Jaya Kumar
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
10 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
12 * This driver is written to be used with the Broadsheet display controller.
14 * It is intended to be architecture independent. A board specific driver
15 * must be used to perform all the physical IO interactions.
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/errno.h>
22 #include <linux/string.h>
24 #include <linux/slab.h>
25 #include <linux/vmalloc.h>
26 #include <linux/delay.h>
27 #include <linux/interrupt.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>
35 #include <video/broadsheetfb.h>
37 /* track panel specific parameters */
51 /* table of panel specific parameters to be indexed into by the board drivers */
52 static struct panel_info panel_table
[] = {
53 { /* standard 6" on TFT backplane */
56 .sdcfg
= (100 | (1 << 8) | (1 << 9)),
58 .lutfmt
= (4 | (1 << 7)),
60 .fendfbegin
= (10 << 8) | 4,
62 .lendlbegin
= (100 << 8) | 4,
65 { /* custom 3.7" flexible on PET or steel */
68 .sdcfg
= (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
70 .lutfmt
= (4 | (1 << 7)),
72 .fendfbegin
= (80 << 8) | 4,
74 .lendlbegin
= (80 << 8) | 20,
77 { /* standard 9.7" on TFT backplane */
80 .sdcfg
= (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
82 .lutfmt
= (4 | (1 << 7)),
84 .fendfbegin
= (4 << 8) | 4,
86 .lendlbegin
= (60 << 8) | 10,
94 static struct fb_fix_screeninfo broadsheetfb_fix __devinitdata
= {
96 .type
= FB_TYPE_PACKED_PIXELS
,
97 .visual
= FB_VISUAL_STATIC_PSEUDOCOLOR
,
101 .line_length
= DPY_W
,
102 .accel
= FB_ACCEL_NONE
,
105 static struct fb_var_screeninfo broadsheetfb_var __devinitdata
= {
108 .xres_virtual
= DPY_W
,
109 .yres_virtual
= DPY_H
,
113 .green
= { 0, 4, 0 },
115 .transp
= { 0, 0, 0 },
118 /* main broadsheetfb functions */
119 static void broadsheet_gpio_issue_data(struct broadsheetfb_par
*par
, u16 data
)
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);
126 static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par
*par
, u16 data
)
128 par
->board
->set_ctl(par
, BS_DC
, 0);
129 broadsheet_gpio_issue_data(par
, data
);
132 static void broadsheet_gpio_send_command(struct broadsheetfb_par
*par
, u16 data
)
134 par
->board
->wait_for_rdy(par
);
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);
142 static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par
*par
, u16 cmd
,
147 par
->board
->wait_for_rdy(par
);
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);
153 for (i
= 0; i
< argc
; i
++)
154 broadsheet_gpio_issue_data(par
, argv
[i
]);
155 par
->board
->set_ctl(par
, BS_CS
, 1);
158 static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par
*par
, u16 cmd
,
163 par
->board
->mmio_write(par
, BS_MMIO_CMD
, cmd
);
165 for (i
= 0; i
< argc
; i
++)
166 par
->board
->mmio_write(par
, BS_MMIO_DATA
, argv
[i
]);
169 static void broadsheet_send_command(struct broadsheetfb_par
*par
, u16 data
)
171 if (par
->board
->mmio_write
)
172 par
->board
->mmio_write(par
, BS_MMIO_CMD
, data
);
174 broadsheet_gpio_send_command(par
, data
);
177 static void broadsheet_send_cmdargs(struct broadsheetfb_par
*par
, u16 cmd
,
180 if (par
->board
->mmio_write
)
181 broadsheet_mmio_send_cmdargs(par
, cmd
, argc
, argv
);
183 broadsheet_gpio_send_cmdargs(par
, cmd
, argc
, argv
);
186 static void broadsheet_gpio_burst_write(struct broadsheetfb_par
*par
, int size
,
192 par
->board
->set_ctl(par
, BS_CS
, 0);
193 par
->board
->set_ctl(par
, BS_DC
, 1);
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);
203 par
->board
->set_ctl(par
, BS_CS
, 1);
206 static void broadsheet_mmio_burst_write(struct broadsheetfb_par
*par
, int size
,
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
);
220 static void broadsheet_burst_write(struct broadsheetfb_par
*par
, int size
,
223 if (par
->board
->mmio_write
)
224 broadsheet_mmio_burst_write(par
, size
, data
);
226 broadsheet_gpio_burst_write(par
, size
, data
);
229 static u16
broadsheet_gpio_get_data(struct broadsheetfb_par
*par
)
232 /* wait for ready to go hi. (lo is busy) */
233 par
->board
->wait_for_rdy(par
);
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);
240 res
= par
->board
->get_hdb(par
);
243 par
->board
->set_ctl(par
, BS_WR
, 1);
244 par
->board
->set_ctl(par
, BS_CS
, 1);
250 static u16
broadsheet_get_data(struct broadsheetfb_par
*par
)
252 if (par
->board
->mmio_read
)
253 return par
->board
->mmio_read(par
);
255 return broadsheet_gpio_get_data(par
);
258 static void broadsheet_gpio_write_reg(struct broadsheetfb_par
*par
, u16 reg
,
261 /* wait for ready to go hi. (lo is busy) */
262 par
->board
->wait_for_rdy(par
);
264 /* cs lo, dc lo for cmd, we lo for each data, db as usual */
265 par
->board
->set_ctl(par
, BS_CS
, 0);
267 broadsheet_gpio_issue_cmd(par
, BS_CMD_WR_REG
);
269 par
->board
->set_ctl(par
, BS_DC
, 1);
271 broadsheet_gpio_issue_data(par
, reg
);
272 broadsheet_gpio_issue_data(par
, data
);
274 par
->board
->set_ctl(par
, BS_CS
, 1);
277 static void broadsheet_mmio_write_reg(struct broadsheetfb_par
*par
, u16 reg
,
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
);
286 static void broadsheet_write_reg(struct broadsheetfb_par
*par
, u16 reg
,
289 if (par
->board
->mmio_write
)
290 broadsheet_mmio_write_reg(par
, reg
, data
);
292 broadsheet_gpio_write_reg(par
, reg
, data
);
295 static void broadsheet_write_reg32(struct broadsheetfb_par
*par
, u16 reg
,
298 broadsheet_write_reg(par
, reg
, cpu_to_le32(data
) & 0xFFFF);
299 broadsheet_write_reg(par
, reg
+ 2, (cpu_to_le32(data
) >> 16) & 0xFFFF);
303 static u16
broadsheet_read_reg(struct broadsheetfb_par
*par
, u16 reg
)
305 broadsheet_send_cmdargs(par
, BS_CMD_RD_REG
, 1, ®
);
306 par
->board
->wait_for_rdy(par
);
307 return broadsheet_get_data(par
);
310 /* functions for waveform manipulation */
311 static int is_broadsheet_pll_locked(struct broadsheetfb_par
*par
)
313 return broadsheet_read_reg(par
, 0x000A) & 0x0001;
316 static int broadsheet_setup_plls(struct broadsheetfb_par
*par
)
321 /* disable arral saemipu mode */
322 broadsheet_write_reg(par
, 0x0006, 0x0000);
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);
330 if (retry_count
++ > 100)
333 } while (!is_broadsheet_pll_locked(par
));
335 tmp
= broadsheet_read_reg(par
, 0x0006);
337 broadsheet_write_reg(par
, 0x0006, tmp
);
342 static int broadsheet_setup_spi(struct broadsheetfb_par
*par
)
345 broadsheet_write_reg(par
, 0x0204, ((3 << 3) | 1));
346 broadsheet_write_reg(par
, 0x0208, 0x0001);
351 static int broadsheet_setup_spiflash(struct broadsheetfb_par
*par
,
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));
363 static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par
*par
,
364 u16 reg
, int bitnum
, int val
,
370 tmp
= broadsheet_read_reg(par
, reg
);
371 if (((tmp
>> bitnum
) & 1) == val
)
379 static int broadsheet_spiflash_write_byte(struct broadsheetfb_par
*par
, u8 data
)
381 broadsheet_write_reg(par
, 0x0202, (data
| 0x100));
383 return broadsheet_spiflash_wait_for_bit(par
, 0x0206, 3, 0, 100);
386 static int broadsheet_spiflash_read_byte(struct broadsheetfb_par
*par
, u8
*data
)
391 broadsheet_write_reg(par
, 0x0202, 0);
393 err
= broadsheet_spiflash_wait_for_bit(par
, 0x0206, 3, 0, 100);
397 tmp
= broadsheet_read_reg(par
, 0x200);
404 static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par
*par
,
411 broadsheet_write_reg(par
, 0x0208, 1);
413 err
= broadsheet_spiflash_write_byte(par
, 0x05);
417 err
= broadsheet_spiflash_read_byte(par
, &tmp
);
421 broadsheet_write_reg(par
, 0x0208, 0);
429 dev_err(par
->info
->device
, "Timed out waiting for spiflash status\n");
433 broadsheet_write_reg(par
, 0x0208, 0);
437 static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par
*par
,
444 broadsheet_write_reg(par
, 0x0208, 1);
446 err
= broadsheet_spiflash_write_byte(par
, op
);
450 for (i
= 2; i
>= 0; i
--) {
451 tmp
= ((addr
>> (i
* 8)) & 0xFF);
452 err
= broadsheet_spiflash_write_byte(par
, tmp
);
460 static int broadsheet_verify_spiflash(struct broadsheetfb_par
*par
,
466 err
= broadsheet_spiflash_op_on_address(par
, 0xAB, 0x00000000);
470 err
= broadsheet_spiflash_read_byte(par
, &sig
);
474 if ((sig
!= 0x10) && (sig
!= 0x11)) {
475 dev_err(par
->info
->device
, "Unexpected flash type\n");
483 broadsheet_write_reg(par
, 0x0208, 0);
487 static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par
*par
,
488 u16
*initial_sfmcd
, int *flash_type
)
493 err
= broadsheet_setup_plls(par
);
497 broadsheet_write_reg(par
, 0x0106, 0x0203);
499 err
= broadsheet_setup_spi(par
);
503 err
= broadsheet_setup_spiflash(par
, initial_sfmcd
);
507 return broadsheet_verify_spiflash(par
, flash_type
);
510 static int broadsheet_spiflash_write_control(struct broadsheetfb_par
*par
,
515 broadsheet_write_reg(par
, 0x0208, 1);
517 err
= broadsheet_spiflash_write_byte(par
, 0x06);
519 err
= broadsheet_spiflash_write_byte(par
, 0x04);
521 broadsheet_write_reg(par
, 0x0208, 0);
525 static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par
*par
,
530 broadsheet_spiflash_write_control(par
, 1);
532 err
= broadsheet_spiflash_op_on_address(par
, 0xD8, addr
);
534 broadsheet_write_reg(par
, 0x0208, 0);
539 err
= broadsheet_spiflash_wait_for_status(par
, 1000);
544 static int broadsheet_spiflash_read_range(struct broadsheetfb_par
*par
,
545 int addr
, int size
, char *data
)
550 err
= broadsheet_spiflash_op_on_address(par
, 0x03, addr
);
554 for (i
= 0; i
< size
; i
++) {
555 err
= broadsheet_spiflash_read_byte(par
, &data
[i
]);
561 broadsheet_write_reg(par
, 0x0208, 0);
565 #define BS_SPIFLASH_PAGE_SIZE 256
566 static int broadsheet_spiflash_write_page(struct broadsheetfb_par
*par
,
567 int addr
, const char *data
)
572 broadsheet_spiflash_write_control(par
, 1);
574 err
= broadsheet_spiflash_op_on_address(par
, 0x02, addr
);
578 for (i
= 0; i
< BS_SPIFLASH_PAGE_SIZE
; i
++) {
579 err
= broadsheet_spiflash_write_byte(par
, data
[i
]);
584 broadsheet_write_reg(par
, 0x0208, 0);
586 err
= broadsheet_spiflash_wait_for_status(par
, 100);
592 static int broadsheet_spiflash_write_sector(struct broadsheetfb_par
*par
,
593 int addr
, const char *data
, int sector_size
)
598 for (i
= 0; i
< sector_size
; i
+= BS_SPIFLASH_PAGE_SIZE
) {
599 err
= broadsheet_spiflash_write_page(par
, addr
+ i
, &data
[i
]);
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.
611 static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par
*par
,
612 int sector_size
, int data_start_addr
,
613 int data_len
, const char *data
)
618 int start_sector_addr
;
620 sector_buffer
= kzalloc(sizeof(char)*sector_size
, GFP_KERNEL
);
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
;
628 * check if there is head data that we need to readback into our sector
631 if (data_start_addr
!= start_sector_addr
) {
633 * we need to read every byte up till the start address of our
634 * data and we put it into our sector buffer.
636 err
= broadsheet_spiflash_read_range(par
, start_sector_addr
,
637 data_start_addr
, sector_buffer
);
642 /* now we copy our data into the right place in the sector buffer */
643 memcpy(sector_buffer
+ data_start_addr
, data
, data_len
);
646 * now we check if there is a tail section of the sector that we need to
649 tail_start_addr
= (data_start_addr
+ data_len
) % sector_size
;
651 if (tail_start_addr
) {
654 tail_len
= sector_size
- tail_start_addr
;
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
);
663 /* if we got here we have the full sector that we want to rewrite. */
665 /* first erase the sector */
666 err
= broadsheet_spiflash_erase_sector(par
, start_sector_addr
);
671 err
= broadsheet_spiflash_write_sector(par
, start_sector_addr
,
672 sector_buffer
, sector_size
);
676 static int broadsheet_write_spiflash(struct broadsheetfb_par
*par
, u32 wfm_addr
,
677 const u8
*wfm
, int bytecount
, int flash_type
)
686 switch (flash_type
) {
688 sector_size
= 32*1024;
692 sector_size
= 64*1024;
697 cur_addr
= wfm_addr
+ offset
;
698 maxlen
= roundup(cur_addr
, sector_size
) - cur_addr
;
699 writecount
= min(bytecount
, maxlen
);
701 err
= broadsheet_spiflash_rewrite_sector(par
, sector_size
,
702 cur_addr
, writecount
, wfm
+ offset
);
706 offset
+= writecount
;
707 bytecount
-= writecount
;
713 static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par
*par
,
714 const u8
*wfm
, size_t wfm_size
)
717 u16 initial_sfmcd
= 0;
720 err
= broadsheet_setup_for_wfm_write(par
, &initial_sfmcd
, &flash_type
);
724 err
= broadsheet_write_spiflash(par
, 0x886, wfm
, wfm_size
, flash_type
);
727 broadsheet_write_reg(par
, 0x0204, initial_sfmcd
);
731 static ssize_t
broadsheet_loadstore_waveform(struct device
*dev
,
732 struct device_attribute
*attr
,
733 const char *buf
, size_t len
)
736 struct fb_info
*info
= dev_get_drvdata(dev
);
737 struct broadsheetfb_par
*par
= info
->par
;
738 const struct firmware
*fw_entry
;
743 err
= request_firmware(&fw_entry
, "broadsheet.wbf", dev
);
745 dev_err(dev
, "Failed to get broadsheet waveform\n");
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");
756 mutex_lock(&(par
->io_lock
));
757 err
= broadsheet_store_waveform_to_spiflash(par
, fw_entry
->data
,
760 mutex_unlock(&(par
->io_lock
));
762 dev_err(dev
, "Failed to store broadsheet waveform\n");
766 dev_info(dev
, "Stored broadsheet waveform, size %zd\n", fw_entry
->size
);
773 static DEVICE_ATTR(loadstore_waveform
, S_IWUSR
, NULL
,
774 broadsheet_loadstore_waveform
);
776 /* upper level functions that manipulate the display and other stuff */
777 static void __devinit
broadsheet_init_display(struct broadsheetfb_par
*par
)
780 int xres
= par
->info
->var
.xres
;
781 int yres
= par
->info
->var
.yres
;
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
);
790 /* did the controller really set it? */
791 broadsheet_send_cmdargs(par
, BS_CMD_INIT_DSPE_CFG
, 5, args
);
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
);
800 broadsheet_write_reg32(par
, 0x310, xres
*yres
*2);
805 broadsheet_send_cmdargs(par
, BS_CMD_RD_WFM_INFO
, 2, args
);
807 broadsheet_send_command(par
, BS_CMD_UPD_GDRV_CLR
);
809 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_TRG
);
811 broadsheet_write_reg(par
, 0x330, 0x84);
813 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_TRG
);
815 args
[0] = (0x3 << 4);
816 broadsheet_send_cmdargs(par
, BS_CMD_LD_IMG
, 1, args
);
819 broadsheet_send_cmdargs(par
, BS_CMD_WR_REG
, 1, args
);
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
);
825 broadsheet_send_command(par
, BS_CMD_LD_IMG_END
);
828 broadsheet_send_cmdargs(par
, BS_CMD_UPD_FULL
, 1, args
);
830 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_TRG
);
832 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_FREND
);
834 par
->board
->wait_for_rdy(par
);
837 static void __devinit
broadsheet_identify(struct broadsheetfb_par
*par
)
840 struct device
*dev
= par
->info
->device
;
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
);
847 dev_warn(dev
, "Unrecognized Broadsheet Product Code\n");
849 dev_warn(dev
, "Unrecognized Broadsheet Revision\n");
852 static void __devinit
broadsheet_init(struct broadsheetfb_par
*par
)
854 broadsheet_send_command(par
, BS_CMD_INIT_SYS_RUN
);
855 /* the controller needs a second */
857 broadsheet_init_display(par
);
860 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par
*par
,
864 unsigned char *buf
= (unsigned char *)par
->info
->screen_base
;
866 mutex_lock(&(par
->io_lock
));
867 /* y1 must be a multiple of 4 so drop the lower bits */
869 /* y2 must be a multiple of 4 , but - 1 so up the lower bits */
875 args
[3] = cpu_to_le16(par
->info
->var
.xres
);
877 broadsheet_send_cmdargs(par
, BS_CMD_LD_IMG_AREA
, 5, args
);
880 broadsheet_send_cmdargs(par
, BS_CMD_WR_REG
, 1, args
);
882 buf
+= y1
* par
->info
->var
.xres
;
883 broadsheet_burst_write(par
, ((1 + y2
- y1
) * par
->info
->var
.xres
)/2,
886 broadsheet_send_command(par
, BS_CMD_LD_IMG_END
);
889 broadsheet_send_cmdargs(par
, BS_CMD_UPD_FULL
, 1, args
);
891 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_TRG
);
893 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_FREND
);
895 par
->board
->wait_for_rdy(par
);
896 mutex_unlock(&(par
->io_lock
));
900 static void broadsheetfb_dpy_update(struct broadsheetfb_par
*par
)
904 mutex_lock(&(par
->io_lock
));
906 broadsheet_send_cmdargs(par
, BS_CMD_LD_IMG
, 1, args
);
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
);
914 broadsheet_send_command(par
, BS_CMD_LD_IMG_END
);
917 broadsheet_send_cmdargs(par
, BS_CMD_UPD_FULL
, 1, args
);
919 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_TRG
);
921 broadsheet_send_command(par
, BS_CMD_WAIT_DSPE_FREND
);
923 par
->board
->wait_for_rdy(par
);
924 mutex_unlock(&(par
->io_lock
));
927 /* this is called back from the deferred io workqueue */
928 static void broadsheetfb_dpy_deferred_io(struct fb_info
*info
,
929 struct list_head
*pagelist
)
934 struct fb_deferred_io
*fbdefio
= info
->fbdefio
;
936 u16 yres
= info
->var
.yres
;
937 u16 xres
= info
->var
.xres
;
939 /* height increment is fixed per page */
940 h_inc
= DIV_ROUND_UP(PAGE_SIZE
, xres
);
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
;
948 } else if ((prev_index
+ 1) == cur
->index
) {
949 /* this page is consecutive so increase our height */
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
;
958 prev_index
= cur
->index
;
961 /* if we still have any pages to update we do so now */
963 /* its a full screen update, just do it */
964 broadsheetfb_dpy_update(info
->par
);
966 broadsheetfb_dpy_update_pages(info
->par
, y1
,
967 min((u16
) (y1
+ h
), yres
));
971 static void broadsheetfb_fillrect(struct fb_info
*info
,
972 const struct fb_fillrect
*rect
)
974 struct broadsheetfb_par
*par
= info
->par
;
976 sys_fillrect(info
, rect
);
978 broadsheetfb_dpy_update(par
);
981 static void broadsheetfb_copyarea(struct fb_info
*info
,
982 const struct fb_copyarea
*area
)
984 struct broadsheetfb_par
*par
= info
->par
;
986 sys_copyarea(info
, area
);
988 broadsheetfb_dpy_update(par
);
991 static void broadsheetfb_imageblit(struct fb_info
*info
,
992 const struct fb_image
*image
)
994 struct broadsheetfb_par
*par
= info
->par
;
996 sys_imageblit(info
, image
);
998 broadsheetfb_dpy_update(par
);
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
1005 static ssize_t
broadsheetfb_write(struct fb_info
*info
, const char __user
*buf
,
1006 size_t count
, loff_t
*ppos
)
1008 struct broadsheetfb_par
*par
= info
->par
;
1009 unsigned long p
= *ppos
;
1012 unsigned long total_size
;
1014 if (info
->state
!= FBINFO_STATE_RUNNING
)
1017 total_size
= info
->fix
.smem_len
;
1022 if (count
> total_size
) {
1027 if (count
+ p
> total_size
) {
1031 count
= total_size
- p
;
1034 dst
= (void *)(info
->screen_base
+ p
);
1036 if (copy_from_user(dst
, buf
, count
))
1042 broadsheetfb_dpy_update(par
);
1044 return (err
) ? err
: count
;
1047 static 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
,
1056 static struct fb_deferred_io broadsheetfb_defio
= {
1058 .deferred_io
= broadsheetfb_dpy_deferred_io
,
1061 static int __devinit
broadsheetfb_probe(struct platform_device
*dev
)
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
;
1073 /* pick up board specific routines */
1074 board
= dev
->dev
.platform_data
;
1078 /* try to count device specific driver, if can't, platform recalls */
1079 if (!try_module_get(board
->owner
))
1082 info
= framebuffer_alloc(sizeof(struct broadsheetfb_par
), &dev
->dev
);
1086 switch (board
->get_panel_type()) {
1099 dpyw
= panel_table
[panel_index
].w
;
1100 dpyh
= panel_table
[panel_index
].h
;
1102 videomemorysize
= roundup((dpyw
*dpyh
), PAGE_SIZE
);
1104 videomemory
= vzalloc(videomemorysize
);
1108 info
->screen_base
= (char *)videomemory
;
1109 info
->fbops
= &broadsheetfb_ops
;
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
;
1117 broadsheetfb_fix
.line_length
= dpyw
;
1118 info
->fix
= broadsheetfb_fix
;
1119 info
->fix
.smem_len
= videomemorysize
;
1121 par
->panel_index
= panel_index
;
1124 par
->write_reg
= broadsheet_write_reg
;
1125 par
->read_reg
= broadsheet_read_reg
;
1126 init_waitqueue_head(&par
->waitq
);
1128 mutex_init(&par
->io_lock
);
1130 info
->flags
= FBINFO_FLAG_DEFAULT
| FBINFO_VIRTFB
;
1132 info
->fbdefio
= &broadsheetfb_defio
;
1133 fb_deferred_io_init(info
);
1135 retval
= fb_alloc_cmap(&info
->cmap
, 16, 0);
1137 dev_err(&dev
->dev
, "Failed to allocate colormap\n");
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);
1147 retval
= par
->board
->setup_irq(info
);
1151 /* this inits the dpy */
1152 retval
= board
->init(par
);
1156 broadsheet_identify(par
);
1158 broadsheet_init(par
);
1160 retval
= register_framebuffer(info
);
1164 platform_set_drvdata(dev
, info
);
1166 retval
= device_create_file(&dev
->dev
, &dev_attr_loadstore_waveform
);
1171 "fb%d: Broadsheet frame buffer, using %dK of video memory\n",
1172 info
->node
, videomemorysize
>> 10);
1178 unregister_framebuffer(info
);
1180 board
->cleanup(par
);
1182 fb_dealloc_cmap(&info
->cmap
);
1186 framebuffer_release(info
);
1188 module_put(board
->owner
);
1193 static int __devexit
broadsheetfb_remove(struct platform_device
*dev
)
1195 struct fb_info
*info
= platform_get_drvdata(dev
);
1198 struct broadsheetfb_par
*par
= info
->par
;
1200 device_remove_file(info
->dev
, &dev_attr_loadstore_waveform
);
1201 unregister_framebuffer(info
);
1202 fb_deferred_io_cleanup(info
);
1203 par
->board
->cleanup(par
);
1204 fb_dealloc_cmap(&info
->cmap
);
1205 vfree((void *)info
->screen_base
);
1206 module_put(par
->board
->owner
);
1207 framebuffer_release(info
);
1212 static struct platform_driver broadsheetfb_driver
= {
1213 .probe
= broadsheetfb_probe
,
1214 .remove
= broadsheetfb_remove
,
1216 .owner
= THIS_MODULE
,
1217 .name
= "broadsheetfb",
1221 static int __init
broadsheetfb_init(void)
1223 return platform_driver_register(&broadsheetfb_driver
);
1226 static void __exit
broadsheetfb_exit(void)
1228 platform_driver_unregister(&broadsheetfb_driver
);
1231 module_init(broadsheetfb_init
);
1232 module_exit(broadsheetfb_exit
);
1234 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1235 MODULE_AUTHOR("Jaya Kumar");
1236 MODULE_LICENSE("GPL");