11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/video/sa1100fb.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1999 Eric A. Thomas 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Based on acornfb.c Copyright (C) Russell King. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * License. See the file COPYING in the main directory of this archive for 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * more details. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * StrongARM 1100 LCD Controller Frame Buffer Driver 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please direct your questions and comments on this driver to the following 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * email address: 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux-arm-kernel@lists.arm.linux.org.uk 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clean patches should be sent to the ARM Linux Patch System. Please see the 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * following web page for more information: 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * http://www.arm.linux.org.uk/developer/patches/info.shtml 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thank you. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Known problems: 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - With the Neponset plugged into an Assabet, LCD powerdown 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't work (LCD stays powered up). Therefore we shouldn't 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blank the screen. 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - We don't limit the CPU clock rate nor the mode selection 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * according to the available SDRAM bandwidth. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Other notes: 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Linear grayscale palettes and the kernel. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Such code does not belong in the kernel. The kernel frame buffer 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers do not expect a linear colourmap, but a colourmap based on 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the VT100 standard mapping. 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If your _userspace_ requires a linear colourmap, then the setup of 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * such a colourmap belongs _in userspace_, not in the kernel. Code 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to set the colourmap correctly from user space has been sent to 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * David Neuer. It's around 8 lines of C code, plus another 4 to 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * detect if we are using grayscale. 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - The following must never be specified in a panel definition: 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LCCR0_LtlEnd, LCCR3_PixClkDiv, LCCR3_VrtSnchL, LCCR3_HorSnchL 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - The following should be specified: 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR0_Color or LCCR0_Mono 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR0_Sngl or LCCR0_Dual 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR0_Act or LCCR0_Pas 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR3_OutEnH or LCCD3_OutEnL 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR3_PixRsEdg or LCCR3_PixFlEdg 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * either LCCR3_ACBsDiv or LCCR3_ACBsCntOff 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Code Status: 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1999/04/01: 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Driver appears to be working for Brutus 320x200x8bpp mode. Other 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resolutions are working, but only the 8bpp mode is supported. 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Changes need to be made to the palette encode and decode routines 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to support 4 and 16 bpp modes. 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver is not designed to be a module. The FrameBuffer is statically 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocated since dynamic allocation of a 300k buffer cannot be 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * guaranteed. 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1999/06/17: 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - FrameBuffer memory is now allocated at run-time when the 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * driver is initialized. 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 692f82af08fcc7dc01a7e98a49a5995a77e32a2925Nicolas Pitre * 2000/04/10: Nicolas Pitre <nico@fluxnic.net> 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Big cleanup for dynamic selection of machine type at run time. 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Support for Bitsy aka Compaq iPAQ H3600 added. 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com> 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Jeff Sutherland <jsutherland@accelent.com> 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Resolved an issue caused by a change made to the Assabet's PLD 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * earlier this year which broke the framebuffer driver for newer 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Phase 4 Assabets. Some other parameters were changed to optimize 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for the Sharp display. 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp> 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - XP860 support added 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/08/19: Mark Huang <mhuang@livetoy.com> 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Allows standard options to be passed on the kernel command line 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for most common passive displays. 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/08/29: 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - s/save_flags_cli/local_irq_save/ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Updated LART stuff. Fixed some minor bugs. 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw> 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Pangolin support added 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de> 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Huw Webpanel support added 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2000/11/23: Eric Peng <ericpeng@coventive.com> 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Freebird add 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Cliff Brake <cbrake@accelent.com> 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Added PM callback 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/05/26: <rmk@arm.linux.org.uk> 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Fix 16bpp so that (a) we use the right colours rather than some 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * totally random colour depending on what was in page 0, and (b) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we don't de-reference a NULL pointer. 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - remove duplicated implementation of consistent_alloc() 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - convert dma address types to dma_addr_t 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - remove unused 'montype' stuff 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - remove redundant zero inits of init_var after the initial 11759f0cb0fddc14ffc6676ae62e911f8115ebc8ccfRussell King * memset. 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - remove allow_modeset (acornfb idea does not belong here) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/05/28: <rmk@arm.linux.org.uk> 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - massive cleanup - move machine dependent data into structures 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - I've left various #warnings in - if you see one, and know 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware concerned, please get in contact with me. 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/05/31: <rmk@arm.linux.org.uk> 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Fix LCCR1 HSW value, fix all machine type specifications to 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * keep values in line. (Please check your machine type specs) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/06/10: <rmk@arm.linux.org.uk> 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Fiddle with the LCD controller from task context only; mainly 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * so that we can run with interrupts on, and sleep. 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Convert #warnings into #errors. No pain, no gain. ;) 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/06/14: <rmk@arm.linux.org.uk> 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Make the palette BPS value for 12bpp come out correctly. 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Take notice of "greyscale" on any colour depth. 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Make truecolor visuals use the RGB channel encoding information. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/07/02: <rmk@arm.linux.org.uk> 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Fix colourmap problems. 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/07/13: <abraham@2d3d.co.za> 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Added support for the ICP LCD-Kit01 on LART. This LCD is 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * manufactured by Prime View, model no V16C6448AB 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/07/23: <rmk@arm.linux.org.uk> 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Hand merge version from handhelds.org CVS tree. See patch 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * notes for 595/1 for more information. 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Drop 12bpp (it's 16bpp with different colour register mappings). 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - This hardware can not do direct colour. Therefore we don't 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * support it. 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/07/27: <rmk@arm.linux.org.uk> 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Halve YRES on dual scan LCDs. 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/08/22: <rmk@arm.linux.org.uk> 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Add b/w iPAQ pixclock value. 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001/10/12: <rmk@arm.linux.org.uk> 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - Add patch 681/1 and clean up stork definitions. 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 17027ac792ca0b0a1e7e65f20342260650516c95864Andrea Righi#include <linux/mm.h> 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h> 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cpufreq.h> 176d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h> 1787951ac91c7d45b61f54f1cdabc24b52b40785de6Matthias Kaehlcke#include <linux/mutex.h> 179997302259f386bca8fe1db67c50296ca426c438fRussell King#include <linux/io.h> 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h> 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach-types.h> 183a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/assabet.h> 184a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/shannon.h> 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * debugging? 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG 0 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Complain if VAR is out of range. 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_VAR 1 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ASSABET_PAL_VIDEO 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sa1100fb.h" 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void (*sa1100fb_backlight_power)(int on); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void (*sa1100fb_lcd_power)(int on); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2020a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewskistatic struct sa1100fb_rgb rgb_4 = { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = { .offset = 0, .length = 4, }, 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = { .offset = 0, .length = 4, }, 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = { .offset = 0, .length = 4, }, 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .transp = { .offset = 0, .length = 0, }, 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2090a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewskistatic struct sa1100fb_rgb rgb_8 = { 2100a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski .red = { .offset = 0, .length = 8, }, 2110a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski .green = { .offset = 0, .length = 8, }, 2120a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski .blue = { .offset = 0, .length = 8, }, 2130a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski .transp = { .offset = 0, .length = 0, }, 2140a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski}; 2150a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_rgb def_rgb_16 = { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = { .offset = 11, .length = 5, }, 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = { .offset = 5, .length = 6, }, 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = { .offset = 0, .length = 5, }, 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .transp = { .offset = 0, .length = 0, }, 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_ASSABET 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef ASSABET_PAL_VIDEO 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * takes an RGB666 signal, but we provide it with an RGB565 signal 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instead (def_rgb_16). 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info lq039q2ds54_info __initdata = { 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 171521, .bpp = 16, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 5, .vsync_len = 1, 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 61, .upper_margin = 3, 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 9, .lower_margin = 0, 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info pal_info __initdata = { 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 67797, .bpp = 16, 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, .yres = 512, 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 64, .vsync_len = 6, 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 125, .upper_margin = 70, 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 115, .lower_margin = 36, 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_H3600 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info h3600_info __initdata = { 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 174757, .bpp = 16, 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 3, .vsync_len = 3, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 12, .upper_margin = 10, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 17, .lower_margin = 1, 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmap_static = 1, 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_rgb h3600_rgb_16 = { 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .red = { .offset = 12, .length = 4, }, 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .green = { .offset = 7, .length = 4, }, 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .blue = { .offset = 1, .length = 4, }, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .transp = { .offset = 0, .length = 0, }, 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_H3100 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info h3100_info __initdata = { 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 406977, .bpp = 4, 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 26, .vsync_len = 41, 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 4, .upper_margin = 0, 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 4, .lower_margin = 0, 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmap_greyscale = 1, 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmap_inverse = 1, 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas, 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_COLLIE 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info collie_info __initdata = { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 171521, .bpp = 16, 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 5, .vsync_len = 1, 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 11, .upper_margin = 2, 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 30, .lower_margin = 0, 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2), 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_GREY_LCD 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info lart_grey_info __initdata = { 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 150000, .bpp = 4, 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 1, .vsync_len = 1, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 4, .upper_margin = 0, 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 2, .lower_margin = 0, 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .cmap_greyscale = 1, 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono, 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512), 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_COLOR_LCD 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info lart_color_info __initdata = { 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 150000, .bpp = 16, 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 320, .yres = 240, 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 2, .vsync_len = 3, 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 69, .upper_margin = 14, 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 8, .lower_margin = 4, 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_VIDEO_OUT 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info lart_video_info __initdata = { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 39721, .bpp = 16, 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, .yres = 480, 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 95, .vsync_len = 2, 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 40, .upper_margin = 32, 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 24, .lower_margin = 11, 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512), 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_KIT01_LCD 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info lart_kit01_info __initdata = { 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 63291, .bpp = 16, 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, .yres = 480, 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 64, .vsync_len = 3, 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 122, .upper_margin = 45, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 10, .lower_margin = 10, 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act, 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_SHANNON 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info shannon_info __initdata = { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pixclock = 152500, .bpp = 8, 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xres = 640, .yres = 480, 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hsync_len = 4, .vsync_len = 3, 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .left_margin = 2, .upper_margin = 0, 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .right_margin = 1, .lower_margin = 0, 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas, 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lccr3 = LCCR3_ACBsDiv(512), 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_mach_info * __init 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_get_machine_info(struct sa1100fb_info *fbi) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_mach_info *inf = NULL; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * R G B T 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * default {11,5}, { 5,6}, { 0,5}, { 0,0} 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * h3600 {12,4}, { 7,4}, { 1,4}, { 0,0} 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * freebird { 8,4}, { 4,4}, { 0,4}, {12,4} 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_ASSABET 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_assabet()) { 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef ASSABET_PAL_VIDEO 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &lq039q2ds54_info; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &pal_info; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_H3100 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_h3100()) { 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &h3100_info; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_H3600 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_h3600()) { 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &h3600_info; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->rgb[RGB_16] = &h3600_rgb_16; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_COLLIE 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_collie()) { 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &collie_info; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_LART 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_lart()) { 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_GREY_LCD 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &lart_grey_info; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_COLOR_LCD 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &lart_color_info; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_VIDEO_OUT 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &lart_video_info; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LART_KIT01_LCD 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &lart_kit01_info; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SA1100_SHANNON 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_shannon()) { 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = &shannon_info; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return inf; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void sa1100fb_schedule_work(struct sa1100fb_info *fbi, u_int state) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We need to handle two requests being made at the same time. 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There are two important cases: 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must perform the unblanking, which will do our REENABLE for us. 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. When we are blanking, but immediately unblank before we have 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blanked. We do the "REENABLE" thing here as well, just to be sure. 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->task_state == C_ENABLE && state == C_REENABLE) 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = (u_int) -1; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->task_state == C_DISABLE && state == C_ENABLE) 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = C_REENABLE; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state != (u_int)-1) { 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->task_state = state; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_work(&fbi->task); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan &= 0xffff; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chan >>= 16 - bf->length; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return chan << bf->offset; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert bits-per-pixel to a hardware palette PBS value. 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u_int palette_pbs(struct fb_var_screeninfo *var) 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (var->bits_per_pixel) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: ret = 0 << 12; break; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: ret = 1 << 12; break; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 16: ret = 2 << 12; break; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int trans, struct fb_info *info) 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int val, ret = 1; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno < fbi->palette_size) { 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = ((red >> 4) & 0xf00); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= ((green >> 8) & 0x0f0); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= ((blue >> 12) & 0x00f); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno == 0) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= palette_pbs(&fbi->fb.var); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_cpu[regno] = val; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int trans, struct fb_info *info) 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int val; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 1; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If inverse mode was selected, invert all the colours 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rather than the register number. The register number 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is what you poke into the framebuffer to produce the 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * colour you requested. 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->cmap_inverse) { 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds red = 0xffff - red; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds green = 0xffff - green; 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds blue = 0xffff - blue; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If greyscale is true, then we convert the RGB value 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to greyscale no mater what visual we are using. 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->fb.var.grayscale) 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds red = green = blue = (19595 * red + 38470 * green + 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471 * blue) >> 16; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fbi->fb.fix.visual) { 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_VISUAL_TRUECOLOR: 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12 or 16-bit True Colour. We encode the RGB value 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * according to the RGB bitfield information. 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (regno < 16) { 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *pal = fbi->fb.pseudo_palette; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = chan_to_field(red, &fbi->fb.var.red); 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= chan_to_field(green, &fbi->fb.var.green); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val |= chan_to_field(blue, &fbi->fb.var.blue); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pal[regno] = val; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_VISUAL_STATIC_PSEUDOCOLOR: 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_VISUAL_PSEUDOCOLOR: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = sa1100fb_setpalettereg(regno, red, green, blue, trans, info); 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5776edb7467be2195e7eeb6844e37668253af216100Pavel Machek#ifdef CONFIG_CPU_FREQ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_display_dma_period() 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate the minimum period (in picoseconds) between two DMA 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * requests for the LCD controller. If we hit this, it means we're 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doing nothing but LCD DMA. 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 584fc1df37e3b195cb73ecb14c30d41b7aace3f844aRussell Kingstatic inline unsigned int sa1100fb_display_dma_period(struct fb_var_screeninfo *var) 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Period = pixclock * bits_per_byte * bytes_per_transfer 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * / memory_bits_per_pixel; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return var->pixclock * 8 * 16 / var->bits_per_pixel; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5926edb7467be2195e7eeb6844e37668253af216100Pavel Machek#endif 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_check_var(): 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Round up in the following order: bits_per_pixel, xres, 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * bitfields, horizontal timing, vertical timing. 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rgbidx; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->xres < MIN_XRES) 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xres = MIN_XRES; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->yres < MIN_YRES) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yres = MIN_YRES; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->xres > fbi->max_xres) 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xres = fbi->max_xres; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->yres > fbi->max_yres) 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yres = fbi->max_yres; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xres_virtual = max(var->xres_virtual, var->xres); 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yres_virtual = max(var->yres_virtual, var->yres); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (var->bits_per_pixel) { 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 6200a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski rgbidx = RGB_4; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 8: 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rgbidx = RGB_8; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 16: 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rgbidx = RGB_16; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copy the RGB parameters for this display 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from the machine specific parameters. 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red = fbi->rgb[rgbidx]->red; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->green = fbi->rgb[rgbidx]->green; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->blue = fbi->rgb[rgbidx]->blue; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp = fbi->rgb[rgbidx]->transp; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("RGBT length = %d:%d:%d:%d\n", 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.length, var->green.length, var->blue.length, 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.length); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("RGBT offset = %d:%d:%d:%d\n", 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->red.offset, var->green.offset, var->blue.offset, 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->transp.offset); 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_FREQ 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_display_dma_period(var), 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpufreq_get(smp_processor_id())); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void sa1100fb_set_truecolor(u_int is_true_color) 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_assabet()) { 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 1 // phase 4 or newer Assabet's 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (is_true_color) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // older Assabet's 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (is_true_color) 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_set_par(): 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the user defined part of the display for the specified console 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sa1100fb_set_par(struct fb_info *info) 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_var_screeninfo *var = &info->var; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long palette_mem_size; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("set_par\n"); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->bits_per_pixel == 16) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!fbi->cmap_static) 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some people have weird ideas about wanting static 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pseudocolor maps. I suspect their user space 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * applications are broken. 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.line_length = var->xres_virtual * 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->bits_per_pixel / 8; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds palette_mem_size = fbi->palette_size * sizeof(u16); 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set (any) board control register to handle new color depth 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_activate_var(var, fbi); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fb_info *info) 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make sure the user isn't doing something stupid. 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static)) 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return gen_set_cmap(cmap, kspc, con, info); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Formal definition of the VESA spec: 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This refers to the state of the display when it is in full operation 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stand-By 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This defines an optional operating state of minimal power reduction with 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the shortest recovery time 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Suspend 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This refers to a level of power management in which substantial power 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reduction is achieved by the display. The display can have a longer 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * recovery time from this state than from the Stand-by state 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Off 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This indicates that the display is consuming the lowest level of power 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and is non-operational. Recovery from this state may optionally require 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user to manually power on the monitor 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Now, the fbdev driver adds an additional state, (blank), where they 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * turn off the video (maybe by colormap tricks), but don't mess with the 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video itself: think of it semantically between on and Stand-By. 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * So here's what we should do in our fbdev blank routine: 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VESA_NO_BLANKING (mode 0) Video on, front/back light on 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VESA_POWERDOWN (mode 3) Video off, front/back light off 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This will match the matrox implementation. 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_blank(): 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Blank the display by setting all palette values to zero. Note, the 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12 and 16 bpp modes don't really use the palette, so this will not 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blank the display in all modes. 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sa1100fb_blank(int blank, struct fb_info *info) 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("sa1100fb_blank: blank=%d\n", blank); 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (blank) { 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_POWERDOWN: 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_VSYNC_SUSPEND: 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_HSYNC_SUSPEND: 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_NORMAL: 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < fbi->palette_size; i++) 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_setpalettereg(i, 0, 0, 0, 0, info); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_schedule_work(fbi, C_DISABLE); 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case FB_BLANK_UNBLANK: 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR || 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fb_set_cmap(&fbi->fb.cmap, info); 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_schedule_work(fbi, C_ENABLE); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801216d526c89d144928f095f2800bc6c67e968d628Christoph Hellwigstatic int sa1100fb_mmap(struct fb_info *info, 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vm_area_struct *vma) 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT; 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (off < info->fix.smem_len) { 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_pgoff += 1; /* skip over the palette */ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dma_mmap_writecombine(fbi->dev, vma, fbi->map_cpu, 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->map_dma, fbi->map_size); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = info->fix.mmio_start; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((vma->vm_end - vma->vm_start + off) > len) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds off += start & PAGE_MASK; 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_pgoff = off >> PAGE_SHIFT; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_flags |= VM_IO; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_end - vma->vm_start, 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vma->vm_page_prot); 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_ops sa1100fb_ops = { 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_check_var = sa1100fb_check_var, 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_set_par = sa1100fb_set_par, 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// .fb_set_cmap = sa1100fb_set_cmap, 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_setcolreg = sa1100fb_setcolreg, 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_fillrect = cfb_fillrect, 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_copyarea = cfb_copyarea, 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_imageblit = cfb_imageblit, 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_blank = sa1100fb_blank, 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fb_mmap = sa1100fb_mmap, 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate the PCD value from the clock rate (in picoseconds). 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We take account of the PPCR clock setting. 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline unsigned int get_pcd(unsigned int pixclock, unsigned int cpuclock) 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int pcd = cpuclock / 100; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcd *= pixclock; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcd /= 10000000; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return pcd + 1; /* make up for integer math truncations */ 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_activate_var(): 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configures LCD Controller based on entries in var parameter. Settings are 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only written to the controller if changes were made. 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi) 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_lcd_reg new_regs; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int half_screen_size, yres, pcd; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_long flags; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("Configuring SA1100 LCD\n"); 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n", 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->xres, var->hsync_len, 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->left_margin, var->right_margin); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n", 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->yres, var->vsync_len, 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds var->upper_margin, var->lower_margin); 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_VAR 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->xres < 16 || var->xres > 1024) 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid xres %d\n", 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->xres); 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->hsync_len < 1 || var->hsync_len > 64) 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid hsync_len %d\n", 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->hsync_len); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->left_margin < 1 || var->left_margin > 255) 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid left_margin %d\n", 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->left_margin); 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->right_margin < 1 || var->right_margin > 255) 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid right_margin %d\n", 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->right_margin); 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->yres < 1 || var->yres > 1024) 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid yres %d\n", 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->yres); 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->vsync_len < 1 || var->vsync_len > 64) 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid vsync_len %d\n", 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->vsync_len); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->upper_margin < 0 || var->upper_margin > 255) 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid upper_margin %d\n", 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->upper_margin); 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (var->lower_margin < 0 || var->lower_margin > 255) 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "%s: invalid lower_margin %d\n", 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.id, var->lower_margin); 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_regs.lccr0 = fbi->lccr0 | 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0_LEN | LCCR0_LDM | LCCR0_BAM | 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0); 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_regs.lccr1 = 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR1_DisWdth(var->xres) + 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR1_HorSnchWdth(var->hsync_len) + 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR1_BegLnDel(var->left_margin) + 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR1_EndLnDel(var->right_margin); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we have a dual scan LCD, then we need to halve 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the YRES parameter. 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yres = var->yres; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->lccr0 & LCCR0_Dual) 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds yres /= 2; 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_regs.lccr2 = 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR2_DisHght(yres) + 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR2_VrtSnchWdth(var->vsync_len) + 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR2_BegFrmDel(var->upper_margin) + 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR2_EndFrmDel(var->lower_margin); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcd = get_pcd(var->pixclock, cpufreq_get(0)); 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 | 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) | 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL); 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0); 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1); 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds half_screen_size = var->bits_per_pixel; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds half_screen_size = half_screen_size * var->xres * var->yres / 16; 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Update shadow copy atomically */ 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_save(flags); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->dbar1 = fbi->palette_dma; 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->dbar2 = fbi->screen_dma + half_screen_size; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->reg_lccr0 = new_regs.lccr0; 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->reg_lccr1 = new_regs.lccr1; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->reg_lccr2 = new_regs.lccr2; 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->reg_lccr3 = new_regs.lccr3; 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_restore(flags); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only update the registers if the controller is enabled 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and something has changed. 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) || 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) || 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2)) 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_schedule_work(fbi, C_REENABLE); 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE! The following functions are purely helpers for set_ctrlr_state. 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do not call them directly; set_ctrlr_state does the correct serialisation 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to ensure that things happen in the right way 100% of time time. 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -- rmk 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on) 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("backlight o%s\n", on ? "n" : "ff"); 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sa1100fb_backlight_power) 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_backlight_power(on); 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on) 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("LCD power o%s\n", on ? "n" : "ff"); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sa1100fb_lcd_power) 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_lcd_power(on); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sa1100fb_setup_gpio(struct sa1100fb_info *fbi) 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int mask = 0; 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable GPIO<9:2> for LCD use if: 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Active display, or 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. Color Dual Passive display 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * see table 11.8 on page 11-27 in the SA1100 manual 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -- Erik. 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SA1110 spec update nr. 25 says we can and should 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clear LDD15 to 12 for 4 or 8bpp modes with active 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * panels. 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color && 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) { 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->fb.var.bits_per_pixel > 8 || 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual) 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask) { 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GPDR |= mask; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GAFR |= mask; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sa1100fb_enable_controller(struct sa1100fb_info *fbi) 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("Enabling LCD controller\n"); 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Make sure the mode bits are present in the first palette entry 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_cpu[0] &= 0xcfff; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var); 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sequence from 11.7.10 */ 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR3 = fbi->reg_lccr3; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR2 = fbi->reg_lccr2; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR1 = fbi->reg_lccr1; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBAR1 = fbi->dbar1; 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DBAR2 = fbi->dbar2; 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0 |= LCCR0_LEN; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_shannon()) { 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GPDR |= SHANNON_GPIO_DISP_EN; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GPSR |= SHANNON_GPIO_DISP_EN; 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("DBAR1 = 0x%08x\n", DBAR1); 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("DBAR2 = 0x%08x\n", DBAR2); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("LCCR0 = 0x%08x\n", LCCR0); 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("LCCR1 = 0x%08x\n", LCCR1); 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("LCCR2 = 0x%08x\n", LCCR2); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("LCCR3 = 0x%08x\n", LCCR3); 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sa1100fb_disable_controller(struct sa1100fb_info *fbi) 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DPRINTK("Disabling LCD controller\n"); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_shannon()) { 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GPCR |= SHANNON_GPIO_DISP_EN; 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_UNINTERRUPTIBLE); 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&fbi->ctrlr_wait, &wait); 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCSR = 0xffffffff; /* Clear LCD Status Register */ 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */ 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */ 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule_timeout(20 * HZ / 1000); 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&fbi->ctrlr_wait, &wait); 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_handle_irq: Handle 'LCD DONE' interrupts. 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10727d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id) 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = dev_id; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int lcsr = LCSR; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lcsr & LCSR_LDD) { 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCCR0 |= LCCR0_LDM; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&fbi->ctrlr_wait); 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LCSR = lcsr; 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function must be called from task context only, since it will 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sleep when disabling the LCD controller, or if we get two contending 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * processes trying to alter state. 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int old_state; 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10957951ac91c7d45b61f54f1cdabc24b52b40785de6Matthias Kaehlcke mutex_lock(&fbi->ctrlr_lock); 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_state = fbi->state; 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Hack around fbcon initialisation. 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state == C_STARTUP && state == C_REENABLE) 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = C_ENABLE; 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (state) { 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_DISABLE_CLKCHANGE: 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disable controller for clock change. If the 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controller is already disabled, then do nothing. 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state != C_DISABLE && old_state != C_DISABLE_PM) { 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->state = state; 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_disable_controller(fbi); 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_DISABLE_PM: 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_DISABLE: 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disable controller 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state != C_DISABLE) { 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->state = state; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __sa1100fb_backlight_power(fbi, 0); 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state != C_DISABLE_CLKCHANGE) 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_disable_controller(fbi); 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __sa1100fb_lcd_power(fbi, 0); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_ENABLE_CLKCHANGE: 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable the controller after clock change. Only 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do this if we were disabled for the clock change. 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state == C_DISABLE_CLKCHANGE) { 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->state = C_ENABLE; 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_enable_controller(fbi); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_REENABLE: 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Re-enable the controller only if it was already 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * enabled. This is so we reprogram the control 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers. 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state == C_ENABLE) { 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_disable_controller(fbi); 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_setup_gpio(fbi); 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_enable_controller(fbi); 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_ENABLE_PM: 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Re-enable the controller after PM. This is not 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perfect - think about the case where we were doing 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a clock change, and we suspended half-way through. 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state != C_DISABLE_PM) 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fall through */ 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case C_ENABLE: 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Power up the LCD screen, enable controller, and 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * turn on the backlight. 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_state != C_ENABLE) { 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->state = C_ENABLE; 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_setup_gpio(fbi); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __sa1100fb_lcd_power(fbi, 1); 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_enable_controller(fbi); 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __sa1100fb_backlight_power(fbi, 1); 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11807951ac91c7d45b61f54f1cdabc24b52b40785de6Matthias Kaehlcke mutex_unlock(&fbi->ctrlr_lock); 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Our LCD controller task (which is called when we blank or unblank) 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * via keventd. 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11872343217fb770ef2b172a12186c0cd0526bfb7d0cPavel Machekstatic void sa1100fb_task(struct work_struct *w) 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11892343217fb770ef2b172a12186c0cd0526bfb7d0cPavel Machek struct sa1100fb_info *fbi = container_of(w, struct sa1100fb_info, task); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int state = xchg(&fbi->task_state, -1); 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_ctrlr_state(fbi, state); 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_FREQ 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate the minimum DMA period over all displays that we own. 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This, together with the SDRAM bandwidth defines the slowest CPU 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * frequency that can be selected. 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi) 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int min_period = (unsigned int)-1; 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct display *disp = &fb_display[i]; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int period; 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do we own this display? 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (disp->fb_info != &fbi->fb) 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ok, calculate its DMA period 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds period = sa1100fb_display_dma_period(&disp->var); 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (period < min_period) 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds min_period = period; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return min_period; 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: we need to verify _all_ consoles. 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sa1100fb_display_dma_period(&fbi->fb.var); 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CPU clock speed change handler. We need to adjust the LCD timing 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * parameters when the CPU clock is adjusted by the power management 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * subsystem. 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_freq_transition(struct notifier_block *nb, unsigned long val, 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *data) 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = TO_INF(nb, freq_transition); 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpufreq_freqs *f = data; 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_int pcd; 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (val) { 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_PRECHANGE: 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_POSTCHANGE: 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pcd = get_pcd(fbi->fb.var.pixclock, f->new); 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE); 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssa1100fb_freq_policy(struct notifier_block *nb, unsigned long val, 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *data) 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct cpufreq_policy *policy = data; 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (val) { 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_ADJUST: 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_INCOMPATIBLE: 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_DEBUG "min dma period: %d ps, " 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds policy->max); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* todo: fill in min/max values */ 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case CPUFREQ_NOTIFY: 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do {} while(0); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* todo: panic if min/max values aren't fulfilled 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * [can't really happen unless there's a bug in the 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CPU policy verififcation process * 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Power management hooks. Note that we won't be called from IRQ context, 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unlike the blank functions above, so we may sleep. 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12933ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int sa1100fb_suspend(struct platform_device *dev, pm_message_t state) 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12953ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct sa1100fb_info *fbi = platform_get_drvdata(dev); 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12979480e307cd88ef09ec9294c7d97ebec18e6d2221Russell King set_ctrlr_state(fbi, C_DISABLE_PM); 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13013ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic int sa1100fb_resume(struct platform_device *dev) 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13033ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King struct sa1100fb_info *fbi = platform_get_drvdata(dev); 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13059480e307cd88ef09ec9294c7d97ebec18e6d2221Russell King set_ctrlr_state(fbi, C_ENABLE_PM); 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sa1100fb_suspend NULL 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define sa1100fb_resume NULL 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sa1100fb_map_video_memory(): 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocates the DRAM memory for the frame buffer. This buffer is 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remapped into a non-cached, non-buffered, memory region to 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allow palette and pixel writes to occur without flushing the 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * cache. Once this area is remapped, all virtual memory 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * access to the video memory should occur at the new region. 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi) 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We reserve one page for the palette, plus the size 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the framebuffer. 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE); 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &fbi->map_dma, GFP_KERNEL); 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fbi->map_cpu) { 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE; 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->screen_dma = fbi->map_dma + PAGE_SIZE; 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME: this is actually the wrong thing to place in 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * smem_start. But fbdev suffers from the problem that 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it needs an API which doesn't exist (in this case, 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dma_writecombine_mmap) 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.smem_start = fbi->screen_dma; 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fbi->map_cpu ? 0 : -ENOMEM; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Fake monspecs to fill in fbinfo structure */ 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct fb_monspecs monspecs __initdata = { 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hfmin = 30000, 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .hfmax = 70000, 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vfmin = 50, 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vfmax = 65, 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev) 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_mach_info *inf; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi; 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16, 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!fbi) 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(fbi, 0, sizeof(struct sa1100fb_info)); 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->dev = dev; 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(fbi->fb.fix.id, SA1100_NAME); 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS; 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.type_aux = 0; 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.xpanstep = 0; 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.ypanstep = 0; 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.ywrapstep = 0; 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.accel = FB_ACCEL_NONE; 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.nonstd = 0; 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.activate = FB_ACTIVATE_NOW; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.height = -1; 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.width = -1; 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.accel_flags = 0; 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.vmode = FB_VMODE_NONINTERLACED; 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fbops = &sa1100fb_ops; 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.flags = FBINFO_DEFAULT; 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.monspecs = monspecs; 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.pseudo_palette = (fbi + 1); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13890a4534801468325fdb6a7b7bf73ad2a958a1e379Michal Januszewski fbi->rgb[RGB_4] = &rgb_4; 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->rgb[RGB_8] = &rgb_8; 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->rgb[RGB_16] = &def_rgb_16; 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf = sa1100fb_get_machine_info(fbi); 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * People just don't seem to get this. We don't support 13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * anything but correct entries now, so panic if someone 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does something stupid. 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inf->lccr3 & (LCCR3_VrtSnchL|LCCR3_HorSnchL|0xff) || 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inf->pixclock == 0) 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds panic("sa1100fb error: invalid LCCR3 fields set or zero " 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "pixclock."); 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->max_xres = inf->xres; 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.xres = inf->xres; 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.xres_virtual = inf->xres; 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->max_yres = inf->yres; 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.yres = inf->yres; 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.yres_virtual = inf->yres; 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->max_bpp = inf->bpp; 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.bits_per_pixel = inf->bpp; 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.pixclock = inf->pixclock; 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.hsync_len = inf->hsync_len; 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.left_margin = inf->left_margin; 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.right_margin = inf->right_margin; 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.vsync_len = inf->vsync_len; 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.upper_margin = inf->upper_margin; 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.lower_margin = inf->lower_margin; 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.sync = inf->sync; 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.var.grayscale = inf->cmap_greyscale; 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->cmap_inverse = inf->cmap_inverse; 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->cmap_static = inf->cmap_static; 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->lccr0 = inf->lccr0; 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->lccr3 = inf->lccr3; 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->state = C_STARTUP; 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->task_state = (u_char)-1; 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->max_bpp / 8; 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_waitqueue_head(&fbi->ctrlr_wait); 14322343217fb770ef2b172a12186c0cd0526bfb7d0cPavel Machek INIT_WORK(&fbi->task, sa1100fb_task); 14337951ac91c7d45b61f54f1cdabc24b52b40785de6Matthias Kaehlcke mutex_init(&fbi->ctrlr_lock); 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return fbi; 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1438c2e13037e6794bd0d9de3f9ecabf5615f15c160bUwe Kleine-Königstatic int __devinit sa1100fb_probe(struct platform_device *pdev) 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sa1100fb_info *fbi; 1441e9368f8288338c25d8a339c91b15e17ebf33752dRussell King int ret, irq; 1442e9368f8288338c25d8a339c91b15e17ebf33752dRussell King 1443e9368f8288338c25d8a339c91b15e17ebf33752dRussell King irq = platform_get_irq(pdev, 0); 1444489447380a2921ec0e9154f773c44ab3167ede4bDavid Vrabel if (irq < 0) 1445e9368f8288338c25d8a339c91b15e17ebf33752dRussell King return -EINVAL; 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!request_mem_region(0xb0100000, 0x10000, "LCD")) 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14503ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King fbi = sa1100fb_init_fbinfo(&pdev->dev); 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!fbi) 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Initialize video memory */ 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = sa1100fb_map_video_memory(fbi); 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1460f8798ccbefc0e4ef7438c080b7ba0410738c8cfaYong Zhang ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi); 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ASSABET_PAL_VIDEO 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (machine_is_assabet()) 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASSABET_BCR_clear(ASSABET_BCR_LCD_ON); 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This makes sure that our colour bitfield 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptors are correctly initialised. 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa1100fb_check_var(&fbi->fb.var, &fbi->fb); 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14773ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_set_drvdata(pdev, fbi); 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = register_framebuffer(&fbi->fb); 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1481e9368f8288338c25d8a339c91b15e17ebf33752dRussell King goto err_free_irq; 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CPU_FREQ 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->freq_transition.notifier_call = sa1100fb_freq_transition; 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fbi->freq_policy.notifier_call = sa1100fb_freq_policy; 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER); 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This driver cannot be unloaded at the moment */ 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1493e9368f8288338c25d8a339c91b15e17ebf33752dRussell King err_free_irq: 1494e9368f8288338c25d8a339c91b15e17ebf33752dRussell King free_irq(irq, fbi); 1495e9368f8288338c25d8a339c91b15e17ebf33752dRussell King failed: 14963ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King platform_set_drvdata(pdev, NULL); 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(fbi); 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_mem_region(0xb0100000, 0x10000); 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15023ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell Kingstatic struct platform_driver sa1100fb_driver = { 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = sa1100fb_probe, 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = sa1100fb_suspend, 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = sa1100fb_resume, 15063ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .driver = { 15073ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King .name = "sa11x0-fb", 15083ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King }, 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init sa1100fb_init(void) 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fb_get_options("sa1100fb", NULL)) 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15163ae5eaec1d2d9c0cf53745352e7d4b152810ba24Russell King return platform_driver_register(&sa1100fb_driver); 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init sa1100fb_setup(char *options) 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *this_opt; 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!options || !*options) 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((this_opt = strsep(&options, ",")) != NULL) { 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "bpp:", 4)) 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_par.max_bpp = 15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple_strtoul(this_opt + 4, NULL, 0); 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "lccr0:", 6)) 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lcd_shadow.lccr0 = 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple_strtoul(this_opt + 6, NULL, 0); 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "lccr1:", 6)) { 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lcd_shadow.lccr1 = 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple_strtoul(this_opt + 6, NULL, 0); 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_par.max_xres = 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (lcd_shadow.lccr1 & 0x3ff) + 16; 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "lccr2:", 6)) { 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lcd_shadow.lccr2 = 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple_strtoul(this_opt + 6, NULL, 0); 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_par.max_yres = 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (lcd_shadow. 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lccr0 & LCCR0_SDS) ? ((lcd_shadow. 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lccr2 & 0x3ff) + 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1) * 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2 : ((lcd_shadow.lccr2 & 0x3ff) + 1); 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(this_opt, "lccr3:", 6)) 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lcd_shadow.lccr3 = 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds simple_strtoul(this_opt + 6, NULL, 0); 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sa1100fb_init); 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("StrongARM-1100/1110 framebuffer driver"); 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 1563