1/* 2 * linux/drivers/video/sa1100fb.c 3 * 4 * Copyright (C) 1999 Eric A. Thomas 5 * Based on acornfb.c Copyright (C) Russell King. 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file COPYING in the main directory of this archive for 9 * more details. 10 * 11 * StrongARM 1100 LCD Controller Frame Buffer Driver 12 * 13 * Please direct your questions and comments on this driver to the following 14 * email address: 15 * 16 * linux-arm-kernel@lists.arm.linux.org.uk 17 * 18 * Clean patches should be sent to the ARM Linux Patch System. Please see the 19 * following web page for more information: 20 * 21 * http://www.arm.linux.org.uk/developer/patches/info.shtml 22 * 23 * Thank you. 24 * 25 * Known problems: 26 * - With the Neponset plugged into an Assabet, LCD powerdown 27 * doesn't work (LCD stays powered up). Therefore we shouldn't 28 * blank the screen. 29 * - We don't limit the CPU clock rate nor the mode selection 30 * according to the available SDRAM bandwidth. 31 * 32 * Other notes: 33 * - Linear grayscale palettes and the kernel. 34 * Such code does not belong in the kernel. The kernel frame buffer 35 * drivers do not expect a linear colourmap, but a colourmap based on 36 * the VT100 standard mapping. 37 * 38 * If your _userspace_ requires a linear colourmap, then the setup of 39 * such a colourmap belongs _in userspace_, not in the kernel. Code 40 * to set the colourmap correctly from user space has been sent to 41 * David Neuer. It's around 8 lines of C code, plus another 4 to 42 * detect if we are using grayscale. 43 * 44 * - The following must never be specified in a panel definition: 45 * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL 46 * 47 * - The following should be specified: 48 * either LCCR0_Color or LCCR0_Mono 49 * either LCCR0_Sngl or LCCR0_Dual 50 * either LCCR0_Act or LCCR0_Pas 51 * either LCCR3_OutEnH or LCCD3_OutEnL 52 * either LCCR3_PixRsEdg or LCCR3_PixFlEdg 53 * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff 54 * 55 * Code Status: 56 * 1999/04/01: 57 * - Driver appears to be working for Brutus 320x200x8bpp mode. Other 58 * resolutions are working, but only the 8bpp mode is supported. 59 * Changes need to be made to the palette encode and decode routines 60 * to support 4 and 16 bpp modes. 61 * Driver is not designed to be a module. The FrameBuffer is statically 62 * allocated since dynamic allocation of a 300k buffer cannot be 63 * guaranteed. 64 * 65 * 1999/06/17: 66 * - FrameBuffer memory is now allocated at run-time when the 67 * driver is initialized. 68 * 69 * 2000/04/10: Nicolas Pitre <nico@cam.org> 70 * - Big cleanup for dynamic selection of machine type at run time. 71 * 72 * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> 73 * - Support for Bitsy aka Compaq iPAQ H3600 added. 74 * 75 * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com> 76 * Jeff Sutherland <jsutherland@accelent.com> 77 * - Resolved an issue caused by a change made to the Assabet's PLD 78 * earlier this year which broke the framebuffer driver for newer 79 * Phase 4 Assabets. Some other parameters were changed to optimize 80 * for the Sharp display. 81 * 82 * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp> 83 * - XP860 support added 84 * 85 * 2000/08/19: Mark Huang <mhuang@livetoy.com> 86 * - Allows standard options to be passed on the kernel command line 87 * for most common passive displays. 88 * 89 * 2000/08/29: 90 * - s/save_flags_cli/local_irq_save/ 91 * - remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller 92 * 93 * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> 94 * - Updated LART stuff. Fixed some minor bugs. 95 * 96 * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw> 97 * - Pangolin support added 98 * 99 * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de> 100 * - Huw Webpanel support added 101 * 102 * 2000/11/23: Eric Peng <ericpeng@coventive.com> 103 * - Freebird add 104 * 105 * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 106 * Cliff Brake <cbrake@accelent.com> 107 * - Added PM callback 108 * 109 * 2001/05/26: <rmk@arm.linux.org.uk> 110 * - Fix 16bpp so that (a) we use the right colours rather than some 111 * totally random colour depending on what was in page 0, and (b) 112 * we don't de-reference a NULL pointer. 113 * - remove duplicated implementation of consistent_alloc() 114 * - convert dma address types to dma_addr_t 115 * - remove unused 'montype' stuff 116 * - remove redundant zero inits of init_var after the initial 117 * memzero. 118 * - remove allow_modeset (acornfb idea does not belong here) 119 * 120 * 2001/05/28: <rmk@arm.linux.org.uk> 121 * - massive cleanup - move machine dependent data into structures 122 * - I've left various #warnings in - if you see one, and know 123 * the hardware concerned, please get in contact with me. 124 * 125 * 2001/05/31: <rmk@arm.linux.org.uk> 126 * - Fix LCCR1 HSW value, fix all machine type specifications to 127 * keep values in line. (Please check your machine type specs) 128 * 129 * 2001/06/10: <rmk@arm.linux.org.uk> 130 * - Fiddle with the LCD controller from task context only; mainly 131 * so that we can run with interrupts on, and sleep. 132 * - Convert #warnings into #errors. No pain, no gain. ;) 133 * 134 * 2001/06/14: <rmk@arm.linux.org.uk> 135 * - Make the palette BPS value for 12bpp come out correctly. 136 * - Take notice of "greyscale" on any colour depth. 137 * - Make truecolor visuals use the RGB channel encoding information. 138 * 139 * 2001/07/02: <rmk@arm.linux.org.uk> 140 * - Fix colourmap problems. 141 * 142 * 2001/07/13: <abraham@2d3d.co.za> 143 * - Added support for the ICP LCD-Kit01 on LART. This LCD is 144 * manufactured by Prime View, model no V16C6448AB 145 * 146 * 2001/07/23: <rmk@arm.linux.org.uk> 147 * - Hand merge version from handhelds.org CVS tree. See patch 148 * notes for 595/1 for more information. 149 * - Drop 12bpp (it's 16bpp with different colour register mappings). 150 * - This hardware can not do direct colour. Therefore we don't 151 * support it. 152 * 153 * 2001/07/27: <rmk@arm.linux.org.uk> 154 * - Halve YRES on dual scan LCDs. 155 * 156 * 2001/08/22: <rmk@arm.linux.org.uk> 157 * - Add b/w iPAQ pixclock value. 158 * 159 * 2001/10/12: <rmk@arm.linux.org.uk> 160 * - Add patch 681/1 and clean up stork definitions. 161 */ 162 163#include <linux/module.h> 164#include <linux/kernel.h> 165#include <linux/sched.h> 166#include <linux/errno.h> 167#include <linux/string.h> 168#include <linux/interrupt.h> 169#include <linux/slab.h> 170#include <linux/fb.h> 171#include <linux/delay.h> 172#include <linux/init.h> 173#include <linux/ioport.h> 174#include <linux/cpufreq.h> 175#include <linux/platform_device.h> 176#include <linux/dma-mapping.h> 177 178#include <asm/hardware.h> 179#include <asm/io.h> 180#include <asm/mach-types.h> 181#include <asm/uaccess.h> 182#include <asm/arch/assabet.h> 183#include <asm/arch/shannon.h> 184 185/* 186 * debugging? 187 */ 188#define DEBUG 0 189/* 190 * Complain if VAR is out of range. 191 */ 192#define DEBUG_VAR 1 193 194#undef ASSABET_PAL_VIDEO 195 196#include "sa1100fb.h" 197 198extern void (*sa1100fb_backlight_power)(int on); 199extern void (*sa1100fb_lcd_power)(int on); 200 201/* 202 * IMHO this looks wrong. In 8BPP, length should be 8. 203 */ 204static struct sa1100fb_rgb rgb_8 = { 205 .red = { .offset = 0, .length = 4, }, 206 .green = { .offset = 0, .length = 4, }, 207 .blue = { .offset = 0, .length = 4, }, 208 .transp = { .offset = 0, .length = 0, }, 209}; 210 211static struct sa1100fb_rgb def_rgb_16 = { 212 .red = { .offset = 11, .length = 5, }, 213 .green = { .offset = 5, .length = 6, }, 214 .blue = { .offset = 0, .length = 5, }, 215 .transp = { .offset = 0, .length = 0, }, 216}; 217 218#ifdef CONFIG_SA1100_ASSABET 219#ifndef ASSABET_PAL_VIDEO 220/* 221 * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually 222 * takes an RGB666 signal, but we provide it with an RGB565 signal 223 * instead (def_rgb_16). 224 */ 225static struct sa1100fb_mach_info lq039q2ds54_info __initdata = { 226 .pixclock = 171521, .bpp = 16, 227 .xres = 320, .yres = 240, 228 229 .hsync_len = 5, .vsync_len = 1, 230 .left_margin = 61, .upper_margin = 3, 231 .right_margin = 9, .lower_margin = 0, 232 233 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 234 235 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 236 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 237}; 238#else 239static struct sa1100fb_mach_info pal_info __initdata = { 240 .pixclock = 67797, .bpp = 16, 241 .xres = 640, .yres = 512, 242 243 .hsync_len = 64, .vsync_len = 6, 244 .left_margin = 125, .upper_margin = 70, 245 .right_margin = 115, .lower_margin = 36, 246 247 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 248 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), 249}; 250#endif 251#endif 252 253#ifdef CONFIG_SA1100_H3800 254static struct sa1100fb_mach_info h3800_info __initdata = { 255 .pixclock = 174757, .bpp = 16, 256 .xres = 320, .yres = 240, 257 258 .hsync_len = 3, .vsync_len = 3, 259 .left_margin = 12, .upper_margin = 10, 260 .right_margin = 17, .lower_margin = 1, 261 262 .cmap_static = 1, 263 264 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 265 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 266}; 267#endif 268 269#ifdef CONFIG_SA1100_H3600 270static struct sa1100fb_mach_info h3600_info __initdata = { 271 .pixclock = 174757, .bpp = 16, 272 .xres = 320, .yres = 240, 273 274 .hsync_len = 3, .vsync_len = 3, 275 .left_margin = 12, .upper_margin = 10, 276 .right_margin = 17, .lower_margin = 1, 277 278 .cmap_static = 1, 279 280 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 281 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 282}; 283 284static struct sa1100fb_rgb h3600_rgb_16 = { 285 .red = { .offset = 12, .length = 4, }, 286 .green = { .offset = 7, .length = 4, }, 287 .blue = { .offset = 1, .length = 4, }, 288 .transp = { .offset = 0, .length = 0, }, 289}; 290#endif 291 292#ifdef CONFIG_SA1100_H3100 293static struct sa1100fb_mach_info h3100_info __initdata = { 294 .pixclock = 406977, .bpp = 4, 295 .xres = 320, .yres = 240, 296 297 .hsync_len = 26, .vsync_len = 41, 298 .left_margin = 4, .upper_margin = 0, 299 .right_margin = 4, .lower_margin = 0, 300 301 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 302 .cmap_greyscale = 1, 303 .cmap_inverse = 1, 304 305 .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, 306 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 307}; 308#endif 309 310#ifdef CONFIG_SA1100_COLLIE 311static struct sa1100fb_mach_info collie_info __initdata = { 312 .pixclock = 171521, .bpp = 16, 313 .xres = 320, .yres = 240, 314 315 .hsync_len = 5, .vsync_len = 1, 316 .left_margin = 11, .upper_margin = 2, 317 .right_margin = 30, .lower_margin = 0, 318 319 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 320 321 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 322 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 323}; 324#endif 325 326#ifdef LART_GREY_LCD 327static struct sa1100fb_mach_info lart_grey_info __initdata = { 328 .pixclock = 150000, .bpp = 4, 329 .xres = 320, .yres = 240, 330 331 .hsync_len = 1, .vsync_len = 1, 332 .left_margin = 4, .upper_margin = 0, 333 .right_margin = 2, .lower_margin = 0, 334 335 .cmap_greyscale = 1, 336 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 337 338 .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono, 339 .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), 340}; 341#endif 342#ifdef LART_COLOR_LCD 343static struct sa1100fb_mach_info lart_color_info __initdata = { 344 .pixclock = 150000, .bpp = 16, 345 .xres = 320, .yres = 240, 346 347 .hsync_len = 2, .vsync_len = 3, 348 .left_margin = 69, .upper_margin = 14, 349 .right_margin = 8, .lower_margin = 4, 350 351 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 352 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), 353}; 354#endif 355#ifdef LART_VIDEO_OUT 356static struct sa1100fb_mach_info lart_video_info __initdata = { 357 .pixclock = 39721, .bpp = 16, 358 .xres = 640, .yres = 480, 359 360 .hsync_len = 95, .vsync_len = 2, 361 .left_margin = 40, .upper_margin = 32, 362 .right_margin = 24, .lower_margin = 11, 363 364 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 365 366 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 367 .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), 368}; 369#endif 370 371#ifdef LART_KIT01_LCD 372static struct sa1100fb_mach_info lart_kit01_info __initdata = { 373 .pixclock = 63291, .bpp = 16, 374 .xres = 640, .yres = 480, 375 376 .hsync_len = 64, .vsync_len = 3, 377 .left_margin = 122, .upper_margin = 45, 378 .right_margin = 10, .lower_margin = 10, 379 380 .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 381 .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg 382}; 383#endif 384 385#ifdef CONFIG_SA1100_SHANNON 386static struct sa1100fb_mach_info shannon_info __initdata = { 387 .pixclock = 152500, .bpp = 8, 388 .xres = 640, .yres = 480, 389 390 .hsync_len = 4, .vsync_len = 3, 391 .left_margin = 2, .upper_margin = 0, 392 .right_margin = 1, .lower_margin = 0, 393 394 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 395 396 .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, 397 .lccr3 = LCCR3_ACBsDiv(512), 398}; 399#endif 400 401 402 403static struct sa1100fb_mach_info * __init 404sa1100fb_get_machine_info(struct sa1100fb_info *fbi) 405{ 406 struct sa1100fb_mach_info *inf = NULL; 407 408 /* 409 * R G B T 410 * default {11,5}, { 5,6}, { 0,5}, { 0,0} 411 * h3600 {12,4}, { 7,4}, { 1,4}, { 0,0} 412 * freebird { 8,4}, { 4,4}, { 0,4}, {12,4} 413 */ 414#ifdef CONFIG_SA1100_ASSABET 415 if (machine_is_assabet()) { 416#ifndef ASSABET_PAL_VIDEO 417 inf = &lq039q2ds54_info; 418#else 419 inf = &pal_info; 420#endif 421 } 422#endif 423#ifdef CONFIG_SA1100_H3100 424 if (machine_is_h3100()) { 425 inf = &h3100_info; 426 } 427#endif 428#ifdef CONFIG_SA1100_H3600 429 if (machine_is_h3600()) { 430 inf = &h3600_info; 431 fbi->rgb[RGB_16] = &h3600_rgb_16; 432 } 433#endif 434#ifdef CONFIG_SA1100_H3800 435 if (machine_is_h3800()) { 436 inf = &h3800_info; 437 } 438#endif 439#ifdef CONFIG_SA1100_COLLIE 440 if (machine_is_collie()) { 441 inf = &collie_info; 442 } 443#endif 444#ifdef CONFIG_SA1100_LART 445 if (machine_is_lart()) { 446#ifdef LART_GREY_LCD 447 inf = &lart_grey_info; 448#endif 449#ifdef LART_COLOR_LCD 450 inf = &lart_color_info; 451#endif 452#ifdef LART_VIDEO_OUT 453 inf = &lart_video_info; 454#endif 455#ifdef LART_KIT01_LCD 456 inf = &lart_kit01_info; 457#endif 458 } 459#endif 460#ifdef CONFIG_SA1100_SHANNON 461 if (machine_is_shannon()) { 462 inf = &shannon_info; 463 } 464#endif 465 return inf; 466} 467 468static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *); 469static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state); 470 471static inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state) 472{ 473 unsigned long flags; 474 475 local_irq_save(flags); 476 /* 477 * We need to handle two requests being made at the same time. 478 * There are two important cases: 479 * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) 480 * We must perform the unblanking, which will do our REENABLE for us. 481 * 2. When we are blanking, but immediately unblank before we have 482 * blanked. We do the "REENABLE" thing here as well, just to be sure. 483 */ 484 if (fbi->task_state == C_ENABLE && state == C_REENABLE) 485 state = (u_int) -1; 486 if (fbi->task_state == C_DISABLE && state == C_ENABLE) 487 state = C_REENABLE; 488 489 if (state != (u_int)-1) { 490 fbi->task_state = state; 491 schedule_work(&fbi->task); 492 } 493 local_irq_restore(flags); 494} 495 496static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) 497{ 498 chan &= 0xffff; 499 chan >>= 16 - bf->length; 500 return chan << bf->offset; 501} 502 503/* 504 * Convert bits-per-pixel to a hardware palette PBS value. 505 */ 506static inline u_int palette_pbs(struct fb_var_screeninfo *var) 507{ 508 int ret = 0; 509 switch (var->bits_per_pixel) { 510 case 4: ret = 0 << 12; break; 511 case 8: ret = 1 << 12; break; 512 case 16: ret = 2 << 12; break; 513 } 514 return ret; 515} 516 517static int 518sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, 519 u_int trans, struct fb_info *info) 520{ 521 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 522 u_int val, ret = 1; 523 524 if (regno < fbi->palette_size) { 525 val = ((red >> 4) & 0xf00); 526 val |= ((green >> 8) & 0x0f0); 527 val |= ((blue >> 12) & 0x00f); 528 529 if (regno == 0) 530 val |= palette_pbs(&fbi->fb.var); 531 532 fbi->palette_cpu[regno] = val; 533 ret = 0; 534 } 535 return ret; 536} 537 538static int 539sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 540 u_int trans, struct fb_info *info) 541{ 542 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 543 unsigned int val; 544 int ret = 1; 545 546 /* 547 * If inverse mode was selected, invert all the colours 548 * rather than the register number. The register number 549 * is what you poke into the framebuffer to produce the 550 * colour you requested. 551 */ 552 if (fbi->cmap_inverse) { 553 red = 0xffff - red; 554 green = 0xffff - green; 555 blue = 0xffff - blue; 556 } 557 558 /* 559 * If greyscale is true, then we convert the RGB value 560 * to greyscale no mater what visual we are using. 561 */ 562 if (fbi->fb.var.grayscale) 563 red = green = blue = (19595 * red + 38470 * green + 564 7471 * blue) >> 16; 565 566 switch (fbi->fb.fix.visual) { 567 case FB_VISUAL_TRUECOLOR: 568 /* 569 * 12 or 16-bit True Colour. We encode the RGB value 570 * according to the RGB bitfield information. 571 */ 572 if (regno < 16) { 573 u32 *pal = fbi->fb.pseudo_palette; 574 575 val = chan_to_field(red, &fbi->fb.var.red); 576 val |= chan_to_field(green, &fbi->fb.var.green); 577 val |= chan_to_field(blue, &fbi->fb.var.blue); 578 579 pal[regno] = val; 580 ret = 0; 581 } 582 break; 583 584 case FB_VISUAL_STATIC_PSEUDOCOLOR: 585 case FB_VISUAL_PSEUDOCOLOR: 586 ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info); 587 break; 588 } 589 590 return ret; 591} 592 593#ifdef CONFIG_CPU_FREQ 594/* 595 * sa1100fb_display_dma_period() 596 * Calculate the minimum period (in picoseconds) between two DMA 597 * requests for the LCD controller. If we hit this, it means we're 598 * doing nothing but LCD DMA. 599 */ 600static inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) 601{ 602 /* 603 * Period = pixclock * bits_per_byte * bytes_per_transfer 604 * / memory_bits_per_pixel; 605 */ 606 return var->pixclock * 8 * 16 / var->bits_per_pixel; 607} 608#endif 609 610/* 611 * sa1100fb_check_var(): 612 * Round up in the following order: bits_per_pixel, xres, 613 * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, 614 * bitfields, horizontal timing, vertical timing. 615 */ 616static int 617sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 618{ 619 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 620 int rgbidx; 621 622 if (var->xres < MIN_XRES) 623 var->xres = MIN_XRES; 624 if (var->yres < MIN_YRES) 625 var->yres = MIN_YRES; 626 if (var->xres > fbi->max_xres) 627 var->xres = fbi->max_xres; 628 if (var->yres > fbi->max_yres) 629 var->yres = fbi->max_yres; 630 var->xres_virtual = max(var->xres_virtual, var->xres); 631 var->yres_virtual = max(var->yres_virtual, var->yres); 632 633 DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); 634 switch (var->bits_per_pixel) { 635 case 4: 636 rgbidx = RGB_8; 637 break; 638 case 8: 639 rgbidx = RGB_8; 640 break; 641 case 16: 642 rgbidx = RGB_16; 643 break; 644 default: 645 return -EINVAL; 646 } 647 648 /* 649 * Copy the RGB parameters for this display 650 * from the machine specific parameters. 651 */ 652 var->red = fbi->rgb[rgbidx]->red; 653 var->green = fbi->rgb[rgbidx]->green; 654 var->blue = fbi->rgb[rgbidx]->blue; 655 var->transp = fbi->rgb[rgbidx]->transp; 656 657 DPRINTK("RGBT length = %d:%d:%d:%d\n", 658 var->red.length, var->green.length, var->blue.length, 659 var->transp.length); 660 661 DPRINTK("RGBT offset = %d:%d:%d:%d\n", 662 var->red.offset, var->green.offset, var->blue.offset, 663 var->transp.offset); 664 665#ifdef CONFIG_CPU_FREQ 666 printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", 667 sa1100fb_display_dma_period(var), 668 cpufreq_get(smp_processor_id())); 669#endif 670 671 return 0; 672} 673 674static inline void sa1100fb_set_truecolor(u_int is_true_color) 675{ 676 if (machine_is_assabet()) { 677 if (is_true_color) 678 ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); 679 else 680 ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); 681 } 682} 683 684/* 685 * sa1100fb_set_par(): 686 * Set the user defined part of the display for the specified console 687 */ 688static int sa1100fb_set_par(struct fb_info *info) 689{ 690 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 691 struct fb_var_screeninfo *var = &info->var; 692 unsigned long palette_mem_size; 693 694 DPRINTK("set_par\n"); 695 696 if (var->bits_per_pixel == 16) 697 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; 698 else if (!fbi->cmap_static) 699 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 700 else { 701 /* 702 * Some people have weird ideas about wanting static 703 * pseudocolor maps. I suspect their user space 704 * applications are broken. 705 */ 706 fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; 707 } 708 709 fbi->fb.fix.line_length = var->xres_virtual * 710 var->bits_per_pixel / 8; 711 fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; 712 713 palette_mem_size = fbi->palette_size * sizeof(u16); 714 715 DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); 716 717 fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); 718 fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; 719 720 /* 721 * Set (any) board control register to handle new color depth 722 */ 723 sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); 724 sa1100fb_activate_var(var, fbi); 725 726 return 0; 727} 728 729 730/* 731 * Formal definition of the VESA spec: 732 * On 733 * This refers to the state of the display when it is in full operation 734 * Stand-By 735 * This defines an optional operating state of minimal power reduction with 736 * the shortest recovery time 737 * Suspend 738 * This refers to a level of power management in which substantial power 739 * reduction is achieved by the display. The display can have a longer 740 * recovery time from this state than from the Stand-by state 741 * Off 742 * This indicates that the display is consuming the lowest level of power 743 * and is non-operational. Recovery from this state may optionally require 744 * the user to manually power on the monitor 745 * 746 * Now, the fbdev driver adds an additional state, (blank), where they 747 * turn off the video (maybe by colormap tricks), but don't mess with the 748 * video itself: think of it semantically between on and Stand-By. 749 * 750 * So here's what we should do in our fbdev blank routine: 751 * 752 * VESA_NO_BLANKING (mode 0) Video on, front/back light on 753 * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off 754 * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off 755 * VESA_POWERDOWN (mode 3) Video off, front/back light off 756 * 757 * This will match the matrox implementation. 758 */ 759/* 760 * sa1100fb_blank(): 761 * Blank the display by setting all palette values to zero. Note, the 762 * 12 and 16 bpp modes don't really use the palette, so this will not 763 * blank the display in all modes. 764 */ 765static int sa1100fb_blank(int blank, struct fb_info *info) 766{ 767 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 768 int i; 769 770 DPRINTK("sa1100fb_blank: blank=%d\n", blank); 771 772 switch (blank) { 773 case FB_BLANK_POWERDOWN: 774 case FB_BLANK_VSYNC_SUSPEND: 775 case FB_BLANK_HSYNC_SUSPEND: 776 case FB_BLANK_NORMAL: 777 if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || 778 fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) 779 for (i = 0; i < fbi->palette_size; i++) 780 sa1100fb_setpalettereg(i, 0, 0, 0, 0, info); 781 sa1100fb_schedule_work(fbi, C_DISABLE); 782 break; 783 784 case FB_BLANK_UNBLANK: 785 if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || 786 fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) 787 fb_set_cmap(&fbi->fb.cmap, info); 788 sa1100fb_schedule_work(fbi, C_ENABLE); 789 } 790 return 0; 791} 792 793static int sa1100fb_mmap(struct fb_info *info, 794 struct vm_area_struct *vma) 795{ 796 struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 797 unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT; 798 799 if (off < info->fix.smem_len) { 800 vma->vm_pgoff += 1; /* skip over the palette */ 801 return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu, 802 fbi->map_dma, fbi->map_size); 803 } 804 805 start = info->fix.mmio_start; 806 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); 807 808 if ((vma->vm_end - vma->vm_start + off) > len) 809 return -EINVAL; 810 811 off += start & PAGE_MASK; 812 vma->vm_pgoff = off >> PAGE_SHIFT; 813 vma->vm_flags |= VM_IO; 814 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 815 return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 816 vma->vm_end - vma->vm_start, 817 vma->vm_page_prot); 818} 819 820static struct fb_ops sa1100fb_ops = { 821 .owner = THIS_MODULE, 822 .fb_check_var = sa1100fb_check_var, 823 .fb_set_par = sa1100fb_set_par, 824// .fb_set_cmap = sa1100fb_set_cmap, 825 .fb_setcolreg = sa1100fb_setcolreg, 826 .fb_fillrect = cfb_fillrect, 827 .fb_copyarea = cfb_copyarea, 828 .fb_imageblit = cfb_imageblit, 829 .fb_blank = sa1100fb_blank, 830 .fb_mmap = sa1100fb_mmap, 831}; 832 833/* 834 * Calculate the PCD value from the clock rate (in picoseconds). 835 * We take account of the PPCR clock setting. 836 */ 837static inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock) 838{ 839 unsigned int pcd = cpuclock / 100; 840 841 pcd *= pixclock; 842 pcd /= 10000000; 843 844 return pcd + 1; /* make up for integer math truncations */ 845} 846 847/* 848 * sa1100fb_activate_var(): 849 * Configures LCD Controller based on entries in var parameter. Settings are 850 * only written to the controller if changes were made. 851 */ 852static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) 853{ 854 struct sa1100fb_lcd_reg new_regs; 855 u_int half_screen_size, yres, pcd; 856 u_long flags; 857 858 DPRINTK("Configuring SA1100 LCD\n"); 859 860 DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", 861 var->xres, var->hsync_len, 862 var->left_margin, var->right_margin); 863 DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", 864 var->yres, var->vsync_len, 865 var->upper_margin, var->lower_margin); 866 867#if DEBUG_VAR 868 if (var->xres < 16 || var->xres > 1024) 869 printk(KERN_ERR "%s: invalid xres %d\n", 870 fbi->fb.fix.id, var->xres); 871 if (var->hsync_len < 1 || var->hsync_len > 64) 872 printk(KERN_ERR "%s: invalid hsync_len %d\n", 873 fbi->fb.fix.id, var->hsync_len); 874 if (var->left_margin < 1 || var->left_margin > 255) 875 printk(KERN_ERR "%s: invalid left_margin %d\n", 876 fbi->fb.fix.id, var->left_margin); 877 if (var->right_margin < 1 || var->right_margin > 255) 878 printk(KERN_ERR "%s: invalid right_margin %d\n", 879 fbi->fb.fix.id, var->right_margin); 880 if (var->yres < 1 || var->yres > 1024) 881 printk(KERN_ERR "%s: invalid yres %d\n", 882 fbi->fb.fix.id, var->yres); 883 if (var->vsync_len < 1 || var->vsync_len > 64) 884 printk(KERN_ERR "%s: invalid vsync_len %d\n", 885 fbi->fb.fix.id, var->vsync_len); 886 if (var->upper_margin < 0 || var->upper_margin > 255) 887 printk(KERN_ERR "%s: invalid upper_margin %d\n", 888 fbi->fb.fix.id, var->upper_margin); 889 if (var->lower_margin < 0 || var->lower_margin > 255) 890 printk(KERN_ERR "%s: invalid lower_margin %d\n", 891 fbi->fb.fix.id, var->lower_margin); 892#endif 893 894 new_regs.lccr0 = fbi->lccr0 | 895 LCCR0_LEN | LCCR0_LDM | LCCR0_BAM | 896 LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0); 897 898 new_regs.lccr1 = 899 LCCR1_DisWdth(var->xres) + 900 LCCR1_HorSnchWdth(var->hsync_len) + 901 LCCR1_BegLnDel(var->left_margin) + 902 LCCR1_EndLnDel(var->right_margin); 903 904 /* 905 * If we have a dual scan LCD, then we need to halve 906 * the YRES parameter. 907 */ 908 yres = var->yres; 909 if (fbi->lccr0 & LCCR0_Dual) 910 yres /= 2; 911 912 new_regs.lccr2 = 913 LCCR2_DisHght(yres) + 914 LCCR2_VrtSnchWdth(var->vsync_len) + 915 LCCR2_BegFrmDel(var->upper_margin) + 916 LCCR2_EndFrmDel(var->lower_margin); 917 918 pcd = get_pcd(var->pixclock, cpufreq_get(0)); 919 new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 | 920 (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | 921 (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); 922 923 DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0); 924 DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1); 925 DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2); 926 DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3); 927 928 half_screen_size = var->bits_per_pixel; 929 half_screen_size = half_screen_size * var->xres * var->yres / 16; 930 931 /* Update shadow copy atomically */ 932 local_irq_save(flags); 933 fbi->dbar1 = fbi->palette_dma; 934 fbi->dbar2 = fbi->screen_dma + half_screen_size; 935 936 fbi->reg_lccr0 = new_regs.lccr0; 937 fbi->reg_lccr1 = new_regs.lccr1; 938 fbi->reg_lccr2 = new_regs.lccr2; 939 fbi->reg_lccr3 = new_regs.lccr3; 940 local_irq_restore(flags); 941 942 /* 943 * Only update the registers if the controller is enabled 944 * and something has changed. 945 */ 946 if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) || 947 (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) || 948 (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2)) 949 sa1100fb_schedule_work(fbi, C_REENABLE); 950 951 return 0; 952} 953 954/* 955 * NOTE! The following functions are purely helpers for set_ctrlr_state. 956 * Do not call them directly; set_ctrlr_state does the correct serialisation 957 * to ensure that things happen in the right way 100% of time time. 958 * -- rmk 959 */ 960static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on) 961{ 962 DPRINTK("backlight o%s\n", on ? "n" : "ff"); 963 964 if (sa1100fb_backlight_power) 965 sa1100fb_backlight_power(on); 966} 967 968static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on) 969{ 970 DPRINTK("LCD power o%s\n", on ? "n" : "ff"); 971 972 if (sa1100fb_lcd_power) 973 sa1100fb_lcd_power(on); 974} 975 976static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi) 977{ 978 u_int mask = 0; 979 980 /* 981 * Enable GPIO<9:2> for LCD use if: 982 * 1. Active display, or 983 * 2. Color Dual Passive display 984 * 985 * see table 11.8 on page 11-27 in the SA1100 manual 986 * -- Erik. 987 * 988 * SA1110 spec update nr. 25 says we can and should 989 * clear LDD15 to 12 for 4 or 8bpp modes with active 990 * panels. 991 */ 992 if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color && 993 (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) { 994 mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; 995 996 if (fbi->fb.var.bits_per_pixel > 8 || 997 (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual) 998 mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12; 999 1000 } 1001 1002 if (mask) { 1003 GPDR |= mask; 1004 GAFR |= mask; 1005 } 1006} 1007 1008static void sa1100fb_enable_controller(struct sa1100fb_info *fbi) 1009{ 1010 DPRINTK("Enabling LCD controller\n"); 1011 1012 /* 1013 * Make sure the mode bits are present in the first palette entry 1014 */ 1015 fbi->palette_cpu[0] &= 0xcfff; 1016 fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); 1017 1018 /* Sequence from 11.7.10 */ 1019 LCCR3 = fbi->reg_lccr3; 1020 LCCR2 = fbi->reg_lccr2; 1021 LCCR1 = fbi->reg_lccr1; 1022 LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN; 1023 DBAR1 = fbi->dbar1; 1024 DBAR2 = fbi->dbar2; 1025 LCCR0 |= LCCR0_LEN; 1026 1027 if (machine_is_shannon()) { 1028 GPDR |= SHANNON_GPIO_DISP_EN; 1029 GPSR |= SHANNON_GPIO_DISP_EN; 1030 } 1031 1032 DPRINTK("DBAR1 = 0x%08x\n", DBAR1); 1033 DPRINTK("DBAR2 = 0x%08x\n", DBAR2); 1034 DPRINTK("LCCR0 = 0x%08x\n", LCCR0); 1035 DPRINTK("LCCR1 = 0x%08x\n", LCCR1); 1036 DPRINTK("LCCR2 = 0x%08x\n", LCCR2); 1037 DPRINTK("LCCR3 = 0x%08x\n", LCCR3); 1038} 1039 1040static void sa1100fb_disable_controller(struct sa1100fb_info *fbi) 1041{ 1042 DECLARE_WAITQUEUE(wait, current); 1043 1044 DPRINTK("Disabling LCD controller\n"); 1045 1046 if (machine_is_shannon()) { 1047 GPCR |= SHANNON_GPIO_DISP_EN; 1048 } 1049 1050 set_current_state(TASK_UNINTERRUPTIBLE); 1051 add_wait_queue(&fbi->ctrlr_wait, &wait); 1052 1053 LCSR = 0xffffffff; /* Clear LCD Status Register */ 1054 LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ 1055 LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */ 1056 1057 schedule_timeout(20 * HZ / 1000); 1058 remove_wait_queue(&fbi->ctrlr_wait, &wait); 1059} 1060 1061/* 1062 * sa1100fb_handle_irq: Handle 'LCD DONE' interrupts. 1063 */ 1064static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id) 1065{ 1066 struct sa1100fb_info *fbi = dev_id; 1067 unsigned int lcsr = LCSR; 1068 1069 if (lcsr & LCSR_LDD) { 1070 LCCR0 |= LCCR0_LDM; 1071 wake_up(&fbi->ctrlr_wait); 1072 } 1073 1074 LCSR = lcsr; 1075 return IRQ_HANDLED; 1076} 1077 1078/* 1079 * This function must be called from task context only, since it will 1080 * sleep when disabling the LCD controller, or if we get two contending 1081 * processes trying to alter state. 1082 */ 1083static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) 1084{ 1085 u_int old_state; 1086 1087 down(&fbi->ctrlr_sem); 1088 1089 old_state = fbi->state; 1090 1091 /* 1092 * Hack around fbcon initialisation. 1093 */ 1094 if (old_state == C_STARTUP && state == C_REENABLE) 1095 state = C_ENABLE; 1096 1097 switch (state) { 1098 case C_DISABLE_CLKCHANGE: 1099 /* 1100 * Disable controller for clock change. If the 1101 * controller is already disabled, then do nothing. 1102 */ 1103 if (old_state != C_DISABLE && old_state != C_DISABLE_PM) { 1104 fbi->state = state; 1105 sa1100fb_disable_controller(fbi); 1106 } 1107 break; 1108 1109 case C_DISABLE_PM: 1110 case C_DISABLE: 1111 /* 1112 * Disable controller 1113 */ 1114 if (old_state != C_DISABLE) { 1115 fbi->state = state; 1116 1117 __sa1100fb_backlight_power(fbi, 0); 1118 if (old_state != C_DISABLE_CLKCHANGE) 1119 sa1100fb_disable_controller(fbi); 1120 __sa1100fb_lcd_power(fbi, 0); 1121 } 1122 break; 1123 1124 case C_ENABLE_CLKCHANGE: 1125 /* 1126 * Enable the controller after clock change. Only 1127 * do this if we were disabled for the clock change. 1128 */ 1129 if (old_state == C_DISABLE_CLKCHANGE) { 1130 fbi->state = C_ENABLE; 1131 sa1100fb_enable_controller(fbi); 1132 } 1133 break; 1134 1135 case C_REENABLE: 1136 /* 1137 * Re-enable the controller only if it was already 1138 * enabled. This is so we reprogram the control 1139 * registers. 1140 */ 1141 if (old_state == C_ENABLE) { 1142 sa1100fb_disable_controller(fbi); 1143 sa1100fb_setup_gpio(fbi); 1144 sa1100fb_enable_controller(fbi); 1145 } 1146 break; 1147 1148 case C_ENABLE_PM: 1149 /* 1150 * Re-enable the controller after PM. This is not 1151 * perfect - think about the case where we were doing 1152 * a clock change, and we suspended half-way through. 1153 */ 1154 if (old_state != C_DISABLE_PM) 1155 break; 1156 /* fall through */ 1157 1158 case C_ENABLE: 1159 /* 1160 * Power up the LCD screen, enable controller, and 1161 * turn on the backlight. 1162 */ 1163 if (old_state != C_ENABLE) { 1164 fbi->state = C_ENABLE; 1165 sa1100fb_setup_gpio(fbi); 1166 __sa1100fb_lcd_power(fbi, 1); 1167 sa1100fb_enable_controller(fbi); 1168 __sa1100fb_backlight_power(fbi, 1); 1169 } 1170 break; 1171 } 1172 up(&fbi->ctrlr_sem); 1173} 1174 1175/* 1176 * Our LCD controller task (which is called when we blank or unblank) 1177 * via keventd. 1178 */ 1179static void sa1100fb_task(struct work_struct *w) 1180{ 1181 struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task); 1182 u_int state = xchg(&fbi->task_state, -1); 1183 1184 set_ctrlr_state(fbi, state); 1185} 1186 1187#ifdef CONFIG_CPU_FREQ 1188/* 1189 * Calculate the minimum DMA period over all displays that we own. 1190 * This, together with the SDRAM bandwidth defines the slowest CPU 1191 * frequency that can be selected. 1192 */ 1193static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) 1194{ 1195 return sa1100fb_display_dma_period(&fbi->fb.var); 1196} 1197 1198/* 1199 * CPU clock speed change handler. We need to adjust the LCD timing 1200 * parameters when the CPU clock is adjusted by the power management 1201 * subsystem. 1202 */ 1203static int 1204sa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, 1205 void *data) 1206{ 1207 struct sa1100fb_info *fbi = TO_INF(nb, freq_transition); 1208 struct cpufreq_freqs *f = data; 1209 u_int pcd; 1210 1211 switch (val) { 1212 case CPUFREQ_PRECHANGE: 1213 set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); 1214 break; 1215 1216 case CPUFREQ_POSTCHANGE: 1217 pcd = get_pcd(fbi->fb.var.pixclock, f->new); 1218 fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); 1219 set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); 1220 break; 1221 } 1222 return 0; 1223} 1224 1225static int 1226sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, 1227 void *data) 1228{ 1229 struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); 1230 struct cpufreq_policy *policy = data; 1231 1232 switch (val) { 1233 case CPUFREQ_ADJUST: 1234 case CPUFREQ_INCOMPATIBLE: 1235 printk(KERN_DEBUG "min dma period: %d ps, " 1236 "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), 1237 policy->max); 1238 /* todo: fill in min/max values */ 1239 break; 1240 case CPUFREQ_NOTIFY: 1241 do {} while(0); 1242 /* todo: panic if min/max values aren't fulfilled 1243 * [can't really happen unless there's a bug in the 1244 * CPU policy verififcation process * 1245 */ 1246 break; 1247 } 1248 return 0; 1249} 1250#endif 1251 1252#ifdef CONFIG_PM 1253/* 1254 * Power management hooks. Note that we won't be called from IRQ context, 1255 * unlike the blank functions above, so we may sleep. 1256 */ 1257static int sa1100fb_suspend(struct platform_device *dev, pm_message_t state) 1258{ 1259 struct sa1100fb_info *fbi = platform_get_drvdata(dev); 1260 1261 set_ctrlr_state(fbi, C_DISABLE_PM); 1262 return 0; 1263} 1264 1265static int sa1100fb_resume(struct platform_device *dev) 1266{ 1267 struct sa1100fb_info *fbi = platform_get_drvdata(dev); 1268 1269 set_ctrlr_state(fbi, C_ENABLE_PM); 1270 return 0; 1271} 1272#else 1273#define sa1100fb_suspend NULL 1274#define sa1100fb_resume NULL 1275#endif 1276 1277/* 1278 * sa1100fb_map_video_memory(): 1279 * Allocates the DRAM memory for the frame buffer. This buffer is 1280 * remapped into a non-cached, non-buffered, memory region to 1281 * allow palette and pixel writes to occur without flushing the 1282 * cache. Once this area is remapped, all virtual memory 1283 * access to the video memory should occur at the new region. 1284 */ 1285static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi) 1286{ 1287 /* 1288 * We reserve one page for the palette, plus the size 1289 * of the framebuffer. 1290 */ 1291 fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE); 1292 fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, 1293 &fbi->map_dma, GFP_KERNEL); 1294 1295 if (fbi->map_cpu) { 1296 fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE; 1297 fbi->screen_dma = fbi->map_dma + PAGE_SIZE; 1298 fbi->fb.fix.smem_start = fbi->screen_dma; 1299 } 1300 1301 return fbi->map_cpu ? 0 : -ENOMEM; 1302} 1303 1304/* Fake monspecs to fill in fbinfo structure */ 1305static struct fb_monspecs monspecs __initdata = { 1306 .hfmin = 30000, 1307 .hfmax = 70000, 1308 .vfmin = 50, 1309 .vfmax = 65, 1310}; 1311 1312 1313static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) 1314{ 1315 struct sa1100fb_mach_info *inf; 1316 struct sa1100fb_info *fbi; 1317 1318 fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16, 1319 GFP_KERNEL); 1320 if (!fbi) 1321 return NULL; 1322 1323 memset(fbi, 0, sizeof(struct sa1100fb_info)); 1324 fbi->dev = dev; 1325 1326 strcpy(fbi->fb.fix.id, SA1100_NAME); 1327 1328 fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; 1329 fbi->fb.fix.type_aux = 0; 1330 fbi->fb.fix.xpanstep = 0; 1331 fbi->fb.fix.ypanstep = 0; 1332 fbi->fb.fix.ywrapstep = 0; 1333 fbi->fb.fix.accel = FB_ACCEL_NONE; 1334 1335 fbi->fb.var.nonstd = 0; 1336 fbi->fb.var.activate = FB_ACTIVATE_NOW; 1337 fbi->fb.var.height = -1; 1338 fbi->fb.var.width = -1; 1339 fbi->fb.var.accel_flags = 0; 1340 fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; 1341 1342 fbi->fb.fbops = &sa1100fb_ops; 1343 fbi->fb.flags = FBINFO_DEFAULT; 1344 fbi->fb.monspecs = monspecs; 1345 fbi->fb.pseudo_palette = (fbi + 1); 1346 1347 fbi->rgb[RGB_8] = &rgb_8; 1348 fbi->rgb[RGB_16] = &def_rgb_16; 1349 1350 inf = sa1100fb_get_machine_info(fbi); 1351 1352 /* 1353 * People just don't seem to get this. We don't support 1354 * anything but correct entries now, so panic if someone 1355 * does something stupid. 1356 */ 1357 if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) || 1358 inf->pixclock == 0) 1359 panic("sa1100fb error: invalid LCCR3 fields set or zero " 1360 "pixclock."); 1361 1362 fbi->max_xres = inf->xres; 1363 fbi->fb.var.xres = inf->xres; 1364 fbi->fb.var.xres_virtual = inf->xres; 1365 fbi->max_yres = inf->yres; 1366 fbi->fb.var.yres = inf->yres; 1367 fbi->fb.var.yres_virtual = inf->yres; 1368 fbi->max_bpp = inf->bpp; 1369 fbi->fb.var.bits_per_pixel = inf->bpp; 1370 fbi->fb.var.pixclock = inf->pixclock; 1371 fbi->fb.var.hsync_len = inf->hsync_len; 1372 fbi->fb.var.left_margin = inf->left_margin; 1373 fbi->fb.var.right_margin = inf->right_margin; 1374 fbi->fb.var.vsync_len = inf->vsync_len; 1375 fbi->fb.var.upper_margin = inf->upper_margin; 1376 fbi->fb.var.lower_margin = inf->lower_margin; 1377 fbi->fb.var.sync = inf->sync; 1378 fbi->fb.var.grayscale = inf->cmap_greyscale; 1379 fbi->cmap_inverse = inf->cmap_inverse; 1380 fbi->cmap_static = inf->cmap_static; 1381 fbi->lccr0 = inf->lccr0; 1382 fbi->lccr3 = inf->lccr3; 1383 fbi->state = C_STARTUP; 1384 fbi->task_state = (u_char)-1; 1385 fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * 1386 fbi->max_bpp / 8; 1387 1388 init_waitqueue_head(&fbi->ctrlr_wait); 1389 INIT_WORK(&fbi->task, sa1100fb_task); 1390 init_MUTEX(&fbi->ctrlr_sem); 1391 1392 return fbi; 1393} 1394 1395static int __init sa1100fb_probe(struct platform_device *pdev) 1396{ 1397 struct sa1100fb_info *fbi; 1398 int ret, irq; 1399 1400 irq = platform_get_irq(pdev, 0); 1401 if (irq < 0) 1402 return -EINVAL; 1403 1404 if (!request_mem_region(0xb0100000, 0x10000, "LCD")) 1405 return -EBUSY; 1406 1407 fbi = sa1100fb_init_fbinfo(&pdev->dev); 1408 ret = -ENOMEM; 1409 if (!fbi) 1410 goto failed; 1411 1412 /* Initialize video memory */ 1413 ret = sa1100fb_map_video_memory(fbi); 1414 if (ret) 1415 goto failed; 1416 1417 ret = request_irq(irq, sa1100fb_handle_irq, IRQF_DISABLED, 1418 "LCD", fbi); 1419 if (ret) { 1420 printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); 1421 goto failed; 1422 } 1423 1424#ifdef ASSABET_PAL_VIDEO 1425 if (machine_is_assabet()) 1426 ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); 1427#endif 1428 1429 /* 1430 * This makes sure that our colour bitfield 1431 * descriptors are correctly initialised. 1432 */ 1433 sa1100fb_check_var(&fbi->fb.var, &fbi->fb); 1434 1435 platform_set_drvdata(pdev, fbi); 1436 1437 ret = register_framebuffer(&fbi->fb); 1438 if (ret < 0) 1439 goto err_free_irq; 1440 1441#ifdef CONFIG_CPU_FREQ 1442 fbi->freq_transition.notifier_call = sa1100fb_freq_transition; 1443 fbi->freq_policy.notifier_call = sa1100fb_freq_policy; 1444 cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); 1445 cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); 1446#endif 1447 1448 /* This driver cannot be unloaded at the moment */ 1449 return 0; 1450 1451 err_free_irq: 1452 free_irq(irq, fbi); 1453 failed: 1454 platform_set_drvdata(pdev, NULL); 1455 kfree(fbi); 1456 release_mem_region(0xb0100000, 0x10000); 1457 return ret; 1458} 1459 1460static struct platform_driver sa1100fb_driver = { 1461 .probe = sa1100fb_probe, 1462 .suspend = sa1100fb_suspend, 1463 .resume = sa1100fb_resume, 1464 .driver = { 1465 .name = "sa11x0-fb", 1466 }, 1467}; 1468 1469int __init sa1100fb_init(void) 1470{ 1471 if (fb_get_options("sa1100fb", NULL)) 1472 return -ENODEV; 1473 1474 return platform_driver_register(&sa1100fb_driver); 1475} 1476 1477int __init sa1100fb_setup(char *options) 1478{ 1479 return 0; 1480} 1481 1482module_init(sa1100fb_init); 1483MODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver"); 1484MODULE_LICENSE("GPL"); 1485