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