1/* 2 * epson1356fb.c -- Epson SED1356 Framebuffer Driver 3 * 4 * Copyright 2001, 2002 MontaVista Software Inc. 5 * Author: MontaVista Software, Inc. 6 * stevel@mvista.com or source@mvista.com 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 14 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 16 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 19 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 * You should have received a copy of the GNU General Public License along 25 * with this program; if not, write to the Free Software Foundation, Inc., 26 * 675 Mass Ave, Cambridge, MA 02139, USA. 27 * 28 * 29 * TODO: 30 * 31 * Revision history 32 * 03.12.2001 0.1 Initial release 33 * 34 */ 35 36#include <linux/config.h> 37#include <linux/version.h> 38#include <linux/module.h> 39 40#include <linux/kernel.h> 41#include <linux/errno.h> 42#include <linux/string.h> 43#include <linux/mm.h> 44#include <linux/tty.h> 45#include <linux/slab.h> 46#include <linux/vmalloc.h> 47#include <linux/delay.h> 48#include <linux/interrupt.h> 49#include <linux/fb.h> 50#include <linux/selection.h> 51#include <linux/console.h> 52#include <linux/init.h> 53#include <linux/pci.h> 54#include <linux/nvram.h> 55#include <linux/kd.h> 56#include <linux/vt_kern.h> 57#include <asm/io.h> 58#include <asm/uaccess.h> 59#include <linux/timer.h> 60#include <linux/pagemap.h> 61 62#include <asm/pgalloc.h> 63#include <asm/uaccess.h> 64#include <asm/tlb.h> 65 66#ifdef CONFIG_MTRR 67#include <asm/mtrr.h> 68#endif 69 70#include <video/fbcon.h> 71#include <video/fbcon-cfb8.h> 72#include <video/fbcon-cfb16.h> 73#include <video/fbcon-cfb24.h> 74#include <video/fbcon-cfb32.h> 75 76#include <linux/spinlock.h> 77 78#include <video/e1356fb.h> 79 80#ifdef CONFIG_CPU_AU1X00 81#include <asm/au1000.h> 82#endif 83 84#define E1356FB_DEBUG 1 85#undef E1356FB_VERBOSE_DEBUG 86#undef SHADOW_FRAME_BUFFER 87#include "epson1356fb.h" 88 89static char *options; 90MODULE_PARM(options, "s"); 91 92/* 93 * Frame buffer device API 94 */ 95static int e1356fb_open(struct fb_info *fb, int user); 96static int e1356fb_release(struct fb_info *fb, int user); 97static int e1356fb_get_fix(struct fb_fix_screeninfo* fix, 98 int con, 99 struct fb_info* fb); 100static int e1356fb_get_var(struct fb_var_screeninfo* var, 101 int con, 102 struct fb_info* fb); 103static int e1356fb_set_var(struct fb_var_screeninfo* var, 104 int con, 105 struct fb_info* fb); 106static int e1356fb_pan_display(struct fb_var_screeninfo* var, 107 int con, 108 struct fb_info* fb); 109static int e1356fb_get_cmap(struct fb_cmap *cmap, 110 int kspc, 111 int con, 112 struct fb_info* info); 113static int e1356fb_set_cmap(struct fb_cmap* cmap, 114 int kspc, 115 int con, 116 struct fb_info* info); 117static int e1356fb_ioctl(struct inode* inode, 118 struct file* file, 119 u_int cmd, 120 u_long arg, 121 int con, 122 struct fb_info* info); 123static int e1356fb_mmap(struct fb_info *info, 124 struct file *file, 125 struct vm_area_struct *vma); 126 127/* 128 * Interface to the low level console driver 129 */ 130static int e1356fb_switch_con(int con, 131 struct fb_info* fb); 132static int e1356fb_updatevar(int con, 133 struct fb_info* fb); 134static void e1356fb_blank(int blank, 135 struct fb_info* fb); 136 137/* 138 * Internal routines 139 */ 140static void e1356fb_set_par(const struct e1356fb_par* par, 141 struct fb_info_e1356* 142 info); 143static int e1356fb_var_to_par(const struct fb_var_screeninfo *var, 144 struct e1356fb_par* par, 145 const struct fb_info_e1356* info); 146static int e1356fb_par_to_var(struct fb_var_screeninfo* var, 147 struct e1356fb_par* par, 148 const struct fb_info_e1356* info); 149static int e1356fb_encode_fix(struct fb_fix_screeninfo* fix, 150 const struct e1356fb_par* par, 151 const struct fb_info_e1356* info); 152static void e1356fb_set_dispsw(struct display* disp, 153 struct fb_info_e1356* info, 154 int bpp, 155 int accel); 156static int e1356fb_getcolreg(u_int regno, 157 u_int* red, 158 u_int* green, 159 u_int* blue, 160 u_int* transp, 161 struct fb_info* fb); 162static int e1356fb_setcolreg(u_int regno, 163 u_int red, 164 u_int green, 165 u_int blue, 166 u_int transp, 167 struct fb_info* fb); 168static void e1356fb_install_cmap(struct display *d, 169 struct fb_info *info); 170 171static void e1356fb_hwcursor_init(struct fb_info_e1356* info); 172static void e1356fb_createcursorshape(struct display* p); 173static void e1356fb_createcursor(struct display * p); 174 175/* 176 * do_xxx: Hardware-specific functions 177 */ 178static void do_pan_var(struct fb_var_screeninfo* var, 179 struct fb_info_e1356* i); 180static void do_flashcursor(unsigned long ptr); 181static void doBlt_Move(const struct e1356fb_par* par, 182 struct fb_info_e1356* i, 183 blt_info_t* blt); 184static void doBlt_SolidFill(const struct e1356fb_par* par, 185 struct fb_info_e1356* i, 186 blt_info_t* blt); 187 188/* 189 * Interface used by the world 190 */ 191int e1356fb_init(void); 192void e1356fb_setup(char *options, int *ints); 193 194static int currcon = 0; 195 196static struct fb_ops e1356fb_ops = { 197 owner: THIS_MODULE, 198 fb_open: e1356fb_open, 199 fb_release: e1356fb_release, 200 fb_get_fix: e1356fb_get_fix, 201 fb_get_var: e1356fb_get_var, 202 fb_set_var: e1356fb_set_var, 203 fb_get_cmap: e1356fb_get_cmap, 204 fb_set_cmap: e1356fb_set_cmap, 205 fb_pan_display: e1356fb_pan_display, 206 fb_mmap: e1356fb_mmap, 207}; 208 209#define PCI_VENDOR_ID_EPSON 0x10f4 210#define PCI_DEVICE_ID_EPSON_SDU1356 0x1300 211 212 213static struct fb_info_e1356 fb_info; 214static struct e1356fb_fix boot_fix; // boot options 215static struct e1356fb_par boot_par; // boot options 216 217static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot); 218 219 220/* ------------------------------------------------------------------------- 221 * Hardware-specific funcions 222 * ------------------------------------------------------------------------- */ 223 224/* 225 * The SED1356 has only a 16-bit wide data bus, so some embedded 226 * implementations with 32-bit CPU's (Alchemy Pb1000) may not 227 * correctly emulate a 32-bit write to the framebuffer by splitting 228 * the write into two seperate 16-bit writes. So it is safest to 229 * only do byte or half-word writes to the fb. This routine assumes 230 * fbaddr is atleast aligned on a half-word boundary. 231 */ 232static inline void 233fbfill(u16* fbaddr, u8 val, int size) 234{ 235 u16 valw = (u16)val | ((u16)val << 8); 236 for ( ; size >= 2; size -= 2) 237 writew(valw, fbaddr++); 238 if (size) 239 writeb(val, (u8*)fbaddr); 240} 241 242static inline int 243e1356_wait_bitclr(u8* reg, u8 bit, int timeout) 244{ 245 while (readb(reg) & bit) { 246 udelay(10); 247 if (!--timeout) 248 break; 249 } 250 return timeout; 251} 252 253static inline int 254e1356_wait_bitset(u8* reg, u8 bit, int timeout) 255{ 256 while (!(readb(reg) & bit)) { 257 udelay(10); 258 if (!--timeout) 259 break; 260 } 261 return timeout; 262} 263 264 265static struct fb_videomode panel_modedb[] = { 266 { 267 /* 320x240 @ 109 Hz, 33.3 kHz hsync */ 268 NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3), 269 16, 16, 32, 24, 48, 8, 270 0, FB_VMODE_NONINTERLACED 271 }, { 272 /* 640x480 @ 84 Hz, 48.1 kHz hsync */ 273 NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1), 274 96, 32, 32, 48, 64, 8, 275 0, FB_VMODE_NONINTERLACED 276 }, { 277 /* 800x600 @ 76 Hz, 46.3 kHz hsync */ 278 NULL, 76, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1), 279 32, 10, 1, 1, 22, 1, 280 0, FB_VMODE_NONINTERLACED 281 } 282}; 283static struct fb_videomode crt_modedb[] = { 284 { 285 /* 320x240 @ 84 Hz, 31.25 kHz hsync */ 286 NULL, 84, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/2), 287 128, 128, 60, 60, 64, 8, 288 0, FB_VMODE_NONINTERLACED 289 }, { 290 /* 320x240 @ 109 Hz, 33.3 kHz hsync */ 291 NULL, 109, 320, 240, KHZ2PICOS(MAX_PIXCLOCK/3), 292 16, 16, 32, 24, 48, 8, 293 0, FB_VMODE_NONINTERLACED 294 }, { 295 /* 512x384 @ 77 Hz, 31.25 kHz hsync */ 296 NULL, 77, 512, 384, KHZ2PICOS(MAX_PIXCLOCK/2), 297 48, 16, 16, 1, 64, 3, 298 0, FB_VMODE_NONINTERLACED 299 }, { 300 /* 640x400 @ 88 Hz, 43.1 kHz hsync */ 301 NULL, 88, 640, 400, KHZ2PICOS(MAX_PIXCLOCK/1), 302 128, 96, 32, 48, 64, 8, 303 0, FB_VMODE_NONINTERLACED 304 }, { 305 /* 640x480 @ 84 Hz, 48.1 kHz hsync */ 306 NULL, 84, 640, 480, KHZ2PICOS(MAX_PIXCLOCK/1), 307 96, 32, 32, 48, 64, 8, 308 0, FB_VMODE_NONINTERLACED 309 }, { 310 /* 768x576 @ 62 Hz, 38.5 kHz hsync */ 311 NULL, 62, 768, 576, KHZ2PICOS(MAX_PIXCLOCK/1), 312 144, 16, 28, 6, 112, 4, 313 0, FB_VMODE_NONINTERLACED 314 }, { 315 /* 800x600 @ 60 Hz, 37.9 kHz hsync */ 316 NULL, 60, 800, 600, KHZ2PICOS(MAX_PIXCLOCK/1), 317 88, 40, 23, 1, 128, 4, 318 FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 319 FB_VMODE_NONINTERLACED 320 } 321}; 322 323static struct fb_videomode ntsc_modedb[] = { 324 { 325 /* 640x480 @ 62 Hz, requires flicker filter */ 326 //NULL, 62, 640, 480, 34921, 213, 57, 20, 2, 0, 0, 327 NULL, 62, 640, 480, KHZ2PICOS(2*NTSC_PIXCLOCK), 328 200, 70, 15, 7, 0, 0, 329 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED 330 } 331}; 332static struct fb_videomode pal_modedb[] = { 333 { 334 /* 640x480 @ 56 Hz, requires flicker filter */ 335 NULL, 56, 640, 480, KHZ2PICOS(2*PAL_PIXCLOCK), 336 350, 145, 49, 23, 0, 0, 337 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED 338 } 339}; 340 341 342static inline void 343fb_videomode_to_var(struct fb_videomode* mode, 344 struct fb_var_screeninfo*var) 345{ 346 var->xres = mode->xres; 347 var->yres = mode->yres; 348 var->pixclock = mode->pixclock; 349 var->left_margin = mode->left_margin; 350 var->right_margin = mode->right_margin; 351 var->upper_margin = mode->upper_margin; 352 var->lower_margin = mode->lower_margin; 353 var->hsync_len = mode->hsync_len; 354 var->vsync_len = mode->vsync_len; 355 var->sync = mode->sync; 356 var->vmode = mode->vmode; 357} 358 359 360static int 361e1356fb_get_mode(const struct fb_info_e1356 *info, 362 int xres, 363 int yres, 364 struct fb_videomode ** modedb, 365 struct fb_videomode ** mode) 366{ 367 struct fb_videomode * ret; 368 int i, dbsize; 369 370 if (IS_PANEL(info->fix.disp_type)) { 371 ret = panel_modedb; 372 dbsize = sizeof(panel_modedb)/sizeof(struct fb_videomode); 373 } else if (info->fix.disp_type == DISP_TYPE_CRT) { 374 ret = crt_modedb; 375 dbsize = sizeof(crt_modedb)/sizeof(struct fb_videomode); 376 } else if (info->fix.disp_type == DISP_TYPE_NTSC) { 377 ret = ntsc_modedb; 378 dbsize = sizeof(ntsc_modedb)/sizeof(struct fb_videomode); 379 } else { 380 ret = pal_modedb; 381 dbsize = sizeof(pal_modedb)/sizeof(struct fb_videomode); 382 } 383 384 if (modedb) 385 *modedb = ret; 386 for (i=0; i<dbsize; i++) { 387 if (xres == ret[i].xres && yres == ret[i].yres) { 388 *mode = &ret[i]; 389 break; 390 } 391 } 392 if (i == dbsize) 393 return -EINVAL; 394 return dbsize; 395} 396 397 398 399#ifdef E1356FB_VERBOSE_DEBUG 400static void 401dump_par(const struct e1356fb_par* par) 402{ 403 DPRINTK("width: %d\n", par->width); 404 DPRINTK("height: %d\n", par->height); 405 DPRINTK("width_virt: %d\n", par->width_virt); 406 DPRINTK("height_virt: %d\n", par->height_virt); 407 DPRINTK("bpp: %d\n", par->bpp); 408 DPRINTK("pixclock: %d\n", par->ipclk.pixclk); 409 DPRINTK("horiz_ndp: %d\n", par->horiz_ndp); 410 DPRINTK("vert_ndp: %d\n", par->vert_ndp); 411 DPRINTK("hsync_pol: %d\n", par->hsync_pol); 412 DPRINTK("hsync_start: %d\n", par->hsync_start); 413 DPRINTK("hsync_width: %d\n", par->hsync_width); 414 DPRINTK("vsync_pol: %d\n", par->vsync_pol); 415 DPRINTK("vsync_start: %d\n", par->vsync_start); 416 DPRINTK("vsync_width: %d\n", par->vsync_width); 417 DPRINTK("cmap_len: %d\n", par->cmap_len); 418} 419 420static void 421dump_display_regs(reg_dispcfg_t* dispcfg, reg_dispmode_t* dispmode) 422{ 423 DPRINTK("hdw: 0x%02x\n", readb(&dispcfg->hdw)); 424 DPRINTK("hndp: 0x%02x\n", readb(&dispcfg->hndp)); 425 DPRINTK("hsync_start: 0x%02x\n", readb(&dispcfg->hsync_start)); 426 DPRINTK("hsync_pulse: 0x%02x\n", readb(&dispcfg->hsync_pulse)); 427 DPRINTK("vdh0: 0x%02x\n", readb(&dispcfg->vdh0)); 428 DPRINTK("vdh1: 0x%02x\n", readb(&dispcfg->vdh1)); 429 DPRINTK("vndp: 0x%02x\n", readb(&dispcfg->vndp)); 430 DPRINTK("vsync_start: 0x%02x\n", readb(&dispcfg->vsync_start)); 431 DPRINTK("vsync_pulse: 0x%02x\n", readb(&dispcfg->vsync_pulse)); 432 DPRINTK("tv_output_ctrl: 0x%02x\n\n", readb(&dispcfg->tv_output_ctrl)); 433 434 DPRINTK("disp_mode: 0x%02x\n", readb(&dispmode->disp_mode)); 435 DPRINTK("lcd_misc: 0x%02x\n", readb(&dispmode->lcd_misc)); 436 DPRINTK("start_addr0: 0x%02x\n", readb(&dispmode->start_addr0)); 437 DPRINTK("start_addr1: 0x%02x\n", readb(&dispmode->start_addr1)); 438 DPRINTK("start_addr2: 0x%02x\n", readb(&dispmode->start_addr2)); 439 DPRINTK("mem_addr_offset0: 0x%02x\n", readb(&dispmode->mem_addr_offset0)); 440 DPRINTK("mem_addr_offset1: 0x%02x\n", readb(&dispmode->mem_addr_offset1)); 441 DPRINTK("pixel_panning: 0x%02x\n", readb(&dispmode->pixel_panning)); 442 DPRINTK("fifo_high_thresh: 0x%02x\n", readb(&dispmode->fifo_high_thresh)); 443 DPRINTK("fifo_low_thresh: 0x%02x\n", readb(&dispmode->fifo_low_thresh)); 444} 445 446static void 447dump_fb(u8* base, int len) 448{ 449 int i; 450 DPRINTK("FB memory dump, start 0x%p, len %d", base, len); 451 for (i=0; i<len; i++) { 452 if (!(i%16)) 453 printk("\n%p: %02x ", &base[i], readb(&base[i])); 454 else 455 printk("%02x ", readb(&base[i])); 456 } 457 printk("\n"); 458} 459 460#endif // E1356FB_VERBOSE_DEBUG 461 462 463 464// Input: ipclk->clksrc, ipclk->pixclk_d 465// Output: ipclk->pixclk, ipclk->error, and ipclk->divisor 466static int 467get_nearest_pixclk_div(pixclock_info_t* ipclk, int x2) 468{ 469 int pixclk_d = ipclk->pixclk_d; 470 int clksrc = ipclk->clksrc; 471 472 if (x2) clksrc *= 2; 473 474 if (clksrc < (3*pixclk_d+1)/2) 475 ipclk->divisor = 1; 476 else if (clksrc < (5*pixclk_d+1)/2) 477 ipclk->divisor = 2; 478 else if (clksrc < (7*pixclk_d+1)/2) 479 ipclk->divisor = 3; 480 else if (clksrc < (9*pixclk_d+1)/2) 481 ipclk->divisor = 4; 482 else 483 return -ENXIO; 484 485 ipclk->pixclk = clksrc / ipclk->divisor; 486 ipclk->error = (100*(pixclk_d - ipclk->pixclk)) / pixclk_d; 487 return 0; 488} 489 490static int 491e1356_calc_pixclock(const struct fb_info_e1356 *info, 492 pixclock_info_t* ipclk) 493{ 494 int src_sel=-1, flicker_mult=0; 495 pixclock_info_t test, ret; 496 497 if (ipclk->pixclk > info->max_pixclock) 498 return -ENXIO; 499 500 test.pixclk_d = ipclk->pixclk_d; 501 ret.error = 100; 502 503 if (IS_TV(info->fix.disp_type) && 504 (info->fix.tv_filt & TV_FILT_FLICKER)) 505 flicker_mult = 0x80; 506 507 test.clksrc = info->fix.busclk; 508 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 && 509 abs(test.error) < abs(ret.error)) { 510 ret = test; 511 src_sel = 0x01; 512 } 513 514 test.clksrc = info->fix.mclk; 515 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 && 516 abs(test.error) < abs(ret.error)) { 517 ret = test; 518 src_sel = 0x03; 519 } 520 521 test.clksrc = info->fix.clki; 522 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 && 523 abs(test.error) < abs(ret.error)) { 524 ret = test; 525 src_sel = 0x00; 526 } 527 528 test.clksrc = info->fix.clki2; 529 if (get_nearest_pixclk_div(&test, flicker_mult != 0) == 0 && 530 abs(test.error) < abs(ret.error)) { 531 ret = test; 532 src_sel = 0x02; 533 } 534 535 if (ret.error > MAX_PCLK_ERROR_LOWER || 536 ret.error < MAX_PCLK_ERROR_HIGHER) 537 return -ENXIO; 538 539 ret.pixclk_bits = flicker_mult | ((ret.divisor-1)<<4) | src_sel; 540 *ipclk = ret; 541 return 0; 542} 543 544static inline int 545e1356_engine_wait_complete(reg_bitblt_t* bltreg) 546{ 547 return e1356_wait_bitclr(&bltreg->ctrl0, 0x80, 5000); 548} 549static inline int 550e1356_engine_wait_busy(reg_bitblt_t* bltreg) 551{ 552 return e1356_wait_bitset(&bltreg->ctrl0, 0x80, 5000); 553} 554 555static void 556e1356fb_engine_init(const struct e1356fb_par* par, 557 struct fb_info_e1356* info) 558{ 559 reg_bitblt_t* bltreg = info->reg.bitblt; 560 561 e1356_engine_wait_complete(bltreg); 562 563 writeb(0, &bltreg->ctrl0); 564 writeb(0, &bltreg->ctrl1); 565 writeb(0, &bltreg->rop_code); 566 writeb(0, &bltreg->operation); 567 writeb(0, &bltreg->src_start_addr0); 568 writeb(0, &bltreg->src_start_addr1); 569 writeb(0, &bltreg->src_start_addr2); 570 writeb(0, &bltreg->dest_start_addr0); 571 writeb(0, &bltreg->dest_start_addr1); 572 writeb(0, &bltreg->dest_start_addr2); 573 writew(0, &bltreg->mem_addr_offset0); 574 writew(0, &bltreg->width0); 575 writew(0, &bltreg->height0); 576 writew(0, &bltreg->bg_color0); 577 writew(0, &bltreg->fg_color0); 578} 579 580 581static void doBlt_Write(const struct e1356fb_par* par, 582 struct fb_info_e1356* info, 583 blt_info_t* blt) 584{ 585 reg_bitblt_t* bltreg = info->reg.bitblt; 586 int nWords, nTotalWords; 587 u32 srcphase, dstAddr; 588 u16* w16; 589 u32 stride = par->width_virt * par->Bpp; 590 591 dstAddr = blt->dst_x * par->Bpp + blt->dst_y * stride; 592 srcphase = (u32)blt->src & 1; 593 594 if (blt->attribute & BLT_ATTR_TRANSPARENT) 595 writew(blt->bg_color, &bltreg->bg_color0); 596 else 597 writeb(blt->rop, &bltreg->rop_code); 598 599 writeb(blt->operation, &bltreg->operation); 600 writeb((u8)srcphase, &bltreg->src_start_addr0); 601 writew(stride/2, &bltreg->mem_addr_offset0); 602 603 writeb(dstAddr, &bltreg->dest_start_addr0); 604 writeb(dstAddr>>8, &bltreg->dest_start_addr1); 605 writeb(dstAddr>>16, &bltreg->dest_start_addr2); 606 607 writew(blt->dst_width-1, &bltreg->width0); 608 writew(blt->dst_height-1, &bltreg->height0); 609 610 // program color format operation 611 writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1); 612 613 // start it up 614 writeb(0x80, &bltreg->ctrl0); 615 616 // wait for it to actually start 617 e1356_engine_wait_busy(bltreg); 618 619 // calculate the number of 16 bit words per one blt line 620 621 nWords = srcphase + ((blt->dst_width - srcphase)*par->Bpp + 1) / 2; 622 nTotalWords = nWords*blt->dst_height; 623 w16 = (u16*)((u32)blt->src & 0xfffffffe); // Word aligned 624 625 while (nTotalWords > 0) { 626 int j, nFIFO; 627 u8 ctrl0; 628 629 // read the FIFO status 630 ctrl0 = readb(&bltreg->ctrl0); 631 632 if ((ctrl0 & 0x30) == 0x20) 633 // FIFO is at least half full, but not full 634 nFIFO = 1; 635 else if ((ctrl0 & 0x40) == 0) 636 // FIFO is empty 637 nFIFO = 16; 638 else 639 // FIFO is full 640 continue; 641 642 for (j = 0; j < nFIFO && nTotalWords > 0; j++,nTotalWords--) 643 writew(*w16++, info->reg.bitblt_data); 644 } 645 646 e1356_engine_wait_complete(bltreg); 647} 648 649 650static void 651doBlt_SolidFill(const struct e1356fb_par* par, 652 struct fb_info_e1356* info, 653 blt_info_t* blt) 654{ 655 reg_bitblt_t* bltreg = info->reg.bitblt; 656 u32 width = blt->dst_width, height = blt->dst_height; 657 u32 stride = par->width_virt * par->Bpp; 658 u32 dest_addr = (blt->dst_y * stride) + (blt->dst_x * par->Bpp); 659 660 if (width == 0 || height == 0) 661 return; 662 663 // program dest address 664 writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0); 665 writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1); 666 writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2); 667 668 // program width and height of solid-fill blit 669 writew(width-1, &bltreg->width0); 670 writew(height-1, &bltreg->height0); 671 672 // program color of fill 673 writew(blt->fg_color, &bltreg->fg_color0); 674 // select solid-fill BLIT 675 writeb(BLT_SOLID_FILL, &bltreg->operation); 676 // program color format operation 677 writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1); 678 // program BLIT memory offset 679 writew(stride/2, &bltreg->mem_addr_offset0); 680 681 // start it up (self completes) 682 writeb(0x80, &bltreg->ctrl0); 683 684 e1356_engine_wait_complete(bltreg); 685} 686 687 688static void 689doBlt_Move(const struct e1356fb_par* par, 690 struct fb_info_e1356* info, 691 blt_info_t* blt) 692{ 693 reg_bitblt_t* bltreg = info->reg.bitblt; 694 int neg_dir=0; 695 u32 dest_addr, src_addr; 696 u32 bpp = par->bpp; 697 u32 stride = par->width_virt * par->Bpp; // virt line length in bytes 698 u32 srcx = blt->src_x, srcy = blt->src_y; 699 u32 dstx = blt->dst_x, dsty = blt->dst_y; 700 u32 width = blt->dst_width, height = blt->dst_height; 701 702 if (width == 0 || height == 0) 703 return; 704 705 src_addr = srcx*par->Bpp + srcy*stride; 706 dest_addr = dstx*par->Bpp + dsty*stride; 707 708 /* 709 * See if regions overlap and dest region is beyond source region. 710 * If so, we need to do a move BLT in negative direction. Only applies 711 * if the BLT is not transparent. 712 */ 713 if (!(blt->attribute & BLT_ATTR_TRANSPARENT)) { 714 if ((srcx + width > dstx) && (srcx < dstx + width) && 715 (srcy + height > dsty) && (srcy < dsty + height) && 716 (dest_addr > src_addr)) { 717 neg_dir = 1; 718 // negative direction : get the coords of lower right corner 719 src_addr += stride * (height-1) + par->Bpp * (width-1); 720 dest_addr += stride * (height-1) + par->Bpp * (width-1); 721 } 722 } 723 724 // program BLIT memory offset 725 writew(stride/2, &bltreg->mem_addr_offset0); 726 727 // program src and dest addresses 728 writeb(src_addr & 0x00ff, &bltreg->src_start_addr0); 729 writeb((src_addr>>8) & 0x00ff, &bltreg->src_start_addr1); 730 writeb((src_addr>>16) & 0x00ff, &bltreg->src_start_addr2); 731 writeb(dest_addr & 0x00ff, &bltreg->dest_start_addr0); 732 writeb((dest_addr>>8) & 0x00ff, &bltreg->dest_start_addr1); 733 writeb((dest_addr>>16) & 0x00ff, &bltreg->dest_start_addr2); 734 735 // program width and height of blit 736 writew(width-1, &bltreg->width0); 737 writew(height-1, &bltreg->height0); 738 739 // program color format operation 740 writeb(bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1); 741 742 // set the blt type 743 if (blt->attribute & BLT_ATTR_TRANSPARENT) { 744 writew(blt->bg_color, &bltreg->bg_color0); 745 writeb(BLT_MOVE_POS_TRANSP, &bltreg->operation); 746 } else { 747 writeb(blt->rop, &bltreg->rop_code); 748 // select pos/neg move BLIT 749 writeb(neg_dir ? BLT_MOVE_NEG_ROP : BLT_MOVE_POS_ROP, 750 &bltreg->operation); 751 } 752 753 // start it up (self completes) 754 writeb(0x80, &bltreg->ctrl0); 755 756 e1356_engine_wait_complete(bltreg); 757} 758 759 760static void doBlt_ColorExpand(const struct e1356fb_par* par, 761 struct fb_info_e1356* info, 762 blt_info_t* blt) 763{ 764 reg_bitblt_t* bltreg = info->reg.bitblt; 765 int i, j, nWords, Sx, Sy; 766 u32 dstAddr; 767 u16* wpt, *wpt1; 768 u32 stride = par->width_virt * par->Bpp; 769 770 if (blt->dst_width == 0 || blt->dst_height == 0) 771 return; 772 773 Sx = blt->src_x; 774 Sy = blt->src_y; 775 776 writeb((7 - Sx%8), &bltreg->rop_code); 777 778 writeb(blt->operation, &bltreg->operation); 779 780 writeb((u8)(Sx & 1), &bltreg->src_start_addr0); 781 782 dstAddr = blt->dst_x*par->Bpp + blt->dst_y * stride; 783 writeb(dstAddr, &bltreg->dest_start_addr0); 784 writeb(dstAddr>>8, &bltreg->dest_start_addr1); 785 writeb(dstAddr>>16, &bltreg->dest_start_addr2); 786 787 // program color format operation 788 writeb(par->bpp == 8 ? 0x00 : 0x01, &bltreg->ctrl1); 789 writew(stride/2, &bltreg->mem_addr_offset0); 790 writew(blt->dst_width-1, &bltreg->width0); 791 writew(blt->dst_height-1, &bltreg->height0); 792 writew(blt->bg_color, &bltreg->bg_color0); 793 writew(blt->fg_color, &bltreg->fg_color0); 794 795 // start it up 796 writeb(0x80, &bltreg->ctrl0); 797 798 // wait for it to actually start 799 e1356_engine_wait_busy(bltreg); 800 801 // calculate the number of 16 bit words per one blt line 802 803 nWords = (Sx%16 + blt->dst_width + 15)/16; 804 805 wpt = blt->src + (Sy*blt->srcstride + Sx/16)/2; 806 807 for (i = 0; i < blt->dst_height; i++) { 808 wpt1 = wpt; 809 810 for (j = 0; j < nWords; j++) { 811 // loop until FIFO becomes empty... 812 e1356_wait_bitclr(&bltreg->ctrl0, 0x40, 10000); 813 writew(*wpt1++, info->reg.bitblt_data); 814 } 815 816 wpt += blt->srcstride/2; 817 } 818 819 e1356_engine_wait_complete(bltreg); 820} 821 822 823/* 824 * The BitBLT operation dispatcher 825 */ 826static int 827doBlt(const struct e1356fb_par* par, 828 struct fb_info_e1356* info, 829 blt_info_t* blt) 830{ 831 /* 832 * Make sure we're not reentering in the middle of an 833 * active BitBLT operation. ALWAYS call this dispatcher 834 * and not one of the above BLT routines directly, or you 835 * run the risk of overlapping BLT operations, which can 836 * cause complete system hangs. 837 */ 838 if (readb(&info->reg.bitblt->ctrl0) & 0x80) 839 return -ENXIO; 840 841 switch (blt->operation) { 842 case BLT_MOVE_POS_ROP: 843 case BLT_MOVE_NEG_ROP: 844 case BLT_MOVE_POS_TRANSP: 845 doBlt_Move(par, info, blt); 846 break; 847 case BLT_COLOR_EXP: 848 case BLT_COLOR_EXP_TRANSP: 849 doBlt_ColorExpand(par, info, blt); 850 break; 851 case BLT_SOLID_FILL: 852 doBlt_SolidFill(par, info, blt); 853 break; 854 case BLT_WRITE_ROP: 855 case BLT_WRITE_TRANSP: 856 doBlt_Write(par, info, blt); 857 break; 858 case BLT_READ: 859 case BLT_PAT_FILL_ROP: 860 case BLT_PAT_FILL_TRANSP: 861 case BLT_MOVE_COLOR_EXP: 862 case BLT_MOVE_COLOR_EXP_TRANSP: 863 DPRINTK("BitBLT operation 0x%02x not implemented yet\n", 864 blt->operation); 865 return -ENXIO; 866 default: 867 DPRINTK("Unknown BitBLT operation 0x%02x\n", blt->operation); 868 return -ENXIO; 869 } 870 871 return 0; 872} 873 874 875// Initializes blt->src and blt->srcstride 876static void fill_putcs_buffer(struct display *p, 877 blt_info_t* blt, 878 const unsigned short* str, 879 int count) 880{ 881 int row, i, j; 882 u8* b1, *b2; 883 u32 fw = fontwidth(p); 884 u32 fwb = (fw + 7) >> 3; 885 u32 fh = fontheight(p); 886 int bytesPerChar = fwb * fh; 887 888 if (count*bytesPerChar > PAGE_SIZE) { 889 // Truncate the string if it overflows putcs_buffer, which is 890 // one page in size. 891 count = PAGE_SIZE/bytesPerChar - 1; 892 } 893 894 blt->srcstride = (fwb*count + 1) & ~1; //round up to be even 895 896 b1 = (u8*)blt->src; 897 898 for (row = 0; row < fh; row++) { 899 b2 = b1; 900 for (i = 0; i < count; i++) { 901 for (j=0; j<fwb; j++) 902 *b2++ = p->fontdata[(str[i] & p->charmask) * 903 bytesPerChar + 904 row*fwb + j]; 905 } 906 b1 += blt->srcstride; 907 } 908} 909 910 911/* 912 * Set the color of a palette entry in 8bpp mode 913 */ 914static inline void 915do_setpalentry(reg_lut_t* lut, unsigned regno, 916 u8 r, u8 g, u8 b) 917{ 918 writeb(0x00, &lut->mode); 919 writeb((u8)regno, &lut->addr); 920 writeb(r&0xf0, &lut->data); 921 writeb(g&0xf0, &lut->data); 922 writeb(b&0xf0, &lut->data); 923} 924 925 926static void 927do_pan_var(struct fb_var_screeninfo* var, struct fb_info_e1356* info) 928{ 929 u32 pixel_start, start_addr; 930 u8 pixel_pan; 931 struct e1356fb_par* par = &info->current_par; 932 reg_misc_t* misc = info->reg.misc; 933 reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ? 934 info->reg.lcd_mode : info->reg.crttv_mode; 935 936 pixel_start = var->yoffset * par->width_virt + var->xoffset; 937 start_addr = (pixel_start * par->Bpp) / 2; 938 pixel_pan = (par->bpp == 8) ? (u8)(pixel_start & 1) : 0; 939 940 if (readb(&misc->disp_mode) != 0) { 941 reg_dispcfg_t* dispcfg = (IS_PANEL(info->fix.disp_type)) ? 942 info->reg.lcd_cfg : info->reg.crttv_cfg; 943 944 // wait for the end of the current VNDP 945 e1356_wait_bitclr(&dispcfg->vndp, 0x80, 5000); 946 // now wait for the start of a new VNDP 947 e1356_wait_bitset(&dispcfg->vndp, 0x80, 5000); 948 } 949 950 writeb((u8)(start_addr & 0xff), &dispmode->start_addr0); 951 writeb((u8)((start_addr>>8) & 0xff), &dispmode->start_addr1); 952 writeb((u8)((start_addr>>16) & 0xff), &dispmode->start_addr2); 953 writeb(pixel_pan, &dispmode->pixel_panning); 954} 955 956 957/* 958 * Invert the hardware cursor image (timerfunc) 959 */ 960static void 961do_flashcursor(unsigned long ptr) 962{ 963 u8 curs_ctrl; 964 struct fb_info_e1356* info = (struct fb_info_e1356 *)ptr; 965 reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ? 966 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs; 967 968 spin_lock(&info->cursor.lock); 969 // toggle cursor enable bit 970 curs_ctrl = readb(&inkcurs->ctrl); 971 writeb((curs_ctrl ^ 0x01) & 0x01, &inkcurs->ctrl); 972 info->cursor.timer.expires = jiffies+HZ/2; 973 add_timer(&info->cursor.timer); 974 spin_unlock(&info->cursor.lock); 975} 976 977#ifdef SHADOW_FRAME_BUFFER 978/* 979 * Write BLT the shadow frame buffer to the real fb (timerfunc) 980 */ 981static void 982do_write_shadow_fb(unsigned long ptr) 983{ 984 blt_info_t blt; 985 struct fb_info_e1356 *info = (struct fb_info_e1356*)ptr; 986 struct fb_info* fb = &info->fb_info; 987 struct e1356fb_par* par = &info->current_par; 988 u32 stride = par->width_virt * par->Bpp; 989 990 unsigned long j_start = jiffies; 991 992 blt.src_x = blt.src_y = 0; 993 blt.attribute = 0; 994 blt.dst_width = par->width; 995 blt.dst_height = par->height; 996 blt.dst_y = fb->var.yoffset; 997 blt.dst_x = fb->var.xoffset; 998 blt.operation = BLT_WRITE_ROP; 999 blt.rop = 0x0c; // ROP: destination = source 1000 blt.src = (u16*)(info->shadow.fb + blt.dst_x * par->Bpp + 1001 blt.dst_y * stride); 1002 1003 doBlt(par, info, &blt); 1004 1005 info->shadow.timer.expires = jiffies+HZ/2; 1006 add_timer(&info->shadow.timer); 1007 1008 //DPRINTK("delta jiffies = %ld\n", jiffies - j_start); 1009} 1010#endif 1011 1012 1013/* ------------------------------------------------------------------------- 1014 * Hardware independent part, interface to the world 1015 * ------------------------------------------------------------------------- */ 1016 1017static void 1018e1356_cfbX_clear_margins(struct vc_data* conp, struct display* p, 1019 int bottom_only) 1020{ 1021 blt_info_t blt; 1022 unsigned int cw=fontwidth(p); 1023 unsigned int ch=fontheight(p); 1024 unsigned int rw=p->var.xres % cw; 1025 unsigned int bh=p->var.yres % ch; 1026 unsigned int rs=p->var.xres - rw; 1027 unsigned int bs=p->var.yres - bh; 1028 1029 //DPRINTK("\n"); 1030 1031 if (!bottom_only && rw) { 1032 blt.dst_x = p->var.xoffset+rs; 1033 blt.dst_y = p->var.yoffset; 1034 blt.dst_height = p->var.yres; 1035 blt.dst_width = rw; 1036 blt.attribute = 0; 1037 blt.fg_color = 0; 1038 blt.operation = BLT_SOLID_FILL; 1039 doBlt (&fb_info.current_par, &fb_info, &blt); 1040 } 1041 1042 if (bh) { 1043 blt.dst_x = p->var.xoffset; 1044 blt.dst_y = p->var.yoffset+bs; 1045 blt.dst_height = bh; 1046 blt.dst_width = rs; 1047 blt.attribute = 0; 1048 blt.fg_color = 0; 1049 blt.operation = BLT_SOLID_FILL; 1050 doBlt (&fb_info.current_par, &fb_info, &blt); 1051 } 1052} 1053 1054static void 1055e1356_cfbX_bmove(struct display* p, 1056 int sy, 1057 int sx, 1058 int dy, 1059 int dx, 1060 int height, 1061 int width) 1062{ 1063 blt_info_t blt; 1064 1065 //DPRINTK("(%d,%d) to (%d,%d) size (%d,%d)\n", sx,sy,dx,dy,width,height); 1066 1067 blt.src_x = fontwidth_x8(p)*sx; 1068 blt.src_y = fontheight(p)*sy; 1069 blt.dst_x = fontwidth_x8(p)*dx; 1070 blt.dst_y = fontheight(p)*dy; 1071 blt.src_height = blt.dst_height = fontheight(p)*height; 1072 blt.src_width = blt.dst_width = fontwidth_x8(p)*width; 1073 blt.attribute = 0; 1074 blt.rop = 0x0c; 1075 /* 1076 * The move BLT routine will actually decide between a pos/neg 1077 * move BLT. This is just so that the BLT dispatcher knows to 1078 * call the move BLT routine. 1079 */ 1080 blt.operation = BLT_MOVE_POS_ROP; 1081 1082 doBlt (&fb_info.current_par, &fb_info, &blt); 1083} 1084 1085static void 1086e1356_cfb8_putc(struct vc_data* conp, 1087 struct display* p, 1088 int c, int yy,int xx) 1089{ 1090 blt_info_t blt; 1091 u32 fgx,bgx; 1092 u32 fw = fontwidth_x8(p); 1093 u32 fh = fontheight(p); 1094 u16 cs = (u16)c; 1095 1096 fgx = attr_fgcol(p, c); 1097 bgx = attr_bgcol(p, c); 1098 1099 blt.src_x = blt.src_y = 0; 1100 blt.attribute = 0; 1101 blt.dst_width = fw; 1102 blt.dst_height = fh; 1103 blt.dst_y = yy * fh; 1104 blt.dst_x = xx * fw; 1105 blt.bg_color = bgx; 1106 blt.fg_color = fgx; 1107 blt.operation = BLT_COLOR_EXP; 1108 blt.src = fb_info.putcs_buffer; 1109 fill_putcs_buffer(p, &blt, &cs, 1); 1110 1111 doBlt(&fb_info.current_par, &fb_info, &blt); 1112 1113} 1114 1115static void 1116e1356_cfb16_putc(struct vc_data* conp, 1117 struct display* p, 1118 int c, int yy,int xx) 1119{ 1120 blt_info_t blt; 1121 u32 fgx,bgx; 1122 u32 fw = fontwidth_x8(p); 1123 u32 fh = fontheight(p); 1124 u16 cs = (u16)c; 1125 1126 fgx = ((u16*)p->dispsw_data)[attr_fgcol(p,c)]; 1127 bgx = ((u16*)p->dispsw_data)[attr_bgcol(p,c)]; 1128 1129 blt.src_x = blt.src_y = 0; 1130 blt.attribute = 0; 1131 blt.dst_width = fw; 1132 blt.dst_height = fh; 1133 blt.dst_y = yy * fh; 1134 blt.dst_x = xx * fw; 1135 blt.bg_color = bgx; 1136 blt.fg_color = fgx; 1137 blt.operation = BLT_COLOR_EXP; 1138 blt.src = fb_info.putcs_buffer; 1139 fill_putcs_buffer(p, &blt, &cs, 1); 1140 1141 doBlt(&fb_info.current_par, &fb_info, &blt); 1142} 1143 1144 1145static void 1146e1356_cfb8_putcs(struct vc_data* conp, 1147 struct display* p, 1148 const unsigned short *s,int count,int yy,int xx) 1149{ 1150 blt_info_t blt; 1151 u32 fgx,bgx; 1152 u32 fw = fontwidth_x8(p); 1153 u32 fh = fontheight(p); 1154 1155 //DPRINTK("\n"); 1156 1157 fgx=attr_fgcol(p, *s); 1158 bgx=attr_bgcol(p, *s); 1159 1160 blt.src_x = blt.src_y = 0; 1161 blt.attribute = 0; 1162 blt.dst_width = count * fw; 1163 blt.dst_height = fh; 1164 blt.dst_y = yy * fh; 1165 blt.dst_x = xx * fw; 1166 blt.bg_color = bgx; 1167 blt.fg_color = fgx; 1168 blt.operation = BLT_COLOR_EXP; 1169 blt.src = fb_info.putcs_buffer; 1170 fill_putcs_buffer(p, &blt, s, count); 1171 1172 doBlt(&fb_info.current_par, &fb_info, &blt); 1173} 1174 1175static void 1176e1356_cfb16_putcs(struct vc_data* conp, 1177 struct display* p, 1178 const unsigned short *s,int count,int yy,int xx) 1179{ 1180 blt_info_t blt; 1181 u32 fgx,bgx; 1182 u32 fw = fontwidth_x8(p); 1183 u32 fh = fontheight(p); 1184 1185 //DPRINTK("\n"); 1186 1187 fgx=((u16*)p->dispsw_data)[attr_fgcol(p,*s)]; 1188 bgx=((u16*)p->dispsw_data)[attr_bgcol(p,*s)]; 1189 1190 blt.src_x = blt.src_y = 0; 1191 blt.attribute = 0; 1192 blt.dst_width = count * fw; 1193 blt.dst_height = fh; 1194 blt.dst_y = yy * fh; 1195 blt.dst_x = xx * fw; 1196 blt.bg_color = bgx; 1197 blt.fg_color = fgx; 1198 blt.operation = BLT_COLOR_EXP; 1199 blt.src = fb_info.putcs_buffer; 1200 fill_putcs_buffer(p, &blt, s, count); 1201 1202 doBlt(&fb_info.current_par, &fb_info, &blt); 1203} 1204 1205 1206static void 1207e1356_cfb8_clear(struct vc_data* conp, 1208 struct display* p, 1209 int sy, 1210 int sx, 1211 int height, 1212 int width) 1213{ 1214 blt_info_t blt; 1215 u32 bg = attr_bgcol_ec(p,conp); 1216 1217 //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height); 1218 1219 blt.dst_x = fontwidth_x8(p)*sx; 1220 blt.dst_y = fontheight(p)*sy; 1221 blt.dst_height = fontheight(p)*height; 1222 blt.dst_width = fontwidth_x8(p)*width; 1223 blt.attribute = 0; 1224 blt.fg_color = bg; 1225 blt.operation = BLT_SOLID_FILL; 1226 1227 doBlt (&fb_info.current_par, &fb_info, &blt); 1228} 1229 1230static void 1231e1356_cfb16_clear(struct vc_data* conp, 1232 struct display* p, 1233 int sy, 1234 int sx, 1235 int height, 1236 int width) 1237{ 1238 blt_info_t blt; 1239 u32 bg = ((u16*)p->dispsw_data)[attr_bgcol_ec(p,conp)]; 1240 1241 //DPRINTK("(%d,%d) size (%d,%d)\n", sx,sy,width,height); 1242 1243 blt.dst_x = fontwidth_x8(p)*sx; 1244 blt.dst_y = fontheight(p)*sy; 1245 blt.dst_height = fontheight(p)*height; 1246 blt.dst_width = fontwidth_x8(p)*width; 1247 blt.attribute = 0; 1248 blt.fg_color = bg; 1249 blt.operation = BLT_SOLID_FILL; 1250 1251 doBlt (&fb_info.current_par, &fb_info, &blt); 1252} 1253 1254 1255static void 1256e1356_cfbX_revc(struct display *p, int xx, int yy) 1257{ 1258 // not used if h/w cursor 1259 //DPRINTK("\n"); 1260} 1261 1262static void 1263e1356_cfbX_cursor(struct display *p, int mode, int x, int y) 1264{ 1265 unsigned long flags; 1266 struct fb_info_e1356 *info=(struct fb_info_e1356 *)p->fb_info; 1267 reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ? 1268 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs; 1269 1270 //DPRINTK("\n"); 1271 1272 if (mode == CM_ERASE) { 1273 if (info->cursor.state != CM_ERASE) { 1274 spin_lock_irqsave(&info->cursor.lock,flags); 1275 info->cursor.state = CM_ERASE; 1276 del_timer(&(info->cursor.timer)); 1277 writeb(0x00, &inkcurs->ctrl); 1278 spin_unlock_irqrestore(&info->cursor.lock,flags); 1279 } 1280 return; 1281 } 1282 1283 if ((p->conp->vc_cursor_type & CUR_HWMASK) != info->cursor.type) 1284 e1356fb_createcursor(p); 1285 1286 x *= fontwidth_x8(p); 1287 y *= fontheight(p); 1288 x -= p->var.xoffset; 1289 y -= p->var.yoffset; 1290 1291 spin_lock_irqsave(&info->cursor.lock,flags); 1292 if ((x != info->cursor.x) || (y != info->cursor.y) || 1293 (info->cursor.redraw)) { 1294 info->cursor.x = x; 1295 info->cursor.y = y; 1296 info->cursor.redraw = 0; 1297 writeb(0x01, &inkcurs->ctrl); 1298 writew(x, &inkcurs->x_pos0); 1299 writew(y, &inkcurs->y_pos0); 1300 /* fix cursor color - XFree86 forgets to restore it properly */ 1301 writeb(0x00, &inkcurs->blue0); 1302 writeb(0x00, &inkcurs->green0); 1303 writeb(0x00, &inkcurs->red0); 1304 writeb(0x1f, &inkcurs->blue1); 1305 writeb(0x3f, &inkcurs->green1); 1306 writeb(0x1f, &inkcurs->red1); 1307 } 1308 1309 info->cursor.state = CM_DRAW; 1310 mod_timer(&info->cursor.timer, jiffies+HZ/2); 1311 spin_unlock_irqrestore(&info->cursor.lock,flags); 1312} 1313 1314#ifdef FBCON_HAS_CFB8 1315static struct display_switch fbcon_e1356_8 = { 1316 setup: fbcon_cfb8_setup, 1317 bmove: e1356_cfbX_bmove, 1318 clear: e1356_cfb8_clear, 1319 putc: e1356_cfb8_putc, 1320 putcs: e1356_cfb8_putcs, 1321 revc: e1356_cfbX_revc, 1322 cursor: e1356_cfbX_cursor, 1323 clear_margins: e1356_cfbX_clear_margins, 1324 fontwidthmask: FONTWIDTHRANGE(6,16) 1325}; 1326#endif 1327 1328#ifdef FBCON_HAS_CFB16 1329static struct display_switch fbcon_e1356_16 = { 1330 setup: fbcon_cfb16_setup, 1331 bmove: e1356_cfbX_bmove, 1332 clear: e1356_cfb16_clear, 1333 putc: e1356_cfb16_putc, 1334 putcs: e1356_cfb16_putcs, 1335 revc: e1356_cfbX_revc, 1336 cursor: e1356_cfbX_cursor, 1337 clear_margins: e1356_cfbX_clear_margins, 1338 fontwidthmask: FONTWIDTHRANGE(6,16) 1339}; 1340#endif 1341 1342/* ------------------------------------------------------------------------- */ 1343 1344static void 1345e1356fb_set_par(const struct e1356fb_par* par, 1346 struct fb_info_e1356* info) 1347{ 1348 reg_dispcfg_t* dispcfg=NULL; 1349 reg_dispmode_t* dispmode=NULL; 1350 u8* pclk_cfg=NULL; 1351 u8 width, hndp=0, hsync_start=0, hsync_width=0; 1352 u8 vndp, vsync_start, vsync_width=0, display_mode; 1353 u8 main_display_mode=0; 1354 u16 height, addr_offset; 1355 int disp_type = info->fix.disp_type; 1356 1357 DPRINTK("%dx%d-%dbpp @ %d Hz, %d kHz hsync\n", 1358 par->width, par->height, par->bpp, 1359 par->vsync_freq, (((2*par->hsync_freq)/1000)+1)/2); 1360#ifdef E1356FB_VERBOSE_DEBUG 1361 dump_par(par); 1362#endif 1363 1364 info->current_par = *par; 1365 1366 width = (par->width >> 3) - 1; 1367 display_mode = (par->bpp == 8) ? 0x03 : 0x05; 1368 addr_offset = (par->width_virt * par->Bpp) / 2; 1369 vsync_start = (disp_type == DISP_TYPE_LCD) ? 0 : par->vsync_start - 1; 1370 height = par->height - 1; 1371 vndp = par->vert_ndp - 1; 1372 1373 switch (disp_type) { 1374 case DISP_TYPE_LCD: 1375 dispcfg = info->reg.lcd_cfg; 1376 dispmode = info->reg.lcd_mode; 1377 pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg; 1378 hndp = (par->horiz_ndp >> 3) - 1; 1379 hsync_start = 0; 1380 hsync_width = par->hsync_pol ? 0x00 : 0x80; 1381 vsync_width = par->vsync_pol ? 0x00 : 0x80; 1382 main_display_mode = 0x01; 1383 break; 1384 case DISP_TYPE_TFT: 1385 dispcfg = info->reg.lcd_cfg; 1386 dispmode = info->reg.lcd_mode; 1387 pclk_cfg = &info->reg.clk_cfg->lcd_pclk_cfg; 1388 hndp = (par->horiz_ndp >> 3) - 1; 1389 hsync_start = (par->bpp == 8) ? 1390 (par->hsync_start - 4) >> 3 : 1391 (par->hsync_start - 6) >> 3; 1392 hsync_width = 1393 (par->hsync_pol ? 0x80 : 0x00) | 1394 ((par->hsync_width >> 3) - 1); 1395 vsync_width = 1396 (par->vsync_pol ? 0x80 : 0x00) | 1397 (par->vsync_width - 1); 1398 main_display_mode = 0x01; 1399 break; 1400 case DISP_TYPE_CRT: 1401 dispcfg = info->reg.crttv_cfg; 1402 dispmode = info->reg.crttv_mode; 1403 pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg; 1404 hndp = (par->horiz_ndp >> 3) - 1; 1405 hsync_start = (par->bpp == 8) ? 1406 (par->hsync_start - 3) >> 3 : 1407 (par->hsync_start - 5) >> 3; 1408 hsync_width = 1409 (par->hsync_pol ? 0x80 : 0x00) | 1410 ((par->hsync_width >> 3) - 1); 1411 vsync_width = 1412 (par->vsync_pol ? 0x80 : 0x00) | 1413 (par->vsync_width - 1); 1414 main_display_mode = 0x02; 1415 break; 1416 case DISP_TYPE_NTSC: 1417 case DISP_TYPE_PAL: 1418 dispcfg = info->reg.crttv_cfg; 1419 dispmode = info->reg.crttv_mode; 1420 pclk_cfg = &info->reg.clk_cfg->crttv_pclk_cfg; 1421 hndp = (disp_type == DISP_TYPE_PAL) ? 1422 (par->horiz_ndp - 7) >> 3 : 1423 (par->horiz_ndp - 6) >> 3; 1424 hsync_start = (par->bpp == 8) ? 1425 (par->hsync_start + 7) >> 3 : 1426 (par->hsync_start + 5) >> 3; 1427 hsync_width = 0; 1428 vsync_width = 0; 1429 main_display_mode = (info->fix.tv_filt & TV_FILT_FLICKER) ? 1430 0x06 : 0x04; 1431 break; 1432 } 1433 1434 // Blast the regs! 1435 // note: reset panning/scrolling (set start-addr and 1436 // pixel pan regs to 0). Panning is handled by pan_display. 1437 1438 e1356_engine_wait_complete(info->reg.bitblt); 1439 1440 // disable display while initializing 1441 writeb(0, &info->reg.misc->disp_mode); 1442 1443 writeb(par->ipclk.pixclk_bits, pclk_cfg); 1444 1445 writeb(width, &dispcfg->hdw); 1446 writeb(hndp, &dispcfg->hndp); 1447 writeb(hsync_start, &dispcfg->hsync_start); 1448 writeb(hsync_width, &dispcfg->hsync_pulse); 1449 writew(height, &dispcfg->vdh0); 1450 writeb(vndp, &dispcfg->vndp); 1451 writeb(vsync_start, &dispcfg->vsync_start); 1452 writeb(vsync_width, &dispcfg->vsync_pulse); 1453 1454 writeb(display_mode, &dispmode->disp_mode); 1455 if (info->fix.mmunalign && info->mmaped) 1456 writeb(1, &dispmode->start_addr0); 1457 else 1458 writeb(0, &dispmode->start_addr0); 1459 writeb(0, &dispmode->start_addr1); 1460 writeb(0, &dispmode->start_addr2); 1461 writew(addr_offset, &dispmode->mem_addr_offset0); 1462 writeb(0, &dispmode->pixel_panning); 1463 1464 // reset BitBlt engine 1465 e1356fb_engine_init(par, info); 1466 1467#ifdef E1356FB_VERBOSE_DEBUG 1468 dump_display_regs(dispcfg, dispmode); 1469#endif 1470 1471 /* clear out framebuffer memory */ 1472 fbfill(fb_info.membase_virt, 0, fb_info.fb_size); 1473 // finally, enable display! 1474 writeb(main_display_mode, &info->reg.misc->disp_mode); 1475} 1476 1477 1478static int 1479e1356fb_verify_timing(struct e1356fb_par* par, 1480 const struct fb_info_e1356* info) 1481{ 1482 int disp_type = info->fix.disp_type; 1483 1484 // timing boundary checks 1485 if (par->horiz_ndp > max_hndp[disp_type]) { 1486 DPRINTK("horiz_ndp too big: %d\n", par->horiz_ndp); 1487 return -EINVAL; 1488 } 1489 if (par->vert_ndp > max_vndp[disp_type]) { 1490 DPRINTK("vert_ndp too big: %d\n", par->vert_ndp); 1491 return -EINVAL; 1492 } 1493 1494 if (disp_type != DISP_TYPE_LCD) { 1495 if (par->hsync_start > 1496 max_hsync_start[(par->bpp==16)][disp_type]) { 1497 DPRINTK("hsync_start too big: %d\n", 1498 par->hsync_start); 1499 return -EINVAL; 1500 } 1501 if (par->vsync_start > max_vsync_start[disp_type]) { 1502 DPRINTK("vsync_start too big: %d\n", 1503 par->vsync_start); 1504 return -EINVAL; 1505 } 1506 if (!IS_TV(disp_type)) { 1507 if (par->hsync_width > max_hsync_width[disp_type]) { 1508 DPRINTK("hsync_width too big: %d\n", 1509 par->hsync_width); 1510 return -EINVAL; 1511 } 1512 if (par->vsync_width > max_vsync_width[disp_type]) { 1513 DPRINTK("vsync_width too big: %d\n", 1514 par->vsync_width); 1515 return -EINVAL; 1516 } 1517 } 1518 } 1519 1520 if (IS_TV(disp_type)) { 1521 int tv_pixclk = (disp_type == DISP_TYPE_NTSC) ? 1522 NTSC_PIXCLOCK : PAL_PIXCLOCK; 1523 if (info->fix.tv_filt & TV_FILT_FLICKER) 1524 tv_pixclk *= 2; 1525 1526 if (par->ipclk.pixclk_d != tv_pixclk) { 1527 DPRINTK("invalid TV pixel clock %u kHz\n", 1528 par->ipclk.pixclk_d); 1529 return -EINVAL; 1530 } 1531 } 1532 1533 if (e1356_calc_pixclock(info, &par->ipclk) < 0) { 1534 DPRINTK("can't set pixel clock %u kHz\n", 1535 par->ipclk.pixclk_d); 1536 return -EINVAL; 1537 } 1538 1539#ifdef E1356FB_VERBOSE_DEBUG 1540 DPRINTK("desired pixclock = %d kHz, actual = %d kHz, error = %d%%\n", 1541 par->ipclk.pixclk_d, par->ipclk.pixclk, par->ipclk.error); 1542#endif 1543 1544 if (disp_type != DISP_TYPE_LCD) { 1545 if (par->horiz_ndp < par->hsync_start + par->hsync_width) { 1546 DPRINTK("invalid horiz. timing\n"); 1547 return -EINVAL; 1548 } 1549 if (par->vert_ndp < par->vsync_start + par->vsync_width) { 1550 DPRINTK("invalid vert. timing\n"); 1551 return -EINVAL; 1552 } 1553 1554 // SED1356 Hardware Functional Spec, section 13.5 1555 if (disp_type == DISP_TYPE_NTSC && 1556 ((par->width + par->horiz_ndp != 910) || 1557 (par->height + 2*par->vert_ndp+1 != 525))) { 1558 DPRINTK("invalid NTSC timing\n"); 1559 return -EINVAL; 1560 } else if (disp_type == DISP_TYPE_PAL && 1561 ((par->width + par->horiz_ndp != 1135) || 1562 (par->height + 2*par->vert_ndp+1 != 625))) { 1563 DPRINTK("invalid PAL timing\n"); 1564 return -EINVAL; 1565 } 1566 } 1567 1568 par->hsync_freq = (1000 * par->ipclk.pixclk) / 1569 (par->width + par->horiz_ndp); 1570 par->vsync_freq = par->hsync_freq / (par->height + par->vert_ndp); 1571 1572 if (par->hsync_freq < 30000 || par->hsync_freq > 90000) { 1573 DPRINTK("hsync freq too %s: %u Hz\n", 1574 par->hsync_freq < 30000 ? "low" : "high", 1575 par->hsync_freq); 1576 return -EINVAL; 1577 } 1578 if (par->vsync_freq < 50 || par->vsync_freq > 110) { 1579 DPRINTK("vsync freq too %s: %u Hz\n", 1580 par->vsync_freq < 50 ? "low" : "high", 1581 par->vsync_freq); 1582 return -EINVAL; 1583 } 1584 1585 return 0; 1586} 1587 1588static int 1589e1356fb_verify_par(struct e1356fb_par* par, 1590 const struct fb_info_e1356* info) 1591{ 1592 int disp_type = info->fix.disp_type; 1593 1594 if (par->bpp != 8 && par->bpp != 16) { 1595 DPRINTK("depth not supported: %u bpp\n", par->bpp); 1596 return -EINVAL; 1597 } 1598 1599 if (par->width > par->width_virt) { 1600 DPRINTK("virtual x resolution < physical x resolution not possible\n"); 1601 return -EINVAL; 1602 } 1603 1604 if (par->height > par->height_virt) { 1605 DPRINTK("virtual y resolution < physical y resolution not possible\n"); 1606 return -EINVAL; 1607 } 1608 1609 if (par->width < 320 || par->width > 1024) { 1610 DPRINTK("width not supported: %u\n", par->width); 1611 return -EINVAL; 1612 } 1613 1614 if ((disp_type == DISP_TYPE_LCD && (par->width % 16)) || 1615 (disp_type == DISP_TYPE_TFT && (par->width % 8))) { 1616 DPRINTK("invalid width for panel type: %u\n", par->width); 1617 return -EINVAL; 1618 } 1619 1620 if (par->height < 200 || par->height > 1024) { 1621 DPRINTK("height not supported: %u\n", par->height); 1622 return -EINVAL; 1623 } 1624 1625 if (par->width_virt * par->height_virt * par->Bpp > 1626 info->fb_size) { 1627 DPRINTK("not enough memory for virtual screen (%ux%ux%u)\n", 1628 par->width_virt, par->height_virt, par->bpp); 1629 return -EINVAL; 1630 } 1631 1632 return e1356fb_verify_timing(par, info); 1633} 1634 1635 1636static int 1637e1356fb_var_to_par(const struct fb_var_screeninfo* var, 1638 struct e1356fb_par* par, 1639 const struct fb_info_e1356* info) 1640{ 1641 if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { 1642 DPRINTK("interlace not supported\n"); 1643 return -EINVAL; 1644 } 1645 1646 memset(par, 0, sizeof(struct e1356fb_par)); 1647 1648 par->width = (var->xres + 15) & ~15; /* could sometimes be 8 */ 1649 par->width_virt = var->xres_virtual; 1650 par->height = var->yres; 1651 par->height_virt = var->yres_virtual; 1652 par->bpp = var->bits_per_pixel; 1653 par->Bpp = (par->bpp + 7) >> 3; 1654 1655 par->ipclk.pixclk_d = PICOS2KHZ(var->pixclock); 1656 1657 par->hsync_start = var->right_margin; 1658 par->hsync_width = var->hsync_len; 1659 1660 par->vsync_start = var->lower_margin; 1661 par->vsync_width = var->vsync_len; 1662 1663 par->horiz_ndp = var->left_margin + var->right_margin + var->hsync_len; 1664 par->vert_ndp = var->upper_margin + var->lower_margin + var->vsync_len; 1665 1666 par->hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0; 1667 par->vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0; 1668 1669 par->cmap_len = (par->bpp == 8) ? 256 : 16; 1670 1671 return e1356fb_verify_par(par, info); 1672} 1673 1674static int 1675e1356fb_par_to_var(struct fb_var_screeninfo* var, 1676 struct e1356fb_par* par, 1677 const struct fb_info_e1356* info) 1678{ 1679 struct fb_var_screeninfo v; 1680 int ret; 1681 1682 // First, make sure par is valid. 1683 if ((ret = e1356fb_verify_par(par, info))) 1684 return ret; 1685 1686 memset(&v, 0, sizeof(struct fb_var_screeninfo)); 1687 v.xres_virtual = par->width_virt; 1688 v.yres_virtual = par->height_virt; 1689 v.xres = par->width; 1690 v.yres = par->height; 1691 v.right_margin = par->hsync_start; 1692 v.hsync_len = par->hsync_width; 1693 v.left_margin = par->horiz_ndp - par->hsync_start - par->hsync_width; 1694 v.lower_margin = par->vsync_start; 1695 v.vsync_len = par->vsync_width; 1696 v.upper_margin = par->vert_ndp - par->vsync_start - par->vsync_width; 1697 v.bits_per_pixel = par->bpp; 1698 1699 switch(par->bpp) { 1700 case 8: 1701 v.red.offset = v.green.offset = v.blue.offset = 0; 1702 v.red.length = v.green.length = v.blue.length = 4; 1703 break; 1704 case 16: 1705 v.red.offset = 11; 1706 v.red.length = 5; 1707 v.green.offset = 5; 1708 v.green.length = 6; 1709 v.blue.offset = 0; 1710 v.blue.length = 5; 1711 break; 1712 } 1713 1714 v.height = v.width = -1; 1715 v.pixclock = KHZ2PICOS(par->ipclk.pixclk); 1716 1717 if (par->hsync_pol) 1718 v.sync |= FB_SYNC_HOR_HIGH_ACT; 1719 if (par->vsync_pol) 1720 v.sync |= FB_SYNC_VERT_HIGH_ACT; 1721 1722 *var = v; 1723 return 0; 1724} 1725 1726static int 1727e1356fb_encode_fix(struct fb_fix_screeninfo* fix, 1728 const struct e1356fb_par* par, 1729 const struct fb_info_e1356* info) 1730{ 1731 memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 1732 1733 strcpy(fix->id, "Epson SED1356"); 1734 fix->smem_start = info->fix.membase_phys; 1735 fix->smem_len = info->fb_size; 1736 fix->mmio_start = info->fix.regbase_phys; 1737 fix->mmio_len = info->regbase_size; 1738 fix->accel = FB_ACCEL_EPSON_SED1356; 1739 fix->type = FB_TYPE_PACKED_PIXELS; 1740 fix->type_aux = 0; 1741 fix->line_length = par->width_virt * par->Bpp; 1742 fix->visual = 1743 (par->bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; 1744 1745 fix->xpanstep = info->fix.nopan ? 0 : 1; 1746 fix->ypanstep = info->fix.nopan ? 0 : 1; 1747 fix->ywrapstep = 0; 1748 1749 return 0; 1750} 1751 1752static int e1356fb_open(struct fb_info *fb, int user) 1753{ 1754 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 1755 if (user) { 1756 info->open++; 1757 } 1758 MOD_INC_USE_COUNT; 1759 return 0; 1760} 1761 1762static int e1356fb_release(struct fb_info *fb, int user) 1763{ 1764 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 1765 if (user && info->open) { 1766 info->open--; 1767 if (info->open == 0) 1768 info->mmaped = 0; 1769 } 1770 MOD_DEC_USE_COUNT; 1771 return 0; 1772} 1773 1774static int 1775e1356fb_get_fix(struct fb_fix_screeninfo *fix, 1776 int con, 1777 struct fb_info *fb) 1778{ 1779 const struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 1780 struct e1356fb_par par; 1781 1782 //DPRINTK("\n"); 1783 1784 if (con == -1) 1785 par = info->current_par; 1786 else 1787 e1356fb_var_to_par(&fb_display[con].var, &par, info); 1788 e1356fb_encode_fix(fix, &par, info); 1789 return 0; 1790} 1791 1792static int 1793e1356fb_get_var(struct fb_var_screeninfo *var, 1794 int con, 1795 struct fb_info *fb) 1796{ 1797 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 1798 1799 //DPRINTK("\n"); 1800 1801 if (con == -1) 1802 e1356fb_par_to_var(var, &info->current_par, info); 1803 else 1804 *var = fb_display[con].var; 1805 return 0; 1806} 1807 1808static void 1809e1356fb_set_dispsw(struct display *disp, 1810 struct fb_info_e1356 *info, 1811 int bpp, 1812 int accel) 1813{ 1814 struct e1356fb_fix* fix = &info->fix; 1815 //DPRINTK("\n"); 1816 1817 if (disp->dispsw && disp->conp) 1818 fb_con.con_cursor(disp->conp, CM_ERASE); 1819 switch (bpp) { 1820#ifdef FBCON_HAS_CFB8 1821 case 8: 1822 disp->dispsw = fix->noaccel ? &fbcon_cfb8 : &fbcon_e1356_8; 1823 if (fix->nohwcursor) 1824 fbcon_e1356_8.cursor = NULL; 1825 break; 1826#endif 1827#ifdef FBCON_HAS_CFB16 1828 case 16: 1829 disp->dispsw = fix->noaccel ? &fbcon_cfb16 : &fbcon_e1356_16; 1830 disp->dispsw_data = info->fbcon_cmap16; 1831 if (fix->nohwcursor) 1832 fbcon_e1356_16.cursor = NULL; 1833 break; 1834#endif 1835 default: 1836 disp->dispsw = &fbcon_dummy; 1837 } 1838 1839} 1840 1841static int 1842e1356fb_set_var(struct fb_var_screeninfo *var, 1843 int con, 1844 struct fb_info *fb) 1845{ 1846 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 1847 struct e1356fb_par par; 1848 struct display *display; 1849 int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err; 1850 int activate = var->activate; 1851 int j,k; 1852 1853 DPRINTK("\n"); 1854 1855 if (con >= 0) 1856 display = &fb_display[con]; 1857 else 1858 display = fb->disp; /* used during initialization */ 1859 1860 if ((err = e1356fb_var_to_par(var, &par, info))) { 1861 struct fb_videomode *dm; 1862 /* 1863 * this mode didn't pass the tests. Try the 1864 * corresponding mode from our own modedb. 1865 */ 1866 DPRINTK("req mode failed, trying SED1356 %dx%d mode\n", 1867 var->xres, var->yres); 1868 if (e1356fb_get_mode(info, var->xres, 1869 var->yres, NULL, &dm) < 0) { 1870 DPRINTK("no SED1356 %dx%d mode found, failed\n", 1871 var->xres, var->yres); 1872 return err; 1873 } 1874 fb_videomode_to_var(dm, var); 1875 if ((err = e1356fb_var_to_par(var, &par, info))) { 1876 DPRINTK("SED1356 %dx%d mode failed\n", 1877 var->xres, var->yres); 1878 return err; 1879 } 1880 } 1881 1882 if (info->fix.tv_filt & TV_FILT_FLICKER) 1883 printk("e1356fb: TV flicker filter enabled\n"); 1884 1885 e1356fb_par_to_var(var, &par, info); 1886 1887 if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { 1888 oldxres = display->var.xres; 1889 oldyres = display->var.yres; 1890 oldvxres = display->var.xres_virtual; 1891 oldvyres = display->var.yres_virtual; 1892 oldbpp = display->var.bits_per_pixel; 1893 oldaccel = display->var.accel_flags; 1894 display->var = *var; 1895 if (con < 0 || 1896 oldxres != var->xres || 1897 oldyres != var->yres || 1898 oldvxres != var->xres_virtual || 1899 oldvyres != var->yres_virtual || 1900 oldbpp != var->bits_per_pixel || 1901 oldaccel != var->accel_flags) { 1902 struct fb_fix_screeninfo fix; 1903 1904 e1356fb_encode_fix(&fix, &par, info); 1905 display->screen_base = info->membase_virt; 1906 display->visual = fix.visual; 1907 display->type = fix.type; 1908 display->type_aux = fix.type_aux; 1909 display->ypanstep = fix.ypanstep; 1910 display->ywrapstep = fix.ywrapstep; 1911 display->line_length = fix.line_length; 1912 display->next_line = fix.line_length; 1913 display->can_soft_blank = 1; 1914 display->inverse = 0; 1915 accel = var->accel_flags & FB_ACCELF_TEXT; 1916 e1356fb_set_dispsw(display, info, par.bpp, accel); 1917 1918 if (info->fix.nopan) 1919 display->scrollmode = SCROLL_YREDRAW; 1920 1921 if (info->fb_info.changevar) 1922 (*info->fb_info.changevar)(con); 1923 } 1924 if (var->bits_per_pixel==8) 1925 for(j = 0; j < 16; j++) { 1926 k = color_table[j]; 1927 fb_info.palette[j].red = default_red[k]; 1928 fb_info.palette[j].green = default_grn[k]; 1929 fb_info.palette[j].blue = default_blu[k]; 1930 } 1931 1932 del_timer(&(info->cursor.timer)); 1933 fb_info.cursor.state=CM_ERASE; 1934 1935 if (!info->fb_info.display_fg || 1936 info->fb_info.display_fg->vc_num == con || con < 0) 1937 e1356fb_set_par(&par, info); 1938 1939 if (!info->fix.nohwcursor) 1940 if (display && display->conp) 1941 e1356fb_createcursor( display ); 1942 info->cursor.redraw = 1; 1943 1944 if (oldbpp != var->bits_per_pixel || con < 0) { 1945 if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) 1946 return err; 1947 e1356fb_install_cmap(display, &(info->fb_info)); 1948 } 1949 } 1950 1951 return 0; 1952} 1953 1954static int 1955e1356fb_pan_display(struct fb_var_screeninfo* var, 1956 int con, 1957 struct fb_info* fb) 1958{ 1959 struct fb_info_e1356* info = (struct fb_info_e1356*)fb; 1960 struct e1356fb_par* par = &info->current_par; 1961 1962 //DPRINTK("\n"); 1963 1964 if (info->fix.nopan) 1965 return -EINVAL; 1966 1967 if ((int)var->xoffset < 0 || 1968 var->xoffset + par->width > par->width_virt || 1969 (int)var->yoffset < 0 || 1970 var->yoffset + par->height > par->height_virt) 1971 return -EINVAL; 1972 1973 if (con == currcon) 1974 do_pan_var(var, info); 1975 1976 fb_display[con].var.xoffset = var->xoffset; 1977 fb_display[con].var.yoffset = var->yoffset; 1978 1979 return 0; 1980} 1981 1982static int 1983e1356fb_get_cmap(struct fb_cmap *cmap, 1984 int kspc, 1985 int con, 1986 struct fb_info *fb) 1987{ 1988 struct fb_info_e1356* info = (struct fb_info_e1356*)fb; 1989 struct display *d = (con<0) ? fb->disp : fb_display + con; 1990 1991 //DPRINTK("\n"); 1992 1993 if (con == currcon) { 1994 /* current console? */ 1995 return fb_get_cmap(cmap, kspc, e1356fb_getcolreg, fb); 1996 } else if (d->cmap.len) { 1997 /* non default colormap? */ 1998 fb_copy_cmap(&d->cmap, cmap, kspc ? 0 : 2); 1999 } else { 2000 fb_copy_cmap(fb_default_cmap(info->current_par.cmap_len), 2001 cmap, kspc ? 0 : 2); 2002 } 2003 return 0; 2004} 2005 2006static int 2007e1356fb_set_cmap(struct fb_cmap *cmap, 2008 int kspc, 2009 int con, 2010 struct fb_info *fb) 2011{ 2012 struct display *d = (con<0) ? fb->disp : fb_display + con; 2013 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 2014 int cmap_len = (info->current_par.bpp == 8) ? 256 : 16; 2015 2016 //DPRINTK("\n"); 2017 2018 if (d->cmap.len!=cmap_len) { 2019 int err; 2020 if ((err = fb_alloc_cmap(&d->cmap, cmap_len, 0))) 2021 return err; 2022 } 2023 2024 if (con == currcon) { 2025 /* current console? */ 2026 return fb_set_cmap(cmap, kspc, e1356fb_setcolreg, fb); 2027 } else { 2028 fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1); 2029 } 2030 return 0; 2031} 2032 2033static int 2034e1356fb_mmap(struct fb_info *fb, 2035 struct file *file, 2036 struct vm_area_struct *vma) 2037{ 2038 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 2039 unsigned int len; 2040#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 2041 u64 start=0, off; 2042#else 2043 unsigned long start=0, off; 2044#endif 2045 2046 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { 2047 DPRINTK("invalid vma->vm_pgoff\n"); 2048 return -EINVAL; 2049 } 2050 2051#ifdef SHADOW_FRAME_BUFFER 2052 if (!info->shadow.fb) { 2053 int order = 0; 2054 while (info->fb_size > (PAGE_SIZE * (1 << order))) 2055 order++; 2056 info->shadow.fb = (void*)__get_free_pages(GFP_KERNEL, order); 2057 if (!info->shadow.fb) { 2058 DPRINTK("shadow fb alloc failed\n"); 2059 return -ENXIO; 2060 } 2061 memset(info->shadow.fb, 0, info->fb_size); 2062 init_timer(&info->shadow.timer); 2063 info->shadow.timer.function = do_write_shadow_fb; 2064 info->shadow.timer.data = (unsigned long)info; 2065 } 2066 mod_timer(&info->shadow.timer, jiffies+HZ/2); 2067 start = virt_to_phys(info->shadow.fb) & PAGE_MASK; 2068#else 2069 start = info->fix.membase_phys & PAGE_MASK; 2070#endif 2071 2072 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fb_size); 2073 2074 off = vma->vm_pgoff << PAGE_SHIFT; 2075 2076 if ((vma->vm_end - vma->vm_start + off) > len) { 2077 DPRINTK("invalid vma\n"); 2078 return -EINVAL; 2079 } 2080 2081 off += start; 2082 vma->vm_pgoff = off >> PAGE_SHIFT; 2083 2084 pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; 2085#ifdef SHADOW_FRAME_BUFFER 2086 vma->vm_flags |= VM_RESERVED; 2087 pgprot_val(vma->vm_page_prot) &= ~_CACHE_UNCACHED; 2088#else 2089 pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; 2090#endif 2091 2092 /* This is an IO map - tell maydump to skip this VMA */ 2093 vma->vm_flags |= VM_IO; 2094 // FIXME: shouldn't have to do this. If the pages are marked writeable, 2095 // the TLB fault handlers should set these. 2096 pgprot_val(vma->vm_page_prot) |= (_PAGE_DIRTY | _PAGE_VALID); 2097 2098 /* 2099 * The SED1356 has only a 16-bit wide data bus, and some 2100 * embedded platforms, such as the Pb1000, do not automatically 2101 * split 32-bit word accesses to the framebuffer into 2102 * seperate half-word accesses. Hence the upper half-word 2103 * never gets to the framebuffer. The following solution is 2104 * to intentionally return a non-32-bit-aligned VA. As long 2105 * as the user app assumes (and doesn't check) that the returned 2106 * VA is 32-bit aligned, all (assumed aligned) 32-bit accesses 2107 * will actually be unaligned and will get trapped by the MIPS 2108 * unaligned exception handler. This handler will emulate the 2109 * load/store instructions by splitting up the load/store 2110 * into two 16-bit load/stores. (This emulation is currently 2111 * enabled by default, but may be disabled in the future, when 2112 * alignment problems in user-level programs get fixed. When 2113 * that happens, this solution won't work anymore, unless the 2114 * process that mmap's the fb also calls sysmips(MIPS_FIXADE, 1), 2115 * which turns address-error emulation back on). 2116 * 2117 * Furthermore, this solution only seems to work for TinyX 2118 * (Xfbdev). Others, like Qt/E, do snoop the returned VA 2119 * and compensate, or do originally unaligned 32-bit accesses 2120 * which then become aligned, hence breaking this solution. 2121 */ 2122 if (info->fix.mmunalign) 2123 vma->vm_start += 2; 2124 2125#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 2126 if (e1356_remap_page_range(vma->vm_start, off, 2127 vma->vm_end - vma->vm_start, 2128 vma->vm_page_prot)) 2129 return -EAGAIN; 2130#else 2131 if (io_remap_page_range(vma->vm_start, off, 2132 vma->vm_end - vma->vm_start, 2133 vma->vm_page_prot)) 2134 return -EAGAIN; 2135#endif 2136 2137 info->mmaped = 1; 2138 return 0; 2139} 2140 2141 2142int __init 2143e1356fb_init(void) 2144{ 2145 struct fb_var_screeninfo var; 2146 struct e1356fb_fix * epfix = &fb_info.fix; 2147 e1356_reg_t* reg; 2148 void* regbase; 2149 char* name = "SED1356"; 2150 int periodMCLK, periodBCLK; 2151 int dram_timing, rr_div, mclk_src; 2152 u8 rev_code, btmp, mclk_cfg; 2153 2154 if (options) { 2155 e1356fb_setup(options, 0); 2156 } 2157 2158 // clear out fb_info 2159 memset(&fb_info, 0, sizeof(struct fb_info_e1356)); 2160 2161 // copy boot options 2162 fb_info.fix = boot_fix; 2163 fb_info.default_par = boot_par; 2164 2165 fb_info.regbase_size = E1356_REG_SIZE; 2166 2167 if (!epfix->system) { 2168 printk(KERN_ERR "e1356/86fb: no valid system found\n"); 2169 return -ENODEV; 2170 } 2171 2172 if (epfix->system == SYS_SDU1356) { 2173 // it's the SDU1356B0C PCI eval card. 2174 struct pci_dev *pdev = NULL; 2175 if (!pci_present()) /* No PCI bus in this machine! */ 2176 return -ENODEV; 2177 if (!(pdev = pci_find_device(PCI_VENDOR_ID_EPSON, 2178 PCI_DEVICE_ID_EPSON_SDU1356, pdev))) 2179 return -ENODEV; 2180 if (pci_enable_device(pdev)) 2181 return -ENODEV; 2182 epfix->regbase_phys = pci_resource_start(pdev, 0); 2183 epfix->membase_phys = epfix->regbase_phys + E1356_REG_SIZE; 2184 } 2185 2186 fb_info.regbase_virt = ioremap_nocache(epfix->regbase_phys, 2187 E1356_REG_SIZE); 2188 2189 if (!fb_info.regbase_virt) { 2190 printk("e1356fb: Can't remap %s register area.\n", name); 2191 return -ENXIO; 2192 } 2193 2194 regbase = fb_info.regbase_virt; 2195 reg = &fb_info.reg; 2196 2197 // Initialize the register pointers 2198 reg->basic = (reg_basic_t*) (regbase + REG_BASE_BASIC); 2199 reg->genio = (reg_genio_t*) (regbase + REG_BASE_GENIO); 2200 reg->md_cfg = (reg_mdcfg_t*) (regbase + REG_BASE_MDCFG); 2201 reg->clk_cfg = (reg_clkcfg_t*) (regbase + REG_BASE_CLKCFG); 2202 reg->mem_cfg = (reg_memcfg_t*) (regbase + REG_BASE_MEMCFG); 2203 reg->panel_cfg = (reg_panelcfg_t*)(regbase + REG_BASE_PANELCFG); 2204 reg->lcd_cfg = (reg_dispcfg_t*) (regbase + REG_BASE_LCD_DISPCFG); 2205 reg->crttv_cfg = (reg_dispcfg_t*) (regbase + REG_BASE_CRTTV_DISPCFG); 2206 reg->lcd_mode = (reg_dispmode_t*)(regbase + REG_BASE_LCD_DISPMODE); 2207 reg->crttv_mode = (reg_dispmode_t*)(regbase + REG_BASE_CRTTV_DISPMODE); 2208 reg->lcd_inkcurs = (reg_inkcurs_t*) (regbase + REG_BASE_LCD_INKCURS); 2209 reg->crttv_inkcurs = (reg_inkcurs_t*) (regbase + REG_BASE_CRTTV_INKCURS); 2210 reg->bitblt = (reg_bitblt_t*) (regbase + REG_BASE_BITBLT); 2211 reg->lut = (reg_lut_t*) (regbase + REG_BASE_LUT); 2212 reg->pwr_save = (reg_pwrsave_t*) (regbase + REG_BASE_PWRSAVE); 2213 reg->misc = (reg_misc_t*) (regbase + REG_BASE_MISC); 2214 reg->mediaplug = (reg_mediaplug_t*)(regbase + REG_BASE_MEDIAPLUG); 2215 reg->bitblt_data = (u16*) (regbase + REG_BASE_BITBLT_DATA); 2216 2217 // Enable all register access 2218 writeb(0, ®->basic->misc); 2219 2220 rev_code = readb(®->basic->rev_code); 2221 if ((rev_code >> 2) == 0x04) { 2222 printk("Found EPSON1356 Display Controller\n"); 2223 } 2224 else if ((rev_code >> 2) == 0x07) { 2225 printk("Found EPSON13806 Display Controller\n"); 2226 } 2227 else { 2228 iounmap(fb_info.regbase_virt); 2229 printk("e1356/806fb: %s not found, rev_code=0x%02x.\n", 2230 name, rev_code); 2231 return -ENODEV; 2232 } 2233 2234 fb_info.chip_rev = rev_code & 0x03; 2235 2236 // Determine frame-buffer size 2237 switch (readb(®->md_cfg->md_cfg_stat0) >> 6) { 2238 case 0: 2239 case 2: 2240 fb_info.fb_size = 0x80000; /* 512K bytes */ 2241 break; 2242 case 1: 2243 if ((rev_code >> 2) == 7) /* 806 */ 2244 fb_info.fb_size = 0x140000; /* 1.2M bytes */ 2245 else 2246 fb_info.fb_size = 0x200000; /* 2M bytes */ 2247 break; 2248 default: 2249 fb_info.fb_size = 0x200000; /* 2M bytes */ 2250 break; 2251 } 2252 2253 fb_info.membase_virt = ioremap_nocache(epfix->membase_phys, 2254 fb_info.fb_size); 2255 2256 if (!fb_info.membase_virt) { 2257 printk("e1356fb: Can't remap %s framebuffer.\n", name); 2258 iounmap(fb_info.regbase_virt); 2259 return -ENXIO; 2260 } 2261 2262 printk("e1356/806fb: Detected %dKB framebuffer\n", 2263 (unsigned)fb_info.fb_size/1000); 2264 2265#ifdef CONFIG_MTRR 2266 if (!epfix->nomtrr) { 2267 fb_info.mtrr_idx = mtrr_add(epfix->membase_phys, fb_info.fb_size, 2268 MTRR_TYPE_WRCOMB, 1); 2269 printk("e1356fb: MTRR's turned on\n"); 2270 } 2271#endif 2272 2273 if (!boot_fix.noaccel) { 2274 /* 2275 Allocate a page for string BLTs. A 4K page is 2276 enough for a 256 character string at an 8x16 font. 2277 */ 2278 fb_info.putcs_buffer = (void*)__get_free_pages(GFP_KERNEL, 0); 2279 if (fb_info.putcs_buffer == NULL) { 2280 printk("e1356fb: Can't allocate putcs buffer\n"); 2281 goto unmap_ret_enxio; 2282 } 2283 } 2284 2285 // Begin SED1356 initialization 2286 2287 // disable display while initializing 2288 writeb(0, ®->misc->disp_mode); 2289 // Set the GPIO1 and 2 to inputs 2290 writeb(0, ®->genio->gpio_cfg); 2291 writeb(0, ®->genio->gpio_ctrl); 2292 if (fb_info.chip_rev == 7) /* 806 */ 2293 writeb(0, ®->genio->gpio_ctrl2); 2294 2295 /* 2296 * Program the clocks 2297 */ 2298 2299#ifdef CONFIG_CPU_AU1X00 2300 if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500)) 2301 epfix->busclk = get_au1x00_lcd_clock(); 2302#endif 2303 2304 if (epfix->busclk > 80000) { 2305 printk("e1356fb: specified busclk too high\n"); 2306 goto ret_enxio; 2307 } 2308 2309 epfix->mclk = mclk_cfg = 0; 2310 if (epfix->system == SYS_PB1500) { 2311 epfix->mclk = epfix->busclk; 2312 mclk_cfg = 0x01; 2313 } 2314 else { 2315 // Find the highest allowable MCLK 2316 if (epfix->busclk <= MAX_PIXCLOCK && 2317 epfix->busclk > epfix->mclk) { 2318 epfix->mclk = epfix->busclk; 2319 mclk_cfg = 0x01; 2320 } 2321 if (epfix->clki <= MAX_PIXCLOCK && epfix->clki > epfix->mclk) { 2322 epfix->mclk = epfix->clki; 2323 mclk_cfg = 0x00; 2324 } 2325 if (epfix->busclk/2 <= MAX_PIXCLOCK && 2326 epfix->busclk/2 > epfix->mclk) { 2327 epfix->mclk = epfix->busclk/2; 2328 mclk_cfg = 0x11; 2329 } 2330 if (epfix->clki/2 <= MAX_PIXCLOCK && 2331 epfix->clki/2 > epfix->mclk) { 2332 epfix->mclk = epfix->clki/2; 2333 mclk_cfg = 0x10; 2334 } 2335 } 2336 2337 if (!epfix->mclk) { 2338 printk("e1356fb: couldn't find an allowable MCLK!\n"); 2339 goto ret_enxio; 2340 } 2341 2342 // When changing mclk src, you must first set bit 4 to 1. 2343 writeb(readb(®->clk_cfg->mem_clk_cfg) | 0x10, 2344 ®->clk_cfg->mem_clk_cfg); 2345 writeb(mclk_cfg, ®->clk_cfg->mem_clk_cfg); 2346 2347 printk("e1356fb: clocks (kHz): busclk=%d mclk=%d clki=%d clki2=%d\n", 2348 epfix->busclk, epfix->mclk, epfix->clki, epfix->clki2); 2349 2350 // Set max pixel clock 2351 switch (epfix->disp_type) { 2352 case DISP_TYPE_LCD: 2353 case DISP_TYPE_TFT: 2354 case DISP_TYPE_CRT: 2355 fb_info.max_pixclock = epfix->mclk; 2356 break; 2357 case DISP_TYPE_NTSC: 2358 case DISP_TYPE_PAL: 2359 fb_info.max_pixclock = (epfix->disp_type == DISP_TYPE_NTSC) ? 2360 NTSC_PIXCLOCK : PAL_PIXCLOCK; 2361 if (epfix->tv_filt & TV_FILT_FLICKER) 2362 fb_info.max_pixclock *= 2; 2363 break; 2364 default: 2365 printk("e1356fb: invalid specified display type\n"); 2366 goto ret_enxio; 2367 } 2368 2369 periodMCLK = 1000000L / epfix->mclk; // in nano-seconds 2370 periodBCLK = 1000000L / epfix->busclk; // in nano-seconds 2371 if (readb(®->md_cfg->md_cfg_stat1) & (1<<4)) 2372 periodBCLK *= 2; 2373 2374 if ((epfix->system == SYS_PB1000) || (epfix->system == SYS_PB1500)) 2375 writeb(0x00, ®->clk_cfg->cpu2mem_wait_sel); 2376 else if (periodMCLK - 4 > periodBCLK) 2377 writeb(0x02, ®->clk_cfg->cpu2mem_wait_sel); 2378 else if (2*periodMCLK - 4 > periodBCLK) 2379 writeb(0x01, ®->clk_cfg->cpu2mem_wait_sel); 2380 else 2381 writeb(0x00, ®->clk_cfg->cpu2mem_wait_sel); 2382 2383 // Program memory config 2384 if (epfix->mem_type < MEM_TYPE_EDO_2CAS || 2385 epfix->mem_type > MEM_TYPE_EMBEDDED_SDRAM) { 2386 printk("e1356fb: bad memory type specified\n"); 2387 goto ret_enxio; 2388 } 2389 writeb((u8)epfix->mem_type, ®->mem_cfg->mem_cfg); 2390 2391 // calc closest refresh rate 2392 rr_div = 7; 2393 mclk_src = (mclk_cfg & 1) ? epfix->busclk : epfix->clki; 2394 while ((mclk_src >> (6 + rr_div)) < epfix->mem_refresh) 2395 if (--rr_div < 0) { 2396 printk("e1356fb: can't set specified refresh rate\n"); 2397 goto ret_enxio; 2398 } 2399 2400 DPRINTK("refresh rate = %d kHz\n", (mclk_src >> (6 + rr_div))); 2401 2402 // add Suspend-Mode Refresh bits 2403 if (epfix->mem_smr < MEM_SMR_CBR || epfix->mem_smr > MEM_SMR_NONE) { 2404 printk("e1356fb: invalid specified suspend-mode refresh type\n"); 2405 goto ret_enxio; 2406 } 2407 writeb(rr_div | (epfix->mem_smr << 6), ®->mem_cfg->dram_refresh); 2408 2409 // set DRAM speed 2410 switch (epfix->mem_speed) { 2411 case 50: 2412 dram_timing = epfix->mclk >= 33000 ? 0x0101 : 0x0212; 2413 break; 2414 case 60: 2415 if (epfix->mclk >= 30000) 2416 dram_timing = 0x0101; 2417 else if (epfix->mclk >= 25000) 2418 dram_timing = 2419 (epfix->mem_type == MEM_TYPE_EDO_2CAS || 2420 epfix->mem_type == MEM_TYPE_EDO_2WE) ? 2421 0x0212 : 0x0101; 2422 else 2423 dram_timing = 0x0212; 2424 break; 2425 case 70: 2426 if (epfix->mclk >= 30000) 2427 dram_timing = 0x0000; 2428 else if (epfix->mclk >= 25000) 2429 dram_timing = 0x0101; 2430 else 2431 dram_timing = 2432 (epfix->mem_type == MEM_TYPE_EDO_2CAS || 2433 epfix->mem_type == MEM_TYPE_EDO_2WE) ? 2434 0x0212 : 0x0211; 2435 break; 2436 case 80: 2437 if (epfix->mclk >= 25000) 2438 dram_timing = 0x0100; 2439 else 2440 dram_timing = 0x0101; 2441 break; 2442 default: 2443 printk("e1356fb: invalid specified memory speed\n"); 2444 goto ret_enxio; 2445 } 2446 2447 writew(dram_timing, ®->mem_cfg->dram_timings_ctrl0); 2448 2449 currcon = -1; 2450 if (!epfix->nohwcursor) 2451 e1356fb_hwcursor_init(&fb_info); 2452 2453 init_timer(&fb_info.cursor.timer); 2454 fb_info.cursor.timer.function = do_flashcursor; 2455 fb_info.cursor.timer.data = (unsigned long)(&fb_info); 2456 fb_info.cursor.state = CM_ERASE; 2457 spin_lock_init(&fb_info.cursor.lock); 2458 2459 strcpy(fb_info.fb_info.modename, "Epson "); 2460 strcat(fb_info.fb_info.modename, name); 2461 fb_info.fb_info.changevar = NULL; 2462 fb_info.fb_info.node = -1; 2463 2464 fb_info.fb_info.fbops = &e1356fb_ops; 2465 fb_info.fb_info.disp = &fb_info.disp; 2466 strcpy(fb_info.fb_info.fontname, epfix->fontname); 2467 fb_info.fb_info.switch_con = &e1356fb_switch_con; 2468 fb_info.fb_info.updatevar = &e1356fb_updatevar; 2469 fb_info.fb_info.blank = &e1356fb_blank; 2470 fb_info.fb_info.flags = FBINFO_FLAG_DEFAULT; 2471 2472 // Set-up display 2473 // clear out unused stuff 2474 writeb(0, ®->panel_cfg->mod_rate); 2475 writeb(0x01, ®->lcd_mode->lcd_misc); 2476 writeb(0, ®->lcd_mode->fifo_high_thresh); 2477 writeb(0, ®->lcd_mode->fifo_low_thresh); 2478 writeb(0, ®->crttv_mode->fifo_high_thresh); 2479 writeb(0, ®->crttv_mode->fifo_low_thresh); 2480 2481 switch (epfix->disp_type) { 2482 case DISP_TYPE_LCD: 2483 switch (epfix->panel_width) { 2484 case 4: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x04); break; 2485 case 8: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x14); break; 2486 case 16: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x24); break; 2487 default: 2488 printk("e1356fb: invalid specified LCD panel data width\n"); 2489 goto ret_enxio; 2490 } 2491 writeb(btmp, ®->panel_cfg->panel_type); 2492 break; 2493 case DISP_TYPE_TFT: 2494 switch (epfix->panel_width) { 2495 case 9: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x05); break; 2496 case 12: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x15); break; 2497 case 18: btmp = (u8)(((epfix->panel_el & 1)<<7) | 0x25); break; 2498 default: 2499 printk("e1356fb: invalid specified TFT panel data width\n"); 2500 goto ret_enxio; 2501 } 2502 writeb(btmp, ®->panel_cfg->panel_type); 2503 break; 2504 case DISP_TYPE_CRT: 2505 writeb(0x00, ®->crttv_cfg->tv_output_ctrl); 2506 break; 2507 case DISP_TYPE_NTSC: 2508 case DISP_TYPE_PAL: 2509 if (epfix->tv_fmt < TV_FMT_COMPOSITE || 2510 epfix->tv_fmt > TV_FMT_S_VIDEO) { 2511 printk("e1356fb: invalid specified TV output format\n"); 2512 goto ret_enxio; 2513 } 2514 btmp = epfix->disp_type == DISP_TYPE_PAL ? 0x01 : 0x00; 2515 btmp |= (epfix->tv_fmt == TV_FMT_S_VIDEO ? 0x02 : 0x00); 2516 btmp |= ((epfix->tv_filt & TV_FILT_LUM) ? 0x10 : 0x00); 2517 btmp |= ((epfix->tv_filt & TV_FILT_CHROM) ? 0x20 : 0x00); 2518 writeb(btmp, ®->crttv_cfg->tv_output_ctrl); 2519 break; 2520 } 2521 2522 memset(&var, 0, sizeof(var)); 2523 /* 2524 * If mode_option wasn't given at boot, assume all the boot 2525 * option timing parameters were specified individually, in 2526 * which case we convert par_to_var instead of calling 2527 * fb_find_mode. 2528 */ 2529 if (epfix->mode_option) { 2530 struct fb_videomode* modedb, *dm; 2531 int dbsize = e1356fb_get_mode(&fb_info, 640, 480, &modedb, &dm); 2532 2533 // first try the generic modedb 2534 if (!fb_find_mode(&var, &fb_info.fb_info, epfix->mode_option, 2535 NULL, 0, NULL, boot_par.bpp)) { 2536 printk("e1356fb: mode %s failed, trying e1356 modedb\n", 2537 epfix->mode_option); 2538 // didn't work in generic modedb, try ours 2539 if (!fb_find_mode(&var, &fb_info.fb_info, 2540 epfix->mode_option, 2541 modedb, dbsize, dm, boot_par.bpp)) { 2542 printk("e1356fb: mode %s failed e1356 modedb too, sorry\n", 2543 epfix->mode_option); 2544 2545 goto ret_enxio; 2546 } 2547 } 2548 2549 var.xres_virtual = boot_par.width_virt ? 2550 boot_par.width_virt : boot_par.width; 2551 var.yres_virtual = boot_par.height_virt ? 2552 boot_par.height_virt : boot_par.height; 2553 } else { 2554 if (e1356fb_par_to_var(&var, &fb_info.default_par, &fb_info)) { 2555 printk("e1356fb: boot option mode failed\n"); 2556 goto ret_enxio; 2557 } 2558 } 2559 2560 if (boot_fix.noaccel) 2561 var.accel_flags &= ~FB_ACCELF_TEXT; 2562 else 2563 var.accel_flags |= FB_ACCELF_TEXT; 2564 2565 if (e1356fb_var_to_par(&var, &fb_info.default_par, &fb_info)) { 2566 /* 2567 * Can't use the mode from the mode db or the default 2568 * mode or the boot options - give up 2569 */ 2570 printk("e1356fb: mode failed var_to_par\n"); 2571 goto ret_enxio; 2572 } 2573 2574 fb_info.disp.screen_base = fb_info.membase_virt; 2575 fb_info.disp.var = var; // struct copy 2576 2577 // here's where the screen is actually initialized and enabled 2578 if (e1356fb_set_var(&var, -1, &fb_info.fb_info)) { 2579 printk("e1356fb: can't set video mode\n"); 2580 goto ret_enxio; 2581 } 2582 2583 writeb(0, ®->pwr_save->cfg); // disable power-save mode 2584 writeb(0, ®->misc->cpu2mem_watchdog); // disable watchdog timer 2585 2586#ifdef E1356FB_VERBOSE_DEBUG 2587 dump_fb(fb_info.membase_virt + 0x100000, 512); 2588#endif 2589 2590 if (register_framebuffer(&fb_info.fb_info) < 0) { 2591 writeb(0, ®->misc->disp_mode); 2592 printk("e1356fb: can't register framebuffer\n"); 2593 goto ret_enxio; 2594 } 2595 2596 printk("fb%d: %s frame buffer device\n", 2597 GET_FB_IDX(fb_info.fb_info.node), 2598 fb_info.fb_info.modename); 2599 2600 2601 return 0; 2602 2603 ret_enxio: 2604 free_pages((unsigned long)fb_info.putcs_buffer, 0); 2605 unmap_ret_enxio: 2606 iounmap(fb_info.regbase_virt); 2607 iounmap(fb_info.membase_virt); 2608 return -ENXIO; 2609} 2610 2611static void __exit 2612e1356fb_exit (void) 2613{ 2614 unregister_framebuffer(&fb_info.fb_info); 2615 del_timer_sync(&fb_info.cursor.timer); 2616 2617#ifdef CONFIG_MTRR 2618 if (!fb_info.fix.nomtrr) { 2619 mtrr_del(fb_info.mtrr_idx, fb_info.fix.membase_phys, 2620 fb_info.fb_size); 2621 printk("fb: MTRR's turned off\n"); 2622 } 2623#endif 2624 2625 free_pages((unsigned long)fb_info.putcs_buffer, 0); 2626 iounmap(fb_info.regbase_virt); 2627 iounmap(fb_info.membase_virt); 2628} 2629 2630MODULE_AUTHOR("Steve Longerbeam <stevel@mvista.com>"); 2631MODULE_DESCRIPTION("SED1356 framebuffer device driver"); 2632 2633#ifdef MODULE 2634module_init(e1356fb_init); 2635#endif 2636module_exit(e1356fb_exit); 2637 2638 2639void 2640e1356fb_setup(char *options, int *ints) 2641{ 2642 char* this_opt; 2643 2644 memset(&boot_fix, 0, sizeof(struct e1356fb_fix)); 2645 memset(&boot_par, 0, sizeof(struct e1356fb_par)); 2646 boot_fix.system = -1; 2647 2648 if (!options || !*options) 2649 return; 2650 2651 for(this_opt=strtok(options, ","); this_opt; 2652 this_opt=strtok(NULL, ",")) { 2653 if (!strncmp(this_opt, "noaccel", 7)) { 2654 boot_fix.noaccel = 1; 2655 } else if (!strncmp(this_opt, "nopan", 5)) { 2656 boot_fix.nopan = 1; 2657 } else if (!strncmp(this_opt, "nohwcursor", 10)) { 2658 boot_fix.nohwcursor = 1; 2659 } else if (!strncmp(this_opt, "mmunalign:", 10)) { 2660 boot_fix.mmunalign = simple_strtoul(this_opt+10, 2661 NULL, 0); 2662#ifdef CONFIG_MTRR 2663 } else if (!strncmp(this_opt, "nomtrr", 6)) { 2664 boot_fix.nomtrr = 1; 2665#endif 2666 } else if (!strncmp(this_opt, "font:", 5)) { 2667 strncpy(boot_fix.fontname, this_opt+5, 2668 sizeof(boot_fix.fontname)-1); 2669 } else if (!strncmp(this_opt, "regbase:", 8)) { 2670 boot_fix.regbase_phys = simple_strtoul(this_opt+8, 2671 NULL, 0); 2672 } else if (!strncmp(this_opt, "membase:", 8)) { 2673 boot_fix.membase_phys = simple_strtoul(this_opt+8, 2674 NULL, 0); 2675 } else if (!strncmp(this_opt, "memsp:", 6)) { 2676 boot_fix.mem_speed = simple_strtoul(this_opt+6, 2677 NULL, 0); 2678 } else if (!strncmp(this_opt, "memtyp:", 7)) { 2679 boot_fix.mem_type = simple_strtoul(this_opt+7, 2680 NULL, 0); 2681 } else if (!strncmp(this_opt, "memref:", 7)) { 2682 boot_fix.mem_refresh = simple_strtoul(this_opt+7, 2683 NULL, 0); 2684 } else if (!strncmp(this_opt, "memsmr:", 7)) { 2685 boot_fix.mem_smr = simple_strtoul(this_opt+7, NULL, 0); 2686 } else if (!strncmp(this_opt, "busclk:", 7)) { 2687 boot_fix.busclk = simple_strtoul(this_opt+7, NULL, 0); 2688 } else if (!strncmp(this_opt, "clki:", 5)) { 2689 boot_fix.clki = simple_strtoul(this_opt+5, NULL, 0); 2690 } else if (!strncmp(this_opt, "clki2:", 6)) { 2691 boot_fix.clki2 = simple_strtoul(this_opt+6, NULL, 0); 2692 } else if (!strncmp(this_opt, "display:", 8)) { 2693 if (!strncmp(this_opt+8, "lcd", 3)) 2694 boot_fix.disp_type = DISP_TYPE_LCD; 2695 else if (!strncmp(this_opt+8, "tft", 3)) 2696 boot_fix.disp_type = DISP_TYPE_TFT; 2697 else if (!strncmp(this_opt+8, "crt", 3)) 2698 boot_fix.disp_type = DISP_TYPE_CRT; 2699 else if (!strncmp(this_opt+8, "pal", 3)) 2700 boot_fix.disp_type = DISP_TYPE_PAL; 2701 else if (!strncmp(this_opt+8, "ntsc", 4)) 2702 boot_fix.disp_type = DISP_TYPE_NTSC; 2703 } else if (!strncmp(this_opt, "width:", 6)) { 2704 boot_par.width = simple_strtoul(this_opt+6, NULL, 0); 2705 } else if (!strncmp(this_opt, "height:", 7)) { 2706 boot_par.height = simple_strtoul(this_opt+7, NULL, 0); 2707 } else if (!strncmp(this_opt, "bpp:", 4)) { 2708 boot_par.bpp = simple_strtoul(this_opt+4, NULL, 0); 2709 boot_par.cmap_len = (boot_par.bpp == 8) ? 256 : 16; 2710 } else if (!strncmp(this_opt, "elpanel:", 8)) { 2711 boot_fix.panel_el = simple_strtoul(this_opt+8, 2712 NULL, 0); 2713 } else if (!strncmp(this_opt, "pdataw:", 7)) { 2714 boot_fix.panel_width = simple_strtoul(this_opt+7, 2715 NULL, 0); 2716 } else if (!strncmp(this_opt, "hndp:", 5)) { 2717 boot_par.horiz_ndp = simple_strtoul(this_opt+5, 2718 NULL, 0); 2719 } else if (!strncmp(this_opt, "vndp:", 5)) { 2720 boot_par.vert_ndp = simple_strtoul(this_opt+5, 2721 NULL, 0); 2722 } else if (!strncmp(this_opt, "hspol:", 6)) { 2723 boot_par.hsync_pol = simple_strtoul(this_opt+6, 2724 NULL, 0); 2725 } else if (!strncmp(this_opt, "vspol:", 6)) { 2726 boot_par.vsync_pol = simple_strtoul(this_opt+6, 2727 NULL, 0); 2728 } else if (!strncmp(this_opt, "hsstart:", 8)) { 2729 boot_par.hsync_start = simple_strtoul(this_opt+8, 2730 NULL, 0); 2731 } else if (!strncmp(this_opt, "hswidth:", 8)) { 2732 boot_par.hsync_width = simple_strtoul(this_opt+8, 2733 NULL, 0); 2734 } else if (!strncmp(this_opt, "vsstart:", 8)) { 2735 boot_par.vsync_start = simple_strtoul(this_opt+8, 2736 NULL, 0); 2737 } else if (!strncmp(this_opt, "vswidth:", 8)) { 2738 boot_par.vsync_width = simple_strtoul(this_opt+8, 2739 NULL, 0); 2740 } else if (!strncmp(this_opt, "tvfilt:", 7)) { 2741 boot_fix.tv_filt = simple_strtoul(this_opt+7, NULL, 0); 2742 } else if (!strncmp(this_opt, "tvfmt:", 6)) { 2743 boot_fix.tv_fmt = simple_strtoul(this_opt+6, NULL, 0); 2744 } else if (!strncmp(this_opt, "system:", 7)) { 2745 if (!strncmp(this_opt+7, "pb1000", 10)) { 2746 boot_fix = systems[SYS_PB1000].fix; 2747 boot_par = systems[SYS_PB1000].par; 2748 } else if (!strncmp(this_opt+7, "pb1500", 7)) { 2749 boot_fix = systems[SYS_PB1500].fix; 2750 boot_par = systems[SYS_PB1500].par; 2751 } else if (!strncmp(this_opt+7, "sdu1356", 7)) { 2752 boot_fix = systems[SYS_SDU1356].fix; 2753 boot_par = systems[SYS_SDU1356].par; 2754 } else if (!strncmp(this_opt+7, "clio1050", 7)) { 2755 boot_fix = systems[SYS_CLIO1050].fix; 2756 boot_par = systems[SYS_CLIO1050].par; 2757 } 2758 } else { 2759 boot_fix.mode_option = this_opt; 2760 } 2761 } 2762} 2763 2764 2765static int 2766e1356fb_switch_con(int con, struct fb_info *fb) 2767{ 2768 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 2769 struct e1356fb_par par; 2770 int old_con = currcon; 2771 int set_par = 1; 2772 2773 //DPRINTK("\n"); 2774 2775 /* Do we have to save the colormap? */ 2776 if (currcon>=0) 2777 if (fb_display[currcon].cmap.len) 2778 fb_get_cmap(&fb_display[currcon].cmap, 1, 2779 e1356fb_getcolreg, fb); 2780 2781 currcon = con; 2782 fb_display[currcon].var.activate = FB_ACTIVATE_NOW; 2783 e1356fb_var_to_par(&fb_display[con].var, &par, info); 2784 if (old_con>=0 && vt_cons[old_con]->vc_mode!=KD_GRAPHICS) { 2785 /* check if we have to change video registers */ 2786 struct e1356fb_par old_par; 2787 e1356fb_var_to_par(&fb_display[old_con].var, &old_par, info); 2788 if (!memcmp(&par,&old_par,sizeof(par))) 2789 set_par = 0; /* avoid flicker */ 2790 } 2791 if (set_par) 2792 e1356fb_set_par(&par, info); 2793 2794 if (fb_display[con].dispsw && fb_display[con].conp) 2795 fb_con.con_cursor(fb_display[con].conp, CM_ERASE); 2796 2797 del_timer(&(info->cursor.timer)); 2798 fb_info.cursor.state=CM_ERASE; 2799 2800 if (!info->fix.nohwcursor) 2801 if (fb_display[con].conp) 2802 e1356fb_createcursor( &fb_display[con] ); 2803 2804 info->cursor.redraw=1; 2805 2806 e1356fb_set_dispsw(&fb_display[con], 2807 info, 2808 par.bpp, 2809 fb_display[con].var.accel_flags & FB_ACCELF_TEXT); 2810 2811 e1356fb_install_cmap(&fb_display[con], fb); 2812 e1356fb_updatevar(con, fb); 2813 2814 return 1; 2815} 2816 2817/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ 2818static void 2819e1356fb_blank(int blank, struct fb_info *fb) 2820{ 2821 struct fb_info_e1356 *info = (struct fb_info_e1356*)fb; 2822 reg_dispmode_t* dispmode = (IS_PANEL(info->fix.disp_type)) ? 2823 info->reg.lcd_mode : info->reg.crttv_mode; 2824 reg_pwrsave_t* pwrsave = info->reg.pwr_save; 2825 2826 //DPRINTK("\n"); 2827 2828 switch (blank) { 2829 case 0: 2830 // Get out of power save mode 2831 writeb(0x00, &pwrsave->cfg); 2832 writeb(readb(&dispmode->disp_mode) & ~0x80, 2833 &dispmode->disp_mode); 2834 break; 2835 case 1: 2836 // Get out of power save mode 2837 writeb(0x00, &pwrsave->cfg); 2838 writeb(readb(&dispmode->disp_mode) | 0x80, 2839 &dispmode->disp_mode); 2840 break; 2841 // No support for turning off horiz or vert sync, so just treat 2842 // it as a power off. 2843 case 2: 2844 case 3: 2845 case 4: 2846 writeb(0x01, &pwrsave->cfg); 2847 break; 2848 } 2849} 2850 2851 2852static int 2853e1356fb_updatevar(int con, struct fb_info* fb) 2854{ 2855 struct fb_info_e1356* i = (struct fb_info_e1356*)fb; 2856 2857 //DPRINTK("\n"); 2858 2859 if ((con==currcon) && (!i->fix.nopan)) 2860 do_pan_var(&fb_display[con].var,i); 2861 return 0; 2862} 2863 2864static int 2865e1356fb_getcolreg(unsigned regno, 2866 unsigned* red, 2867 unsigned* green, 2868 unsigned* blue, 2869 unsigned* transp, 2870 struct fb_info* fb) 2871{ 2872 struct fb_info_e1356* i = (struct fb_info_e1356*)fb; 2873 2874 if (regno > i->current_par.cmap_len) 2875 return 1; 2876 2877 *red = i->palette[regno].red; 2878 *green = i->palette[regno].green; 2879 *blue = i->palette[regno].blue; 2880 *transp = 0; 2881 2882 return 0; 2883} 2884 2885static int 2886e1356fb_setcolreg(unsigned regno, 2887 unsigned red, 2888 unsigned green, 2889 unsigned blue, 2890 unsigned transp, 2891 struct fb_info* info) 2892{ 2893 struct fb_info_e1356* i = (struct fb_info_e1356*)info; 2894 2895 if (regno > 255) 2896 return 1; 2897 2898 i->palette[regno].red = red; 2899 i->palette[regno].green = green; 2900 i->palette[regno].blue = blue; 2901 2902 switch(i->current_par.bpp) { 2903#ifdef FBCON_HAS_CFB8 2904 case 8: 2905 do_setpalentry(i->reg.lut, regno, 2906 (u8)(red>>8), (u8)(green>>8), (u8)(blue>>8)); 2907 break; 2908#endif 2909#ifdef FBCON_HAS_CFB16 2910 case 16: 2911 i->fbcon_cmap16[regno] = (regno << 10) | (regno << 5) | regno; 2912 break; 2913#endif 2914 default: 2915 DPRINTK("bad depth %u\n", i->current_par.bpp); 2916 break; 2917 } 2918 return 0; 2919} 2920 2921static void 2922e1356fb_install_cmap(struct display *d, struct fb_info *info) 2923{ 2924 struct fb_info_e1356* i = (struct fb_info_e1356*)info; 2925 2926 //DPRINTK("\n"); 2927 2928 if (d->cmap.len) { 2929 fb_set_cmap(&(d->cmap), 1, e1356fb_setcolreg, info); 2930 } else { 2931 fb_set_cmap(fb_default_cmap(i->current_par.cmap_len), 1, 2932 e1356fb_setcolreg, info); 2933 } 2934} 2935 2936static void 2937e1356fb_createcursorshape(struct display* p) 2938{ 2939 int h,u; 2940 2941 h = fontheight(p); 2942 2943 fb_info.cursor.type = p->conp->vc_cursor_type & CUR_HWMASK; 2944 2945 switch (fb_info.cursor.type) { 2946 case CUR_NONE: 2947 u = h; 2948 break; 2949 case CUR_UNDERLINE: 2950 u = h - 2; 2951 break; 2952 case CUR_LOWER_THIRD: 2953 u = (h * 2) / 3; 2954 break; 2955 case CUR_LOWER_HALF: 2956 u = h / 2; 2957 break; 2958 case CUR_TWO_THIRDS: 2959 u = h / 3; 2960 break; 2961 case CUR_BLOCK: 2962 default: 2963 u = 0; 2964 break; 2965 } 2966 2967 fb_info.cursor.w = fontwidth_x8(p); 2968 fb_info.cursor.u = u; 2969 fb_info.cursor.h = h; 2970} 2971 2972static void 2973e1356fb_createcursor(struct display *p) 2974{ 2975 void* memcursor; 2976 int y, w, h, u; 2977 2978 e1356fb_createcursorshape(p); 2979 2980 h = fb_info.cursor.h; 2981 w = fb_info.cursor.w; 2982 u = fb_info.cursor.u; 2983 memcursor = fb_info.membase_virt + fb_info.fb_size; 2984 2985 // write cursor to display memory 2986 for (y=0; y<64; y++) { 2987 if (y >= h || y < u) { 2988 fbfill((u16*)memcursor, 0xaa, 16); // b/g 2989 } else { 2990 fbfill((u16*)memcursor, 0xff, w/4); // inverted b/g 2991 fbfill((u16*)memcursor + w/4, 0xaa, (64 - w)/4); // b/g 2992 } 2993 memcursor += 16; 2994 } 2995} 2996 2997static void 2998e1356fb_hwcursor_init(struct fb_info_e1356* info) 2999{ 3000 reg_inkcurs_t* inkcurs = (IS_PANEL(info->fix.disp_type)) ? 3001 info->reg.lcd_inkcurs : info->reg.crttv_inkcurs; 3002 3003 fb_info.fb_size -= 1024; 3004 // program cursor base address 3005 writeb(0x00, &inkcurs->start_addr); 3006 printk("e1356fb: reserving 1024 bytes for the hwcursor at %p\n", 3007 fb_info.membase_virt + fb_info.fb_size); 3008} 3009 3010#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32) 3011 3012/* 3013 * Return indicates whether a page was freed so caller can adjust rss 3014 */ 3015static inline void forget_pte(pte_t page) 3016{ 3017 if (!pte_none(page)) { 3018 printk("forget_pte: old mapping existed!\n"); 3019 BUG(); 3020 } 3021} 3022 3023/* 3024 * maps a range of physical memory into the requested pages. the old 3025 * mappings are removed. any references to nonexistent pages results 3026 * in null mappings (currently treated as "copy-on-access") 3027 */ 3028static inline void e1356_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size, 3029 phys_t phys_addr, pgprot_t prot) 3030{ 3031 unsigned long end; 3032 3033 address &= ~PMD_MASK; 3034 end = address + size; 3035 if (end > PMD_SIZE) 3036 end = PMD_SIZE; 3037 do { 3038 struct page *page; 3039 pte_t oldpage; 3040 oldpage = ptep_get_and_clear(pte); 3041 3042 page = virt_to_page(__va(phys_addr)); 3043 if ((!VALID_PAGE(page)) || PageReserved(page)) 3044 set_pte(pte, mk_pte_phys(phys_addr, prot)); 3045 forget_pte(oldpage); 3046 address += PAGE_SIZE; 3047 phys_addr += PAGE_SIZE; 3048 pte++; 3049 } while (address && (address < end)); 3050} 3051 3052static inline int e1356_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size, 3053 phys_t phys_addr, pgprot_t prot) 3054{ 3055 unsigned long end; 3056 3057 address &= ~PGDIR_MASK; 3058 end = address + size; 3059 if (end > PGDIR_SIZE) 3060 end = PGDIR_SIZE; 3061 phys_addr -= address; 3062 do { 3063 pte_t * pte = pte_alloc(mm, pmd, address); 3064 if (!pte) 3065 return -ENOMEM; 3066 e1356_remap_pte_range(pte, address, end - address, address + phys_addr, prot); 3067 address = (address + PMD_SIZE) & PMD_MASK; 3068 pmd++; 3069 } while (address && (address < end)); 3070 return 0; 3071} 3072 3073/* Note: this is only safe if the mm semaphore is held when called. */ 3074static int e1356_remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot) 3075{ 3076 int error = 0; 3077 pgd_t * dir; 3078 phys_t beg = from; 3079 phys_t end = from + size; 3080 struct mm_struct *mm = current->mm; 3081 3082 phys_addr -= from; 3083 dir = pgd_offset(mm, from); 3084 flush_cache_range(mm, beg, end); 3085 if (from >= end) 3086 BUG(); 3087 3088 spin_lock(&mm->page_table_lock); 3089 do { 3090 pmd_t *pmd = pmd_alloc(mm, dir, from); 3091 error = -ENOMEM; 3092 if (!pmd) 3093 break; 3094 error = e1356_remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot); 3095 if (error) 3096 break; 3097 from = (from + PGDIR_SIZE) & PGDIR_MASK; 3098 dir++; 3099 } while (from && (from < end)); 3100 spin_unlock(&mm->page_table_lock); 3101 flush_tlb_range(mm, beg, end); 3102 return error; 3103} 3104#endif 3105