1 /* linux/drivers/video/sm501fb.c 2 * 3 * Copyright (c) 2006 Simtec Electronics 4 * Vincent Sanders <vince@simtec.co.uk> 5 * Ben Dooks <ben@simtec.co.uk> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Framebuffer driver for the Silicon Motion SM501 12 */ 13 14 #include <linux/module.h> 15 #include <linux/kernel.h> 16 #include <linux/errno.h> 17 #include <linux/string.h> 18 #include <linux/mm.h> 19 #include <linux/tty.h> 20 #include <linux/slab.h> 21 #include <linux/delay.h> 22 #include <linux/fb.h> 23 #include <linux/init.h> 24 #include <linux/vmalloc.h> 25 #include <linux/dma-mapping.h> 26 #include <linux/interrupt.h> 27 #include <linux/workqueue.h> 28 #include <linux/wait.h> 29 #include <linux/platform_device.h> 30 #include <linux/clk.h> 31 #include <linux/console.h> 32 #include <linux/io.h> 33 34 #include <linux/uaccess.h> 35 #include <asm/div64.h> 36 37 #ifdef CONFIG_PM 38 #include <linux/pm.h> 39 #endif 40 41 #include <linux/sm501.h> 42 #include <linux/sm501-regs.h> 43 44 #include "edid.h" 45 46 static char *fb_mode = "640x480-16@60"; 47 static unsigned long default_bpp = 16; 48 49 static const struct fb_videomode sm501_default_mode = { 50 .refresh = 60, 51 .xres = 640, 52 .yres = 480, 53 .pixclock = 20833, 54 .left_margin = 142, 55 .right_margin = 13, 56 .upper_margin = 21, 57 .lower_margin = 1, 58 .hsync_len = 69, 59 .vsync_len = 3, 60 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 61 .vmode = FB_VMODE_NONINTERLACED 62 }; 63 64 #define NR_PALETTE 256 65 66 enum sm501_controller { 67 HEAD_CRT = 0, 68 HEAD_PANEL = 1, 69 }; 70 71 /* SM501 memory address. 72 * 73 * This structure is used to track memory usage within the SM501 framebuffer 74 * allocation. The sm_addr field is stored as an offset as it is often used 75 * against both the physical and mapped addresses. 76 */ 77 struct sm501_mem { 78 unsigned long size; 79 unsigned long sm_addr; /* offset from base of sm501 fb. */ 80 void __iomem *k_addr; 81 }; 82 83 /* private data that is shared between all frambuffers* */ 84 struct sm501fb_info { 85 struct device *dev; 86 struct fb_info *fb[2]; /* fb info for both heads */ 87 struct resource *fbmem_res; /* framebuffer resource */ 88 struct resource *regs_res; /* registers resource */ 89 struct resource *regs2d_res; /* 2d registers resource */ 90 struct sm501_platdata_fb *pdata; /* our platform data */ 91 92 unsigned long pm_crt_ctrl; /* pm: crt ctrl save */ 93 94 int irq; 95 int swap_endian; /* set to swap rgb=>bgr */ 96 void __iomem *regs; /* remapped registers */ 97 void __iomem *regs2d; /* 2d remapped registers */ 98 void __iomem *fbmem; /* remapped framebuffer */ 99 size_t fbmem_len; /* length of remapped region */ 100 u8 *edid_data; 101 }; 102 103 /* per-framebuffer private data */ 104 struct sm501fb_par { 105 u32 pseudo_palette[16]; 106 107 enum sm501_controller head; 108 struct sm501_mem cursor; 109 struct sm501_mem screen; 110 struct fb_ops ops; 111 112 void *store_fb; 113 void *store_cursor; 114 void __iomem *cursor_regs; 115 struct sm501fb_info *info; 116 }; 117 118 /* Helper functions */ 119 120 static inline int h_total(struct fb_var_screeninfo *var) 121 { 122 return var->xres + var->left_margin + 123 var->right_margin + var->hsync_len; 124 } 125 126 static inline int v_total(struct fb_var_screeninfo *var) 127 { 128 return var->yres + var->upper_margin + 129 var->lower_margin + var->vsync_len; 130 } 131 132 /* sm501fb_sync_regs() 133 * 134 * This call is mainly for PCI bus systems where we need to 135 * ensure that any writes to the bus are completed before the 136 * next phase, or after completing a function. 137 */ 138 139 static inline void sm501fb_sync_regs(struct sm501fb_info *info) 140 { 141 smc501_readl(info->regs); 142 } 143 144 /* sm501_alloc_mem 145 * 146 * This is an attempt to lay out memory for the two framebuffers and 147 * everything else 148 * 149 * |fbmem_res->start fbmem_res->end| 150 * | | 151 * |fb[0].fix.smem_start | |fb[1].fix.smem_start | 2K | 152 * |-> fb[0].fix.smem_len <-| spare |-> fb[1].fix.smem_len <-|-> cursors <-| 153 * 154 * The "spare" space is for the 2d engine data 155 * the fixed is space for the cursors (2x1Kbyte) 156 * 157 * we need to allocate memory for the 2D acceleration engine 158 * command list and the data for the engine to deal with. 159 * 160 * - all allocations must be 128bit aligned 161 * - cursors are 64x64x2 bits (1Kbyte) 162 * 163 */ 164 165 #define SM501_MEMF_CURSOR (1) 166 #define SM501_MEMF_PANEL (2) 167 #define SM501_MEMF_CRT (4) 168 #define SM501_MEMF_ACCEL (8) 169 170 static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, 171 unsigned int why, size_t size, u32 smem_len) 172 { 173 struct sm501fb_par *par; 174 struct fb_info *fbi; 175 unsigned int ptr; 176 unsigned int end; 177 178 switch (why) { 179 case SM501_MEMF_CURSOR: 180 ptr = inf->fbmem_len - size; 181 inf->fbmem_len = ptr; /* adjust available memory. */ 182 break; 183 184 case SM501_MEMF_PANEL: 185 if (size > inf->fbmem_len) 186 return -ENOMEM; 187 188 ptr = inf->fbmem_len - size; 189 fbi = inf->fb[HEAD_CRT]; 190 191 /* round down, some programs such as directfb do not draw 192 * 0,0 correctly unless the start is aligned to a page start. 193 */ 194 195 if (ptr > 0) 196 ptr &= ~(PAGE_SIZE - 1); 197 198 if (fbi && ptr < smem_len) 199 return -ENOMEM; 200 201 break; 202 203 case SM501_MEMF_CRT: 204 ptr = 0; 205 206 /* check to see if we have panel memory allocated 207 * which would put an limit on available memory. */ 208 209 fbi = inf->fb[HEAD_PANEL]; 210 if (fbi) { 211 par = fbi->par; 212 end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len; 213 } else 214 end = inf->fbmem_len; 215 216 if ((ptr + size) > end) 217 return -ENOMEM; 218 219 break; 220 221 case SM501_MEMF_ACCEL: 222 fbi = inf->fb[HEAD_CRT]; 223 ptr = fbi ? smem_len : 0; 224 225 fbi = inf->fb[HEAD_PANEL]; 226 if (fbi) { 227 par = fbi->par; 228 end = par->screen.sm_addr; 229 } else 230 end = inf->fbmem_len; 231 232 if ((ptr + size) > end) 233 return -ENOMEM; 234 235 break; 236 237 default: 238 return -EINVAL; 239 } 240 241 mem->size = size; 242 mem->sm_addr = ptr; 243 mem->k_addr = inf->fbmem + ptr; 244 245 dev_dbg(inf->dev, "%s: result %08lx, %p - %u, %zd\n", 246 __func__, mem->sm_addr, mem->k_addr, why, size); 247 248 return 0; 249 } 250 251 /* sm501fb_ps_to_hz 252 * 253 * Converts a period in picoseconds to Hz. 254 * 255 * Note, we try to keep this in Hz to minimise rounding with 256 * the limited PLL settings on the SM501. 257 */ 258 259 static unsigned long sm501fb_ps_to_hz(unsigned long psvalue) 260 { 261 unsigned long long numerator=1000000000000ULL; 262 263 /* 10^12 / picosecond period gives frequency in Hz */ 264 do_div(numerator, psvalue); 265 return (unsigned long)numerator; 266 } 267 268 /* sm501fb_hz_to_ps is identical to the opposite transform */ 269 270 #define sm501fb_hz_to_ps(x) sm501fb_ps_to_hz(x) 271 272 /* sm501fb_setup_gamma 273 * 274 * Programs a linear 1.0 gamma ramp in case the gamma 275 * correction is enabled without programming anything else. 276 */ 277 278 static void sm501fb_setup_gamma(struct sm501fb_info *fbi, 279 unsigned long palette) 280 { 281 unsigned long value = 0; 282 int offset; 283 284 /* set gamma values */ 285 for (offset = 0; offset < 256 * 4; offset += 4) { 286 smc501_writel(value, fbi->regs + palette + offset); 287 value += 0x010101; /* Advance RGB by 1,1,1.*/ 288 } 289 } 290 291 /* sm501fb_check_var 292 * 293 * check common variables for both panel and crt 294 */ 295 296 static int sm501fb_check_var(struct fb_var_screeninfo *var, 297 struct fb_info *info) 298 { 299 struct sm501fb_par *par = info->par; 300 struct sm501fb_info *sm = par->info; 301 unsigned long tmp; 302 303 /* check we can fit these values into the registers */ 304 305 if (var->hsync_len > 255 || var->vsync_len > 63) 306 return -EINVAL; 307 308 /* hdisplay end and hsync start */ 309 if ((var->xres + var->right_margin) > 4096) 310 return -EINVAL; 311 312 /* vdisplay end and vsync start */ 313 if ((var->yres + var->lower_margin) > 2048) 314 return -EINVAL; 315 316 /* hard limits of device */ 317 318 if (h_total(var) > 4096 || v_total(var) > 2048) 319 return -EINVAL; 320 321 /* check our line length is going to be 128 bit aligned */ 322 323 tmp = (var->xres * var->bits_per_pixel) / 8; 324 if ((tmp & 15) != 0) 325 return -EINVAL; 326 327 /* check the virtual size */ 328 329 if (var->xres_virtual > 4096 || var->yres_virtual > 2048) 330 return -EINVAL; 331 332 /* can cope with 8,16 or 32bpp */ 333 334 if (var->bits_per_pixel <= 8) 335 var->bits_per_pixel = 8; 336 else if (var->bits_per_pixel <= 16) 337 var->bits_per_pixel = 16; 338 else if (var->bits_per_pixel == 24) 339 var->bits_per_pixel = 32; 340 341 /* set r/g/b positions and validate bpp */ 342 switch(var->bits_per_pixel) { 343 case 8: 344 var->red.length = var->bits_per_pixel; 345 var->red.offset = 0; 346 var->green.length = var->bits_per_pixel; 347 var->green.offset = 0; 348 var->blue.length = var->bits_per_pixel; 349 var->blue.offset = 0; 350 var->transp.length = 0; 351 var->transp.offset = 0; 352 353 break; 354 355 case 16: 356 if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) { 357 var->blue.offset = 11; 358 var->green.offset = 5; 359 var->red.offset = 0; 360 } else { 361 var->red.offset = 11; 362 var->green.offset = 5; 363 var->blue.offset = 0; 364 } 365 var->transp.offset = 0; 366 367 var->red.length = 5; 368 var->green.length = 6; 369 var->blue.length = 5; 370 var->transp.length = 0; 371 break; 372 373 case 32: 374 if (sm->pdata->flags & SM501_FBPD_SWAP_FB_ENDIAN) { 375 var->transp.offset = 0; 376 var->red.offset = 8; 377 var->green.offset = 16; 378 var->blue.offset = 24; 379 } else { 380 var->transp.offset = 24; 381 var->red.offset = 16; 382 var->green.offset = 8; 383 var->blue.offset = 0; 384 } 385 386 var->red.length = 8; 387 var->green.length = 8; 388 var->blue.length = 8; 389 var->transp.length = 0; 390 break; 391 392 default: 393 return -EINVAL; 394 } 395 396 return 0; 397 } 398 399 /* 400 * sm501fb_check_var_crt(): 401 * 402 * check the parameters for the CRT head, and either bring them 403 * back into range, or return -EINVAL. 404 */ 405 406 static int sm501fb_check_var_crt(struct fb_var_screeninfo *var, 407 struct fb_info *info) 408 { 409 return sm501fb_check_var(var, info); 410 } 411 412 /* sm501fb_check_var_pnl(): 413 * 414 * check the parameters for the CRT head, and either bring them 415 * back into range, or return -EINVAL. 416 */ 417 418 static int sm501fb_check_var_pnl(struct fb_var_screeninfo *var, 419 struct fb_info *info) 420 { 421 return sm501fb_check_var(var, info); 422 } 423 424 /* sm501fb_set_par_common 425 * 426 * set common registers for framebuffers 427 */ 428 429 static int sm501fb_set_par_common(struct fb_info *info, 430 struct fb_var_screeninfo *var) 431 { 432 struct sm501fb_par *par = info->par; 433 struct sm501fb_info *fbi = par->info; 434 unsigned long pixclock; /* pixelclock in Hz */ 435 unsigned long sm501pixclock; /* pixelclock the 501 can achieve in Hz */ 436 unsigned int mem_type; 437 unsigned int clock_type; 438 unsigned int head_addr; 439 unsigned int smem_len; 440 441 dev_dbg(fbi->dev, "%s: %dx%d, bpp = %d, virtual %dx%d\n", 442 __func__, var->xres, var->yres, var->bits_per_pixel, 443 var->xres_virtual, var->yres_virtual); 444 445 switch (par->head) { 446 case HEAD_CRT: 447 mem_type = SM501_MEMF_CRT; 448 clock_type = SM501_CLOCK_V2XCLK; 449 head_addr = SM501_DC_CRT_FB_ADDR; 450 break; 451 452 case HEAD_PANEL: 453 mem_type = SM501_MEMF_PANEL; 454 clock_type = SM501_CLOCK_P2XCLK; 455 head_addr = SM501_DC_PANEL_FB_ADDR; 456 break; 457 458 default: 459 mem_type = 0; /* stop compiler warnings */ 460 head_addr = 0; 461 clock_type = 0; 462 } 463 464 switch (var->bits_per_pixel) { 465 case 8: 466 info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 467 break; 468 469 case 16: 470 info->fix.visual = FB_VISUAL_TRUECOLOR; 471 break; 472 473 case 32: 474 info->fix.visual = FB_VISUAL_TRUECOLOR; 475 break; 476 } 477 478 /* allocate fb memory within 501 */ 479 info->fix.line_length = (var->xres_virtual * var->bits_per_pixel)/8; 480 smem_len = info->fix.line_length * var->yres_virtual; 481 482 dev_dbg(fbi->dev, "%s: line length = %u\n", __func__, 483 info->fix.line_length); 484 485 if (sm501_alloc_mem(fbi, &par->screen, mem_type, smem_len, smem_len)) { 486 dev_err(fbi->dev, "no memory available\n"); 487 return -ENOMEM; 488 } 489 490 mutex_lock(&info->mm_lock); 491 info->fix.smem_start = fbi->fbmem_res->start + par->screen.sm_addr; 492 info->fix.smem_len = smem_len; 493 mutex_unlock(&info->mm_lock); 494 495 info->screen_base = fbi->fbmem + par->screen.sm_addr; 496 info->screen_size = info->fix.smem_len; 497 498 /* set start of framebuffer to the screen */ 499 500 smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP, 501 fbi->regs + head_addr); 502 503 /* program CRT clock */ 504 505 pixclock = sm501fb_ps_to_hz(var->pixclock); 506 507 sm501pixclock = sm501_set_clock(fbi->dev->parent, clock_type, 508 pixclock); 509 510 /* update fb layer with actual clock used */ 511 var->pixclock = sm501fb_hz_to_ps(sm501pixclock); 512 513 dev_dbg(fbi->dev, "%s: pixclock(ps) = %u, pixclock(Hz) = %lu, " 514 "sm501pixclock = %lu, error = %ld%%\n", 515 __func__, var->pixclock, pixclock, sm501pixclock, 516 ((pixclock - sm501pixclock)*100)/pixclock); 517 518 return 0; 519 } 520 521 /* sm501fb_set_par_geometry 522 * 523 * set the geometry registers for specified framebuffer. 524 */ 525 526 static void sm501fb_set_par_geometry(struct fb_info *info, 527 struct fb_var_screeninfo *var) 528 { 529 struct sm501fb_par *par = info->par; 530 struct sm501fb_info *fbi = par->info; 531 void __iomem *base = fbi->regs; 532 unsigned long reg; 533 534 if (par->head == HEAD_CRT) 535 base += SM501_DC_CRT_H_TOT; 536 else 537 base += SM501_DC_PANEL_H_TOT; 538 539 /* set framebuffer width and display width */ 540 541 reg = info->fix.line_length; 542 reg |= ((var->xres * var->bits_per_pixel)/8) << 16; 543 544 smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ? 545 SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET)); 546 547 /* program horizontal total */ 548 549 reg = (h_total(var) - 1) << 16; 550 reg |= (var->xres - 1); 551 552 smc501_writel(reg, base + SM501_OFF_DC_H_TOT); 553 554 /* program horizontal sync */ 555 556 reg = var->hsync_len << 16; 557 reg |= var->xres + var->right_margin - 1; 558 559 smc501_writel(reg, base + SM501_OFF_DC_H_SYNC); 560 561 /* program vertical total */ 562 563 reg = (v_total(var) - 1) << 16; 564 reg |= (var->yres - 1); 565 566 smc501_writel(reg, base + SM501_OFF_DC_V_TOT); 567 568 /* program vertical sync */ 569 reg = var->vsync_len << 16; 570 reg |= var->yres + var->lower_margin - 1; 571 572 smc501_writel(reg, base + SM501_OFF_DC_V_SYNC); 573 } 574 575 /* sm501fb_pan_crt 576 * 577 * pan the CRT display output within an virtual framebuffer 578 */ 579 580 static int sm501fb_pan_crt(struct fb_var_screeninfo *var, 581 struct fb_info *info) 582 { 583 struct sm501fb_par *par = info->par; 584 struct sm501fb_info *fbi = par->info; 585 unsigned int bytes_pixel = info->var.bits_per_pixel / 8; 586 unsigned long reg; 587 unsigned long xoffs; 588 589 xoffs = var->xoffset * bytes_pixel; 590 591 reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); 592 593 reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK; 594 reg |= ((xoffs & 15) / bytes_pixel) << 4; 595 smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL); 596 597 reg = (par->screen.sm_addr + xoffs + 598 var->yoffset * info->fix.line_length); 599 smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR); 600 601 sm501fb_sync_regs(fbi); 602 return 0; 603 } 604 605 /* sm501fb_pan_pnl 606 * 607 * pan the panel display output within an virtual framebuffer 608 */ 609 610 static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, 611 struct fb_info *info) 612 { 613 struct sm501fb_par *par = info->par; 614 struct sm501fb_info *fbi = par->info; 615 unsigned long reg; 616 617 reg = var->xoffset | (info->var.xres_virtual << 16); 618 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); 619 620 reg = var->yoffset | (info->var.yres_virtual << 16); 621 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); 622 623 sm501fb_sync_regs(fbi); 624 return 0; 625 } 626 627 /* sm501fb_set_par_crt 628 * 629 * Set the CRT video mode from the fb_info structure 630 */ 631 632 static int sm501fb_set_par_crt(struct fb_info *info) 633 { 634 struct sm501fb_par *par = info->par; 635 struct sm501fb_info *fbi = par->info; 636 struct fb_var_screeninfo *var = &info->var; 637 unsigned long control; /* control register */ 638 int ret; 639 640 /* activate new configuration */ 641 642 dev_dbg(fbi->dev, "%s(%p)\n", __func__, info); 643 644 /* enable CRT DAC - note 0 is on!*/ 645 sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); 646 647 control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); 648 649 control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK | 650 SM501_DC_CRT_CONTROL_GAMMA | 651 SM501_DC_CRT_CONTROL_BLANK | 652 SM501_DC_CRT_CONTROL_SEL | 653 SM501_DC_CRT_CONTROL_CP | 654 SM501_DC_CRT_CONTROL_TVP); 655 656 /* set the sync polarities before we check data source */ 657 658 if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0) 659 control |= SM501_DC_CRT_CONTROL_HSP; 660 661 if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) 662 control |= SM501_DC_CRT_CONTROL_VSP; 663 664 if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { 665 /* the head is displaying panel data... */ 666 667 sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0, 668 info->fix.smem_len); 669 goto out_update; 670 } 671 672 ret = sm501fb_set_par_common(info, var); 673 if (ret) { 674 dev_err(fbi->dev, "failed to set common parameters\n"); 675 return ret; 676 } 677 678 sm501fb_pan_crt(var, info); 679 sm501fb_set_par_geometry(info, var); 680 681 control |= SM501_FIFO_3; /* fill if >3 free slots */ 682 683 switch(var->bits_per_pixel) { 684 case 8: 685 control |= SM501_DC_CRT_CONTROL_8BPP; 686 break; 687 688 case 16: 689 control |= SM501_DC_CRT_CONTROL_16BPP; 690 sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE); 691 break; 692 693 case 32: 694 control |= SM501_DC_CRT_CONTROL_32BPP; 695 sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE); 696 break; 697 698 default: 699 BUG(); 700 } 701 702 control |= SM501_DC_CRT_CONTROL_SEL; /* CRT displays CRT data */ 703 control |= SM501_DC_CRT_CONTROL_TE; /* enable CRT timing */ 704 control |= SM501_DC_CRT_CONTROL_ENABLE; /* enable CRT plane */ 705 706 out_update: 707 dev_dbg(fbi->dev, "new control is %08lx\n", control); 708 709 smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL); 710 sm501fb_sync_regs(fbi); 711 712 return 0; 713 } 714 715 static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) 716 { 717 unsigned long control; 718 void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; 719 struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; 720 721 control = smc501_readl(ctrl_reg); 722 723 if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { 724 /* enable panel power */ 725 726 control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ 727 smc501_writel(control, ctrl_reg); 728 sm501fb_sync_regs(fbi); 729 mdelay(10); 730 731 control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ 732 smc501_writel(control, ctrl_reg); 733 sm501fb_sync_regs(fbi); 734 mdelay(10); 735 736 /* VBIASEN */ 737 738 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { 739 if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) 740 control &= ~SM501_DC_PANEL_CONTROL_BIAS; 741 else 742 control |= SM501_DC_PANEL_CONTROL_BIAS; 743 744 smc501_writel(control, ctrl_reg); 745 sm501fb_sync_regs(fbi); 746 mdelay(10); 747 } 748 749 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { 750 if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) 751 control &= ~SM501_DC_PANEL_CONTROL_FPEN; 752 else 753 control |= SM501_DC_PANEL_CONTROL_FPEN; 754 755 smc501_writel(control, ctrl_reg); 756 sm501fb_sync_regs(fbi); 757 mdelay(10); 758 } 759 } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { 760 /* disable panel power */ 761 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { 762 if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) 763 control |= SM501_DC_PANEL_CONTROL_FPEN; 764 else 765 control &= ~SM501_DC_PANEL_CONTROL_FPEN; 766 767 smc501_writel(control, ctrl_reg); 768 sm501fb_sync_regs(fbi); 769 mdelay(10); 770 } 771 772 if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { 773 if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) 774 control |= SM501_DC_PANEL_CONTROL_BIAS; 775 else 776 control &= ~SM501_DC_PANEL_CONTROL_BIAS; 777 778 smc501_writel(control, ctrl_reg); 779 sm501fb_sync_regs(fbi); 780 mdelay(10); 781 } 782 783 control &= ~SM501_DC_PANEL_CONTROL_DATA; 784 smc501_writel(control, ctrl_reg); 785 sm501fb_sync_regs(fbi); 786 mdelay(10); 787 788 control &= ~SM501_DC_PANEL_CONTROL_VDD; 789 smc501_writel(control, ctrl_reg); 790 sm501fb_sync_regs(fbi); 791 mdelay(10); 792 } 793 794 sm501fb_sync_regs(fbi); 795 } 796 797 /* sm501fb_set_par_pnl 798 * 799 * Set the panel video mode from the fb_info structure 800 */ 801 802 static int sm501fb_set_par_pnl(struct fb_info *info) 803 { 804 struct sm501fb_par *par = info->par; 805 struct sm501fb_info *fbi = par->info; 806 struct fb_var_screeninfo *var = &info->var; 807 unsigned long control; 808 unsigned long reg; 809 int ret; 810 811 dev_dbg(fbi->dev, "%s(%p)\n", __func__, info); 812 813 /* activate this new configuration */ 814 815 ret = sm501fb_set_par_common(info, var); 816 if (ret) 817 return ret; 818 819 sm501fb_pan_pnl(var, info); 820 sm501fb_set_par_geometry(info, var); 821 822 /* update control register */ 823 824 control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL); 825 control &= (SM501_DC_PANEL_CONTROL_GAMMA | 826 SM501_DC_PANEL_CONTROL_VDD | 827 SM501_DC_PANEL_CONTROL_DATA | 828 SM501_DC_PANEL_CONTROL_BIAS | 829 SM501_DC_PANEL_CONTROL_FPEN | 830 SM501_DC_PANEL_CONTROL_CP | 831 SM501_DC_PANEL_CONTROL_CK | 832 SM501_DC_PANEL_CONTROL_HP | 833 SM501_DC_PANEL_CONTROL_VP | 834 SM501_DC_PANEL_CONTROL_HPD | 835 SM501_DC_PANEL_CONTROL_VPD); 836 837 control |= SM501_FIFO_3; /* fill if >3 free slots */ 838 839 switch(var->bits_per_pixel) { 840 case 8: 841 control |= SM501_DC_PANEL_CONTROL_8BPP; 842 break; 843 844 case 16: 845 control |= SM501_DC_PANEL_CONTROL_16BPP; 846 sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE); 847 break; 848 849 case 32: 850 control |= SM501_DC_PANEL_CONTROL_32BPP; 851 sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE); 852 break; 853 854 default: 855 BUG(); 856 } 857 858 smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL); 859 860 /* panel plane top left and bottom right location */ 861 862 smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC); 863 864 reg = var->xres - 1; 865 reg |= (var->yres - 1) << 16; 866 867 smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC); 868 869 /* program panel control register */ 870 871 control |= SM501_DC_PANEL_CONTROL_TE; /* enable PANEL timing */ 872 control |= SM501_DC_PANEL_CONTROL_EN; /* enable PANEL gfx plane */ 873 874 if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0) 875 control |= SM501_DC_PANEL_CONTROL_HSP; 876 877 if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) 878 control |= SM501_DC_PANEL_CONTROL_VSP; 879 880 smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL); 881 sm501fb_sync_regs(fbi); 882 883 /* ensure the panel interface is not tristated at this point */ 884 885 sm501_modify_reg(fbi->dev->parent, SM501_SYSTEM_CONTROL, 886 0, SM501_SYSCTRL_PANEL_TRISTATE); 887 888 /* power the panel up */ 889 sm501fb_panel_power(fbi, 1); 890 return 0; 891 } 892 893 894 /* chan_to_field 895 * 896 * convert a colour value into a field position 897 * 898 * from pxafb.c 899 */ 900 901 static inline unsigned int chan_to_field(unsigned int chan, 902 struct fb_bitfield *bf) 903 { 904 chan &= 0xffff; 905 chan >>= 16 - bf->length; 906 return chan << bf->offset; 907 } 908 909 /* sm501fb_setcolreg 910 * 911 * set the colour mapping for modes that support palettised data 912 */ 913 914 static int sm501fb_setcolreg(unsigned regno, 915 unsigned red, unsigned green, unsigned blue, 916 unsigned transp, struct fb_info *info) 917 { 918 struct sm501fb_par *par = info->par; 919 struct sm501fb_info *fbi = par->info; 920 void __iomem *base = fbi->regs; 921 unsigned int val; 922 923 if (par->head == HEAD_CRT) 924 base += SM501_DC_CRT_PALETTE; 925 else 926 base += SM501_DC_PANEL_PALETTE; 927 928 switch (info->fix.visual) { 929 case FB_VISUAL_TRUECOLOR: 930 /* true-colour, use pseuo-palette */ 931 932 if (regno < 16) { 933 u32 *pal = par->pseudo_palette; 934 935 val = chan_to_field(red, &info->var.red); 936 val |= chan_to_field(green, &info->var.green); 937 val |= chan_to_field(blue, &info->var.blue); 938 939 pal[regno] = val; 940 } 941 break; 942 943 case FB_VISUAL_PSEUDOCOLOR: 944 if (regno < 256) { 945 val = (red >> 8) << 16; 946 val |= (green >> 8) << 8; 947 val |= blue >> 8; 948 949 smc501_writel(val, base + (regno * 4)); 950 } 951 952 break; 953 954 default: 955 return 1; /* unknown type */ 956 } 957 958 return 0; 959 } 960 961 /* sm501fb_blank_pnl 962 * 963 * Blank or un-blank the panel interface 964 */ 965 966 static int sm501fb_blank_pnl(int blank_mode, struct fb_info *info) 967 { 968 struct sm501fb_par *par = info->par; 969 struct sm501fb_info *fbi = par->info; 970 971 dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info); 972 973 switch (blank_mode) { 974 case FB_BLANK_POWERDOWN: 975 sm501fb_panel_power(fbi, 0); 976 break; 977 978 case FB_BLANK_UNBLANK: 979 sm501fb_panel_power(fbi, 1); 980 break; 981 982 case FB_BLANK_NORMAL: 983 case FB_BLANK_VSYNC_SUSPEND: 984 case FB_BLANK_HSYNC_SUSPEND: 985 default: 986 return 1; 987 } 988 989 return 0; 990 } 991 992 /* sm501fb_blank_crt 993 * 994 * Blank or un-blank the crt interface 995 */ 996 997 static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) 998 { 999 struct sm501fb_par *par = info->par; 1000 struct sm501fb_info *fbi = par->info; 1001 unsigned long ctrl; 1002 1003 dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info); 1004 1005 ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL); 1006 1007 switch (blank_mode) { 1008 case FB_BLANK_POWERDOWN: 1009 ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE; 1010 sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0); 1011 /* fall through */ 1012 1013 case FB_BLANK_NORMAL: 1014 ctrl |= SM501_DC_CRT_CONTROL_BLANK; 1015 break; 1016 1017 case FB_BLANK_UNBLANK: 1018 ctrl &= ~SM501_DC_CRT_CONTROL_BLANK; 1019 ctrl |= SM501_DC_CRT_CONTROL_ENABLE; 1020 sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); 1021 break; 1022 1023 case FB_BLANK_VSYNC_SUSPEND: 1024 case FB_BLANK_HSYNC_SUSPEND: 1025 default: 1026 return 1; 1027 1028 } 1029 1030 smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL); 1031 sm501fb_sync_regs(fbi); 1032 1033 return 0; 1034 } 1035 1036 /* sm501fb_cursor 1037 * 1038 * set or change the hardware cursor parameters 1039 */ 1040 1041 static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 1042 { 1043 struct sm501fb_par *par = info->par; 1044 struct sm501fb_info *fbi = par->info; 1045 void __iomem *base = fbi->regs; 1046 unsigned long hwc_addr; 1047 unsigned long fg, bg; 1048 1049 dev_dbg(fbi->dev, "%s(%p,%p)\n", __func__, info, cursor); 1050 1051 if (par->head == HEAD_CRT) 1052 base += SM501_DC_CRT_HWC_BASE; 1053 else 1054 base += SM501_DC_PANEL_HWC_BASE; 1055 1056 /* check not being asked to exceed capabilities */ 1057 1058 if (cursor->image.width > 64) 1059 return -EINVAL; 1060 1061 if (cursor->image.height > 64) 1062 return -EINVAL; 1063 1064 if (cursor->image.depth > 1) 1065 return -EINVAL; 1066 1067 hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR); 1068 1069 if (cursor->enable) 1070 smc501_writel(hwc_addr | SM501_HWC_EN, 1071 base + SM501_OFF_HWC_ADDR); 1072 else 1073 smc501_writel(hwc_addr & ~SM501_HWC_EN, 1074 base + SM501_OFF_HWC_ADDR); 1075 1076 /* set data */ 1077 if (cursor->set & FB_CUR_SETPOS) { 1078 unsigned int x = cursor->image.dx; 1079 unsigned int y = cursor->image.dy; 1080 1081 if (x >= 2048 || y >= 2048 ) 1082 return -EINVAL; 1083 1084 dev_dbg(fbi->dev, "set position %d,%d\n", x, y); 1085 1086 //y += cursor->image.height; 1087 1088 smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC); 1089 } 1090 1091 if (cursor->set & FB_CUR_SETCMAP) { 1092 unsigned int bg_col = cursor->image.bg_color; 1093 unsigned int fg_col = cursor->image.fg_color; 1094 1095 dev_dbg(fbi->dev, "%s: update cmap (%08x,%08x)\n", 1096 __func__, bg_col, fg_col); 1097 1098 bg = ((info->cmap.red[bg_col] & 0xF8) << 8) | 1099 ((info->cmap.green[bg_col] & 0xFC) << 3) | 1100 ((info->cmap.blue[bg_col] & 0xF8) >> 3); 1101 1102 fg = ((info->cmap.red[fg_col] & 0xF8) << 8) | 1103 ((info->cmap.green[fg_col] & 0xFC) << 3) | 1104 ((info->cmap.blue[fg_col] & 0xF8) >> 3); 1105 1106 dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg); 1107 1108 smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2); 1109 smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3); 1110 } 1111 1112 if (cursor->set & FB_CUR_SETSIZE || 1113 cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE)) { 1114 /* SM501 cursor is a two bpp 64x64 bitmap this routine 1115 * clears it to transparent then combines the cursor 1116 * shape plane with the colour plane to set the 1117 * cursor */ 1118 int x, y; 1119 const unsigned char *pcol = cursor->image.data; 1120 const unsigned char *pmsk = cursor->mask; 1121 void __iomem *dst = par->cursor.k_addr; 1122 unsigned char dcol = 0; 1123 unsigned char dmsk = 0; 1124 unsigned int op; 1125 1126 dev_dbg(fbi->dev, "%s: setting shape (%d,%d)\n", 1127 __func__, cursor->image.width, cursor->image.height); 1128 1129 for (op = 0; op < (64*64*2)/8; op+=4) 1130 smc501_writel(0x0, dst + op); 1131 1132 for (y = 0; y < cursor->image.height; y++) { 1133 for (x = 0; x < cursor->image.width; x++) { 1134 if ((x % 8) == 0) { 1135 dcol = *pcol++; 1136 dmsk = *pmsk++; 1137 } else { 1138 dcol >>= 1; 1139 dmsk >>= 1; 1140 } 1141 1142 if (dmsk & 1) { 1143 op = (dcol & 1) ? 1 : 3; 1144 op <<= ((x % 4) * 2); 1145 1146 op |= readb(dst + (x / 4)); 1147 writeb(op, dst + (x / 4)); 1148 } 1149 } 1150 dst += (64*2)/8; 1151 } 1152 } 1153 1154 sm501fb_sync_regs(fbi); /* ensure cursor data flushed */ 1155 return 0; 1156 } 1157 1158 /* sm501fb_crtsrc_show 1159 * 1160 * device attribute code to show where the crt output is sourced from 1161 */ 1162 1163 static ssize_t sm501fb_crtsrc_show(struct device *dev, 1164 struct device_attribute *attr, char *buf) 1165 { 1166 struct sm501fb_info *info = dev_get_drvdata(dev); 1167 unsigned long ctrl; 1168 1169 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 1170 ctrl &= SM501_DC_CRT_CONTROL_SEL; 1171 1172 return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel"); 1173 } 1174 1175 /* sm501fb_crtsrc_show 1176 * 1177 * device attribute code to set where the crt output is sourced from 1178 */ 1179 1180 static ssize_t sm501fb_crtsrc_store(struct device *dev, 1181 struct device_attribute *attr, 1182 const char *buf, size_t len) 1183 { 1184 struct sm501fb_info *info = dev_get_drvdata(dev); 1185 enum sm501_controller head; 1186 unsigned long ctrl; 1187 1188 if (len < 1) 1189 return -EINVAL; 1190 1191 if (strncasecmp(buf, "crt", 3) == 0) 1192 head = HEAD_CRT; 1193 else if (strncasecmp(buf, "panel", 5) == 0) 1194 head = HEAD_PANEL; 1195 else 1196 return -EINVAL; 1197 1198 dev_info(dev, "setting crt source to head %d\n", head); 1199 1200 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 1201 1202 if (head == HEAD_CRT) { 1203 ctrl |= SM501_DC_CRT_CONTROL_SEL; 1204 ctrl |= SM501_DC_CRT_CONTROL_ENABLE; 1205 ctrl |= SM501_DC_CRT_CONTROL_TE; 1206 } else { 1207 ctrl &= ~SM501_DC_CRT_CONTROL_SEL; 1208 ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE; 1209 ctrl &= ~SM501_DC_CRT_CONTROL_TE; 1210 } 1211 1212 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1213 sm501fb_sync_regs(info); 1214 1215 return len; 1216 } 1217 1218 /* Prepare the device_attr for registration with sysfs later */ 1219 static DEVICE_ATTR(crt_src, 0664, sm501fb_crtsrc_show, sm501fb_crtsrc_store); 1220 1221 /* sm501fb_show_regs 1222 * 1223 * show the primary sm501 registers 1224 */ 1225 static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr, 1226 unsigned int start, unsigned int len) 1227 { 1228 void __iomem *mem = info->regs; 1229 char *buf = ptr; 1230 unsigned int reg; 1231 1232 for (reg = start; reg < (len + start); reg += 4) 1233 ptr += sprintf(ptr, "%08x = %08x\n", reg, 1234 smc501_readl(mem + reg)); 1235 1236 return ptr - buf; 1237 } 1238 1239 /* sm501fb_debug_show_crt 1240 * 1241 * show the crt control and cursor registers 1242 */ 1243 1244 static ssize_t sm501fb_debug_show_crt(struct device *dev, 1245 struct device_attribute *attr, char *buf) 1246 { 1247 struct sm501fb_info *info = dev_get_drvdata(dev); 1248 char *ptr = buf; 1249 1250 ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_CONTROL, 0x40); 1251 ptr += sm501fb_show_regs(info, ptr, SM501_DC_CRT_HWC_BASE, 0x10); 1252 1253 return ptr - buf; 1254 } 1255 1256 static DEVICE_ATTR(fbregs_crt, 0444, sm501fb_debug_show_crt, NULL); 1257 1258 /* sm501fb_debug_show_pnl 1259 * 1260 * show the panel control and cursor registers 1261 */ 1262 1263 static ssize_t sm501fb_debug_show_pnl(struct device *dev, 1264 struct device_attribute *attr, char *buf) 1265 { 1266 struct sm501fb_info *info = dev_get_drvdata(dev); 1267 char *ptr = buf; 1268 1269 ptr += sm501fb_show_regs(info, ptr, 0x0, 0x40); 1270 ptr += sm501fb_show_regs(info, ptr, SM501_DC_PANEL_HWC_BASE, 0x10); 1271 1272 return ptr - buf; 1273 } 1274 1275 static DEVICE_ATTR(fbregs_pnl, 0444, sm501fb_debug_show_pnl, NULL); 1276 1277 /* acceleration operations */ 1278 static int sm501fb_sync(struct fb_info *info) 1279 { 1280 int count = 1000000; 1281 struct sm501fb_par *par = info->par; 1282 struct sm501fb_info *fbi = par->info; 1283 1284 /* wait for the 2d engine to be ready */ 1285 while ((count > 0) && 1286 (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) & 1287 SM501_SYSCTRL_2D_ENGINE_STATUS) != 0) 1288 count--; 1289 1290 if (count <= 0) { 1291 dev_err(info->dev, "Timeout waiting for 2d engine sync\n"); 1292 return 1; 1293 } 1294 return 0; 1295 } 1296 1297 static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 1298 { 1299 struct sm501fb_par *par = info->par; 1300 struct sm501fb_info *fbi = par->info; 1301 int width = area->width; 1302 int height = area->height; 1303 int sx = area->sx; 1304 int sy = area->sy; 1305 int dx = area->dx; 1306 int dy = area->dy; 1307 unsigned long rtl = 0; 1308 1309 /* source clip */ 1310 if ((sx >= info->var.xres_virtual) || 1311 (sy >= info->var.yres_virtual)) 1312 /* source Area not within virtual screen, skipping */ 1313 return; 1314 if ((sx + width) >= info->var.xres_virtual) 1315 width = info->var.xres_virtual - sx - 1; 1316 if ((sy + height) >= info->var.yres_virtual) 1317 height = info->var.yres_virtual - sy - 1; 1318 1319 /* dest clip */ 1320 if ((dx >= info->var.xres_virtual) || 1321 (dy >= info->var.yres_virtual)) 1322 /* Destination Area not within virtual screen, skipping */ 1323 return; 1324 if ((dx + width) >= info->var.xres_virtual) 1325 width = info->var.xres_virtual - dx - 1; 1326 if ((dy + height) >= info->var.yres_virtual) 1327 height = info->var.yres_virtual - dy - 1; 1328 1329 if ((sx < dx) || (sy < dy)) { 1330 rtl = 1 << 27; 1331 sx += width - 1; 1332 dx += width - 1; 1333 sy += height - 1; 1334 dy += height - 1; 1335 } 1336 1337 if (sm501fb_sync(info)) 1338 return; 1339 1340 /* set the base addresses */ 1341 smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); 1342 smc501_writel(par->screen.sm_addr, 1343 fbi->regs2d + SM501_2D_DESTINATION_BASE); 1344 1345 /* set the window width */ 1346 smc501_writel((info->var.xres << 16) | info->var.xres, 1347 fbi->regs2d + SM501_2D_WINDOW_WIDTH); 1348 1349 /* set window stride */ 1350 smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual, 1351 fbi->regs2d + SM501_2D_PITCH); 1352 1353 /* set data format */ 1354 switch (info->var.bits_per_pixel) { 1355 case 8: 1356 smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH); 1357 break; 1358 case 16: 1359 smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); 1360 break; 1361 case 32: 1362 smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); 1363 break; 1364 } 1365 1366 /* 2d compare mask */ 1367 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); 1368 1369 /* 2d mask */ 1370 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); 1371 1372 /* source and destination x y */ 1373 smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE); 1374 smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION); 1375 1376 /* w/h */ 1377 smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); 1378 1379 /* do area move */ 1380 smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL); 1381 } 1382 1383 static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 1384 { 1385 struct sm501fb_par *par = info->par; 1386 struct sm501fb_info *fbi = par->info; 1387 int width = rect->width, height = rect->height; 1388 1389 if ((rect->dx >= info->var.xres_virtual) || 1390 (rect->dy >= info->var.yres_virtual)) 1391 /* Rectangle not within virtual screen, skipping */ 1392 return; 1393 if ((rect->dx + width) >= info->var.xres_virtual) 1394 width = info->var.xres_virtual - rect->dx - 1; 1395 if ((rect->dy + height) >= info->var.yres_virtual) 1396 height = info->var.yres_virtual - rect->dy - 1; 1397 1398 if (sm501fb_sync(info)) 1399 return; 1400 1401 /* set the base addresses */ 1402 smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE); 1403 smc501_writel(par->screen.sm_addr, 1404 fbi->regs2d + SM501_2D_DESTINATION_BASE); 1405 1406 /* set the window width */ 1407 smc501_writel((info->var.xres << 16) | info->var.xres, 1408 fbi->regs2d + SM501_2D_WINDOW_WIDTH); 1409 1410 /* set window stride */ 1411 smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual, 1412 fbi->regs2d + SM501_2D_PITCH); 1413 1414 /* set data format */ 1415 switch (info->var.bits_per_pixel) { 1416 case 8: 1417 smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH); 1418 break; 1419 case 16: 1420 smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH); 1421 break; 1422 case 32: 1423 smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH); 1424 break; 1425 } 1426 1427 /* 2d compare mask */ 1428 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK); 1429 1430 /* 2d mask */ 1431 smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK); 1432 1433 /* colour */ 1434 smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND); 1435 1436 /* x y */ 1437 smc501_writel((rect->dx << 16) | rect->dy, 1438 fbi->regs2d + SM501_2D_DESTINATION); 1439 1440 /* w/h */ 1441 smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION); 1442 1443 /* do rectangle fill */ 1444 smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL); 1445 } 1446 1447 1448 static struct fb_ops sm501fb_ops_crt = { 1449 .owner = THIS_MODULE, 1450 .fb_check_var = sm501fb_check_var_crt, 1451 .fb_set_par = sm501fb_set_par_crt, 1452 .fb_blank = sm501fb_blank_crt, 1453 .fb_setcolreg = sm501fb_setcolreg, 1454 .fb_pan_display = sm501fb_pan_crt, 1455 .fb_cursor = sm501fb_cursor, 1456 .fb_fillrect = sm501fb_fillrect, 1457 .fb_copyarea = sm501fb_copyarea, 1458 .fb_imageblit = cfb_imageblit, 1459 .fb_sync = sm501fb_sync, 1460 }; 1461 1462 static struct fb_ops sm501fb_ops_pnl = { 1463 .owner = THIS_MODULE, 1464 .fb_check_var = sm501fb_check_var_pnl, 1465 .fb_set_par = sm501fb_set_par_pnl, 1466 .fb_pan_display = sm501fb_pan_pnl, 1467 .fb_blank = sm501fb_blank_pnl, 1468 .fb_setcolreg = sm501fb_setcolreg, 1469 .fb_cursor = sm501fb_cursor, 1470 .fb_fillrect = sm501fb_fillrect, 1471 .fb_copyarea = sm501fb_copyarea, 1472 .fb_imageblit = cfb_imageblit, 1473 .fb_sync = sm501fb_sync, 1474 }; 1475 1476 /* sm501_init_cursor 1477 * 1478 * initialise hw cursor parameters 1479 */ 1480 1481 static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base) 1482 { 1483 struct sm501fb_par *par; 1484 struct sm501fb_info *info; 1485 int ret; 1486 1487 if (fbi == NULL) 1488 return 0; 1489 1490 par = fbi->par; 1491 info = par->info; 1492 1493 par->cursor_regs = info->regs + reg_base; 1494 1495 ret = sm501_alloc_mem(info, &par->cursor, SM501_MEMF_CURSOR, 1024, 1496 fbi->fix.smem_len); 1497 if (ret < 0) 1498 return ret; 1499 1500 /* initialise the colour registers */ 1501 1502 smc501_writel(par->cursor.sm_addr, 1503 par->cursor_regs + SM501_OFF_HWC_ADDR); 1504 1505 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC); 1506 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2); 1507 smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3); 1508 sm501fb_sync_regs(info); 1509 1510 return 0; 1511 } 1512 1513 /* sm501fb_info_start 1514 * 1515 * fills the par structure claiming resources and remapping etc. 1516 */ 1517 1518 static int sm501fb_start(struct sm501fb_info *info, 1519 struct platform_device *pdev) 1520 { 1521 struct resource *res; 1522 struct device *dev = &pdev->dev; 1523 int k; 1524 int ret; 1525 1526 info->irq = ret = platform_get_irq(pdev, 0); 1527 if (ret < 0) { 1528 /* we currently do not use the IRQ */ 1529 dev_warn(dev, "no irq for device\n"); 1530 } 1531 1532 /* allocate, reserve and remap resources for display 1533 * controller registers */ 1534 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1535 if (res == NULL) { 1536 dev_err(dev, "no resource definition for registers\n"); 1537 ret = -ENOENT; 1538 goto err_release; 1539 } 1540 1541 info->regs_res = request_mem_region(res->start, 1542 resource_size(res), 1543 pdev->name); 1544 1545 if (info->regs_res == NULL) { 1546 dev_err(dev, "cannot claim registers\n"); 1547 ret = -ENXIO; 1548 goto err_release; 1549 } 1550 1551 info->regs = ioremap(res->start, resource_size(res)); 1552 if (info->regs == NULL) { 1553 dev_err(dev, "cannot remap registers\n"); 1554 ret = -ENXIO; 1555 goto err_regs_res; 1556 } 1557 1558 /* allocate, reserve and remap resources for 2d 1559 * controller registers */ 1560 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1561 if (res == NULL) { 1562 dev_err(dev, "no resource definition for 2d registers\n"); 1563 ret = -ENOENT; 1564 goto err_regs_map; 1565 } 1566 1567 info->regs2d_res = request_mem_region(res->start, 1568 resource_size(res), 1569 pdev->name); 1570 1571 if (info->regs2d_res == NULL) { 1572 dev_err(dev, "cannot claim registers\n"); 1573 ret = -ENXIO; 1574 goto err_regs_map; 1575 } 1576 1577 info->regs2d = ioremap(res->start, resource_size(res)); 1578 if (info->regs2d == NULL) { 1579 dev_err(dev, "cannot remap registers\n"); 1580 ret = -ENXIO; 1581 goto err_regs2d_res; 1582 } 1583 1584 /* allocate, reserve resources for framebuffer */ 1585 res = platform_get_resource(pdev, IORESOURCE_MEM, 2); 1586 if (res == NULL) { 1587 dev_err(dev, "no memory resource defined\n"); 1588 ret = -ENXIO; 1589 goto err_regs2d_map; 1590 } 1591 1592 info->fbmem_res = request_mem_region(res->start, 1593 resource_size(res), 1594 pdev->name); 1595 if (info->fbmem_res == NULL) { 1596 dev_err(dev, "cannot claim framebuffer\n"); 1597 ret = -ENXIO; 1598 goto err_regs2d_map; 1599 } 1600 1601 info->fbmem = ioremap(res->start, resource_size(res)); 1602 if (info->fbmem == NULL) { 1603 dev_err(dev, "cannot remap framebuffer\n"); 1604 ret = -ENXIO; 1605 goto err_mem_res; 1606 } 1607 1608 info->fbmem_len = resource_size(res); 1609 1610 /* clear framebuffer memory - avoids garbage data on unused fb */ 1611 memset_io(info->fbmem, 0, info->fbmem_len); 1612 1613 /* clear palette ram - undefined at power on */ 1614 for (k = 0; k < (256 * 3); k++) 1615 smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); 1616 1617 /* enable display controller */ 1618 sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); 1619 1620 /* enable 2d controller */ 1621 sm501_unit_power(dev->parent, SM501_GATE_2D_ENGINE, 1); 1622 1623 /* setup cursors */ 1624 sm501_init_cursor(info->fb[HEAD_CRT], SM501_DC_CRT_HWC_ADDR); 1625 sm501_init_cursor(info->fb[HEAD_PANEL], SM501_DC_PANEL_HWC_ADDR); 1626 1627 return 0; /* everything is setup */ 1628 1629 err_mem_res: 1630 release_mem_region(info->fbmem_res->start, 1631 resource_size(info->fbmem_res)); 1632 1633 err_regs2d_map: 1634 iounmap(info->regs2d); 1635 1636 err_regs2d_res: 1637 release_mem_region(info->regs2d_res->start, 1638 resource_size(info->regs2d_res)); 1639 1640 err_regs_map: 1641 iounmap(info->regs); 1642 1643 err_regs_res: 1644 release_mem_region(info->regs_res->start, 1645 resource_size(info->regs_res)); 1646 1647 err_release: 1648 return ret; 1649 } 1650 1651 static void sm501fb_stop(struct sm501fb_info *info) 1652 { 1653 /* disable display controller */ 1654 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0); 1655 1656 iounmap(info->fbmem); 1657 release_mem_region(info->fbmem_res->start, 1658 resource_size(info->fbmem_res)); 1659 1660 iounmap(info->regs2d); 1661 release_mem_region(info->regs2d_res->start, 1662 resource_size(info->regs2d_res)); 1663 1664 iounmap(info->regs); 1665 release_mem_region(info->regs_res->start, 1666 resource_size(info->regs_res)); 1667 } 1668 1669 static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, 1670 const char *fbname) 1671 { 1672 struct sm501_platdata_fbsub *pd; 1673 struct sm501fb_par *par = fb->par; 1674 struct sm501fb_info *info = par->info; 1675 unsigned long ctrl; 1676 unsigned int enable; 1677 int ret; 1678 1679 switch (head) { 1680 case HEAD_CRT: 1681 pd = info->pdata->fb_crt; 1682 ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 1683 enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0; 1684 1685 /* ensure we set the correct source register */ 1686 if (info->pdata->fb_route != SM501_FB_CRT_PANEL) { 1687 ctrl |= SM501_DC_CRT_CONTROL_SEL; 1688 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1689 } 1690 1691 break; 1692 1693 case HEAD_PANEL: 1694 pd = info->pdata->fb_pnl; 1695 ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL); 1696 enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0; 1697 break; 1698 1699 default: 1700 pd = NULL; /* stop compiler warnings */ 1701 ctrl = 0; 1702 enable = 0; 1703 BUG(); 1704 } 1705 1706 dev_info(info->dev, "fb %s %sabled at start\n", 1707 fbname, enable ? "en" : "dis"); 1708 1709 /* check to see if our routing allows this */ 1710 1711 if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) { 1712 ctrl &= ~SM501_DC_CRT_CONTROL_SEL; 1713 smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL); 1714 enable = 0; 1715 } 1716 1717 strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id)); 1718 1719 memcpy(&par->ops, 1720 (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl, 1721 sizeof(struct fb_ops)); 1722 1723 /* update ops dependent on what we've been passed */ 1724 1725 if ((pd->flags & SM501FB_FLAG_USE_HWCURSOR) == 0) 1726 par->ops.fb_cursor = NULL; 1727 1728 fb->fbops = &par->ops; 1729 fb->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST | 1730 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | 1731 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; 1732 1733 #if defined(CONFIG_OF) 1734 #ifdef __BIG_ENDIAN 1735 if (of_get_property(info->dev->parent->of_node, "little-endian", NULL)) 1736 fb->flags |= FBINFO_FOREIGN_ENDIAN; 1737 #else 1738 if (of_get_property(info->dev->parent->of_node, "big-endian", NULL)) 1739 fb->flags |= FBINFO_FOREIGN_ENDIAN; 1740 #endif 1741 #endif 1742 /* fixed data */ 1743 1744 fb->fix.type = FB_TYPE_PACKED_PIXELS; 1745 fb->fix.type_aux = 0; 1746 fb->fix.xpanstep = 1; 1747 fb->fix.ypanstep = 1; 1748 fb->fix.ywrapstep = 0; 1749 fb->fix.accel = FB_ACCEL_NONE; 1750 1751 /* screenmode */ 1752 1753 fb->var.nonstd = 0; 1754 fb->var.activate = FB_ACTIVATE_NOW; 1755 fb->var.accel_flags = 0; 1756 fb->var.vmode = FB_VMODE_NONINTERLACED; 1757 fb->var.bits_per_pixel = 16; 1758 1759 if (info->edid_data) { 1760 /* Now build modedb from EDID */ 1761 fb_edid_to_monspecs(info->edid_data, &fb->monspecs); 1762 fb_videomode_to_modelist(fb->monspecs.modedb, 1763 fb->monspecs.modedb_len, 1764 &fb->modelist); 1765 } 1766 1767 if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) { 1768 /* TODO read the mode from the current display */ 1769 } else { 1770 if (pd->def_mode) { 1771 dev_info(info->dev, "using supplied mode\n"); 1772 fb_videomode_to_var(&fb->var, pd->def_mode); 1773 1774 fb->var.bits_per_pixel = pd->def_bpp ? pd->def_bpp : 8; 1775 fb->var.xres_virtual = fb->var.xres; 1776 fb->var.yres_virtual = fb->var.yres; 1777 } else { 1778 if (info->edid_data) { 1779 ret = fb_find_mode(&fb->var, fb, fb_mode, 1780 fb->monspecs.modedb, 1781 fb->monspecs.modedb_len, 1782 &sm501_default_mode, default_bpp); 1783 /* edid_data is no longer needed, free it */ 1784 kfree(info->edid_data); 1785 } else { 1786 ret = fb_find_mode(&fb->var, fb, 1787 NULL, NULL, 0, NULL, 8); 1788 } 1789 1790 switch (ret) { 1791 case 1: 1792 dev_info(info->dev, "using mode specified in " 1793 "@mode\n"); 1794 break; 1795 case 2: 1796 dev_info(info->dev, "using mode specified in " 1797 "@mode with ignored refresh rate\n"); 1798 break; 1799 case 3: 1800 dev_info(info->dev, "using mode default " 1801 "mode\n"); 1802 break; 1803 case 4: 1804 dev_info(info->dev, "using mode from list\n"); 1805 break; 1806 default: 1807 dev_info(info->dev, "ret = %d\n", ret); 1808 dev_info(info->dev, "failed to find mode\n"); 1809 return -EINVAL; 1810 } 1811 } 1812 } 1813 1814 /* initialise and set the palette */ 1815 if (fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0)) { 1816 dev_err(info->dev, "failed to allocate cmap memory\n"); 1817 return -ENOMEM; 1818 } 1819 fb_set_cmap(&fb->cmap, fb); 1820 1821 ret = (fb->fbops->fb_check_var)(&fb->var, fb); 1822 if (ret) 1823 dev_err(info->dev, "check_var() failed on initial setup?\n"); 1824 1825 return 0; 1826 } 1827 1828 /* default platform data if none is supplied (ie, PCI device) */ 1829 1830 static struct sm501_platdata_fbsub sm501fb_pdata_crt = { 1831 .flags = (SM501FB_FLAG_USE_INIT_MODE | 1832 SM501FB_FLAG_USE_HWCURSOR | 1833 SM501FB_FLAG_USE_HWACCEL | 1834 SM501FB_FLAG_DISABLE_AT_EXIT), 1835 1836 }; 1837 1838 static struct sm501_platdata_fbsub sm501fb_pdata_pnl = { 1839 .flags = (SM501FB_FLAG_USE_INIT_MODE | 1840 SM501FB_FLAG_USE_HWCURSOR | 1841 SM501FB_FLAG_USE_HWACCEL | 1842 SM501FB_FLAG_DISABLE_AT_EXIT), 1843 }; 1844 1845 static struct sm501_platdata_fb sm501fb_def_pdata = { 1846 .fb_route = SM501_FB_OWN, 1847 .fb_crt = &sm501fb_pdata_crt, 1848 .fb_pnl = &sm501fb_pdata_pnl, 1849 }; 1850 1851 static char driver_name_crt[] = "sm501fb-crt"; 1852 static char driver_name_pnl[] = "sm501fb-panel"; 1853 1854 static int sm501fb_probe_one(struct sm501fb_info *info, 1855 enum sm501_controller head) 1856 { 1857 unsigned char *name = (head == HEAD_CRT) ? "crt" : "panel"; 1858 struct sm501_platdata_fbsub *pd; 1859 struct sm501fb_par *par; 1860 struct fb_info *fbi; 1861 1862 pd = (head == HEAD_CRT) ? info->pdata->fb_crt : info->pdata->fb_pnl; 1863 1864 /* Do not initialise if we've not been given any platform data */ 1865 if (pd == NULL) { 1866 dev_info(info->dev, "no data for fb %s (disabled)\n", name); 1867 return 0; 1868 } 1869 1870 fbi = framebuffer_alloc(sizeof(struct sm501fb_par), info->dev); 1871 if (fbi == NULL) { 1872 dev_err(info->dev, "cannot allocate %s framebuffer\n", name); 1873 return -ENOMEM; 1874 } 1875 1876 par = fbi->par; 1877 par->info = info; 1878 par->head = head; 1879 fbi->pseudo_palette = &par->pseudo_palette; 1880 1881 info->fb[head] = fbi; 1882 1883 return 0; 1884 } 1885 1886 /* Free up anything allocated by sm501fb_init_fb */ 1887 1888 static void sm501_free_init_fb(struct sm501fb_info *info, 1889 enum sm501_controller head) 1890 { 1891 struct fb_info *fbi = info->fb[head]; 1892 1893 if (!fbi) 1894 return; 1895 1896 fb_dealloc_cmap(&fbi->cmap); 1897 } 1898 1899 static int sm501fb_start_one(struct sm501fb_info *info, 1900 enum sm501_controller head, const char *drvname) 1901 { 1902 struct fb_info *fbi = info->fb[head]; 1903 int ret; 1904 1905 if (!fbi) 1906 return 0; 1907 1908 mutex_init(&info->fb[head]->mm_lock); 1909 1910 ret = sm501fb_init_fb(info->fb[head], head, drvname); 1911 if (ret) { 1912 dev_err(info->dev, "cannot initialise fb %s\n", drvname); 1913 return ret; 1914 } 1915 1916 ret = register_framebuffer(info->fb[head]); 1917 if (ret) { 1918 dev_err(info->dev, "failed to register fb %s\n", drvname); 1919 sm501_free_init_fb(info, head); 1920 return ret; 1921 } 1922 1923 dev_info(info->dev, "fb%d: %s frame buffer\n", fbi->node, fbi->fix.id); 1924 1925 return 0; 1926 } 1927 1928 static int sm501fb_probe(struct platform_device *pdev) 1929 { 1930 struct sm501fb_info *info; 1931 struct device *dev = &pdev->dev; 1932 int ret; 1933 1934 /* allocate our framebuffers */ 1935 1936 info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL); 1937 if (!info) { 1938 dev_err(dev, "failed to allocate state\n"); 1939 return -ENOMEM; 1940 } 1941 1942 info->dev = dev = &pdev->dev; 1943 platform_set_drvdata(pdev, info); 1944 1945 if (dev->parent->platform_data) { 1946 struct sm501_platdata *pd = dev->parent->platform_data; 1947 info->pdata = pd->fb; 1948 } 1949 1950 if (info->pdata == NULL) { 1951 int found = 0; 1952 #if defined(CONFIG_OF) 1953 struct device_node *np = pdev->dev.parent->of_node; 1954 const u8 *prop; 1955 const char *cp; 1956 int len; 1957 1958 info->pdata = &sm501fb_def_pdata; 1959 if (np) { 1960 /* Get EDID */ 1961 cp = of_get_property(np, "mode", &len); 1962 if (cp) 1963 strcpy(fb_mode, cp); 1964 prop = of_get_property(np, "edid", &len); 1965 if (prop && len == EDID_LENGTH) { 1966 info->edid_data = kmemdup(prop, EDID_LENGTH, 1967 GFP_KERNEL); 1968 if (info->edid_data) 1969 found = 1; 1970 } 1971 } 1972 #endif 1973 if (!found) { 1974 dev_info(dev, "using default configuration data\n"); 1975 info->pdata = &sm501fb_def_pdata; 1976 } 1977 } 1978 1979 /* probe for the presence of each panel */ 1980 1981 ret = sm501fb_probe_one(info, HEAD_CRT); 1982 if (ret < 0) { 1983 dev_err(dev, "failed to probe CRT\n"); 1984 goto err_alloc; 1985 } 1986 1987 ret = sm501fb_probe_one(info, HEAD_PANEL); 1988 if (ret < 0) { 1989 dev_err(dev, "failed to probe PANEL\n"); 1990 goto err_probed_crt; 1991 } 1992 1993 if (info->fb[HEAD_PANEL] == NULL && 1994 info->fb[HEAD_CRT] == NULL) { 1995 dev_err(dev, "no framebuffers found\n"); 1996 ret = -ENODEV; 1997 goto err_alloc; 1998 } 1999 2000 /* get the resources for both of the framebuffers */ 2001 2002 ret = sm501fb_start(info, pdev); 2003 if (ret) { 2004 dev_err(dev, "cannot initialise SM501\n"); 2005 goto err_probed_panel; 2006 } 2007 2008 ret = sm501fb_start_one(info, HEAD_CRT, driver_name_crt); 2009 if (ret) { 2010 dev_err(dev, "failed to start CRT\n"); 2011 goto err_started; 2012 } 2013 2014 ret = sm501fb_start_one(info, HEAD_PANEL, driver_name_pnl); 2015 if (ret) { 2016 dev_err(dev, "failed to start Panel\n"); 2017 goto err_started_crt; 2018 } 2019 2020 /* create device files */ 2021 2022 ret = device_create_file(dev, &dev_attr_crt_src); 2023 if (ret) 2024 goto err_started_panel; 2025 2026 ret = device_create_file(dev, &dev_attr_fbregs_pnl); 2027 if (ret) 2028 goto err_attached_crtsrc_file; 2029 2030 ret = device_create_file(dev, &dev_attr_fbregs_crt); 2031 if (ret) 2032 goto err_attached_pnlregs_file; 2033 2034 /* we registered, return ok */ 2035 return 0; 2036 2037 err_attached_pnlregs_file: 2038 device_remove_file(dev, &dev_attr_fbregs_pnl); 2039 2040 err_attached_crtsrc_file: 2041 device_remove_file(dev, &dev_attr_crt_src); 2042 2043 err_started_panel: 2044 unregister_framebuffer(info->fb[HEAD_PANEL]); 2045 sm501_free_init_fb(info, HEAD_PANEL); 2046 2047 err_started_crt: 2048 unregister_framebuffer(info->fb[HEAD_CRT]); 2049 sm501_free_init_fb(info, HEAD_CRT); 2050 2051 err_started: 2052 sm501fb_stop(info); 2053 2054 err_probed_panel: 2055 framebuffer_release(info->fb[HEAD_PANEL]); 2056 2057 err_probed_crt: 2058 framebuffer_release(info->fb[HEAD_CRT]); 2059 2060 err_alloc: 2061 kfree(info); 2062 2063 return ret; 2064 } 2065 2066 2067 /* 2068 * Cleanup 2069 */ 2070 static int sm501fb_remove(struct platform_device *pdev) 2071 { 2072 struct sm501fb_info *info = platform_get_drvdata(pdev); 2073 struct fb_info *fbinfo_crt = info->fb[0]; 2074 struct fb_info *fbinfo_pnl = info->fb[1]; 2075 2076 device_remove_file(&pdev->dev, &dev_attr_fbregs_crt); 2077 device_remove_file(&pdev->dev, &dev_attr_fbregs_pnl); 2078 device_remove_file(&pdev->dev, &dev_attr_crt_src); 2079 2080 sm501_free_init_fb(info, HEAD_CRT); 2081 sm501_free_init_fb(info, HEAD_PANEL); 2082 2083 if (fbinfo_crt) 2084 unregister_framebuffer(fbinfo_crt); 2085 if (fbinfo_pnl) 2086 unregister_framebuffer(fbinfo_pnl); 2087 2088 sm501fb_stop(info); 2089 kfree(info); 2090 2091 framebuffer_release(fbinfo_pnl); 2092 framebuffer_release(fbinfo_crt); 2093 2094 return 0; 2095 } 2096 2097 #ifdef CONFIG_PM 2098 2099 static int sm501fb_suspend_fb(struct sm501fb_info *info, 2100 enum sm501_controller head) 2101 { 2102 struct fb_info *fbi = info->fb[head]; 2103 struct sm501fb_par *par; 2104 2105 if (!fbi) 2106 return 0; 2107 2108 par = fbi->par; 2109 if (par->screen.size == 0) 2110 return 0; 2111 2112 /* blank the relevant interface to ensure unit power minimised */ 2113 (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); 2114 2115 /* tell console/fb driver we are suspending */ 2116 2117 console_lock(); 2118 fb_set_suspend(fbi, 1); 2119 console_unlock(); 2120 2121 /* backup copies in case chip is powered down over suspend */ 2122 2123 par->store_fb = vmalloc(par->screen.size); 2124 if (par->store_fb == NULL) { 2125 dev_err(info->dev, "no memory to store screen\n"); 2126 return -ENOMEM; 2127 } 2128 2129 par->store_cursor = vmalloc(par->cursor.size); 2130 if (par->store_cursor == NULL) { 2131 dev_err(info->dev, "no memory to store cursor\n"); 2132 goto err_nocursor; 2133 } 2134 2135 dev_dbg(info->dev, "suspending screen to %p\n", par->store_fb); 2136 dev_dbg(info->dev, "suspending cursor to %p\n", par->store_cursor); 2137 2138 memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); 2139 memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); 2140 2141 return 0; 2142 2143 err_nocursor: 2144 vfree(par->store_fb); 2145 par->store_fb = NULL; 2146 2147 return -ENOMEM; 2148 } 2149 2150 static void sm501fb_resume_fb(struct sm501fb_info *info, 2151 enum sm501_controller head) 2152 { 2153 struct fb_info *fbi = info->fb[head]; 2154 struct sm501fb_par *par; 2155 2156 if (!fbi) 2157 return; 2158 2159 par = fbi->par; 2160 if (par->screen.size == 0) 2161 return; 2162 2163 /* re-activate the configuration */ 2164 2165 (par->ops.fb_set_par)(fbi); 2166 2167 /* restore the data */ 2168 2169 dev_dbg(info->dev, "restoring screen from %p\n", par->store_fb); 2170 dev_dbg(info->dev, "restoring cursor from %p\n", par->store_cursor); 2171 2172 if (par->store_fb) 2173 memcpy_toio(par->screen.k_addr, par->store_fb, 2174 par->screen.size); 2175 2176 if (par->store_cursor) 2177 memcpy_toio(par->cursor.k_addr, par->store_cursor, 2178 par->cursor.size); 2179 2180 console_lock(); 2181 fb_set_suspend(fbi, 0); 2182 console_unlock(); 2183 2184 vfree(par->store_fb); 2185 vfree(par->store_cursor); 2186 } 2187 2188 2189 /* suspend and resume support */ 2190 2191 static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state) 2192 { 2193 struct sm501fb_info *info = platform_get_drvdata(pdev); 2194 2195 /* store crt control to resume with */ 2196 info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 2197 2198 sm501fb_suspend_fb(info, HEAD_CRT); 2199 sm501fb_suspend_fb(info, HEAD_PANEL); 2200 2201 /* turn off the clocks, in case the device is not powered down */ 2202 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 0); 2203 2204 return 0; 2205 } 2206 2207 #define SM501_CRT_CTRL_SAVE (SM501_DC_CRT_CONTROL_TVP | \ 2208 SM501_DC_CRT_CONTROL_SEL) 2209 2210 2211 static int sm501fb_resume(struct platform_device *pdev) 2212 { 2213 struct sm501fb_info *info = platform_get_drvdata(pdev); 2214 unsigned long crt_ctrl; 2215 2216 sm501_unit_power(info->dev->parent, SM501_GATE_DISPLAY, 1); 2217 2218 /* restore the items we want to be saved for crt control */ 2219 2220 crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL); 2221 crt_ctrl &= ~SM501_CRT_CTRL_SAVE; 2222 crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE; 2223 smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL); 2224 2225 sm501fb_resume_fb(info, HEAD_CRT); 2226 sm501fb_resume_fb(info, HEAD_PANEL); 2227 2228 return 0; 2229 } 2230 2231 #else 2232 #define sm501fb_suspend NULL 2233 #define sm501fb_resume NULL 2234 #endif 2235 2236 static struct platform_driver sm501fb_driver = { 2237 .probe = sm501fb_probe, 2238 .remove = sm501fb_remove, 2239 .suspend = sm501fb_suspend, 2240 .resume = sm501fb_resume, 2241 .driver = { 2242 .name = "sm501-fb", 2243 }, 2244 }; 2245 2246 module_platform_driver(sm501fb_driver); 2247 2248 module_param_named(mode, fb_mode, charp, 0); 2249 MODULE_PARM_DESC(mode, 2250 "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); 2251 module_param_named(bpp, default_bpp, ulong, 0); 2252 MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode"); 2253 MODULE_AUTHOR("Ben Dooks, Vincent Sanders"); 2254 MODULE_DESCRIPTION("SM501 Framebuffer driver"); 2255 MODULE_LICENSE("GPL v2"); 2256