📄 sa1100fb.c
字号:
/* * linux/drivers/video/sa1100fb.c * * Copyright (C) 1999 Eric A. Thomas * Based on acornfb.c Copyright (C) Russell King. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * * StrongARM 1100 LCD Controller Frame Buffer Driver * * Please direct your questions and comments on this driver to the following * email address: * * linux-arm-kernel@lists.arm.linux.org.uk * * Clean patches should be sent to the ARM Linux Patch System. Please see the * following web page for more information: * * http://www.arm.linux.org.uk/developer/patches/info.shtml * * Thank you. * * Known problems: * - With the Neponset plugged into an Assabet, LCD powerdown * doesn't work (LCD stays powered up). Therefore we shouldn't * blank the screen. * - We don't limit the CPU clock rate nor the mode selection * according to the available SDRAM bandwidth. * * Other notes: * - Linear grayscale palettes and the kernel. * Such code does not belong in the kernel. The kernel frame buffer * drivers do not expect a linear colourmap, but a colourmap based on * the VT100 standard mapping. * * If your _userspace_ requires a linear colourmap, then the setup of * such a colourmap belongs _in userspace_, not in the kernel. Code * to set the colourmap correctly from user space has been sent to * David Neuer. It's around 8 lines of C code, plus another 4 to * detect if we are using grayscale. * * Code Status: * 1999/04/01: * - Driver appears to be working for Brutus 320x200x8bpp mode. Other * resolutions are working, but only the 8bpp mode is supported. * Changes need to be made to the palette encode and decode routines * to support 4 and 16 bpp modes. * Driver is not designed to be a module. The FrameBuffer is statically * allocated since dynamic allocation of a 300k buffer cannot be * guaranteed. * * 1999/06/17: * - FrameBuffer memory is now allocated at run-time when the * driver is initialized. * * 2000/04/10: Nicolas Pitre <nico@cam.org> * - Big cleanup for dynamic selection of machine type at run time. * * 2000/07/19: Jamey Hicks <jamey@crl.dec.com> * - Support for Bitsy aka Compaq iPAQ H3600 added. * * 2000/08/07: Tak-Shing Chan <tchan.rd@idthk.com> * Jeff Sutherland <jsutherland@accelent.com> * - Resolved an issue caused by a change made to the Assabet's PLD * earlier this year which broke the framebuffer driver for newer * Phase 4 Assabets. Some other parameters were changed to optimize * for the Sharp display. * * 2000/08/09: Kunihiko IMAI <imai@vasara.co.jp> * - XP860 support added * * 2000/08/19: Mark Huang <mhuang@livetoy.com> * - Allows standard options to be passed on the kernel command line * for most common passive displays. * * 2000/08/29: * - s/save_flags_cli/local_irq_save/ * - remove unneeded extra save_flags_cli in sa1100fb_enable_lcd_controller * * 2000/10/10: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> * - Updated LART stuff. Fixed some minor bugs. * * 2000/10/30: Murphy Chen <murphy@mail.dialogue.com.tw> * - Pangolin support added * * 2000/10/31: Roman Jordan <jor@hoeft-wessel.de> * - Huw Webpanel support added * * 2000/11/23: Eric Peng <ericpeng@coventive.com> * - Freebird add * * 2001/02/07: Jamey Hicks <jamey.hicks@compaq.com> * Cliff Brake <cbrake@accelent.com> * - Added PM callback * * 2001/05/26: <rmk@arm.linux.org.uk> * - Fix 16bpp so that (a) we use the right colours rather than some * totally random colour depending on what was in page 0, and (b) * we don't de-reference a NULL pointer. * - remove duplicated implementation of consistent_alloc() * - convert dma address types to dma_addr_t * - remove unused 'montype' stuff * - remove redundant zero inits of init_var after the initial * memzero. * - remove allow_modeset (acornfb idea does not belong here) * * 2001/05/28: <rmk@arm.linux.org.uk> * - massive cleanup - move machine dependent data into structures * - I've left various #warnings in - if you see one, and know * the hardware concerned, please get in contact with me. * * 2001/05/31: <rmk@arm.linux.org.uk> * - Fix LCCR1 HSW value, fix all machine type specifications to * keep values in line. (Please check your machine type specs) * * 2001/06/10: <rmk@arm.linux.org.uk> * - Fiddle with the LCD controller from task context only; mainly * so that we can run with interrupts on, and sleep. * - Convert #warnings into #errors. No pain, no gain. ;) * * 2001/06/14: <rmk@arm.linux.org.uk> * - Make the palette BPS value for 12bpp come out correctly. * - Take notice of "greyscale" on any colour depth. * - Make truecolor visuals use the RGB channel encoding information. * * 2001/07/02: <rmk@arm.linux.org.uk> * - Fix colourmap problems. * * 2001/07/13: <abraham@2d3d.co.za> * - Added support for the ICP LCD-Kit01 on LART. This LCD is * manufactured by Prime View, model no V16C6448AB * * 2001/07/23: <rmk@arm.linux.org.uk> * - Hand merge version from handhelds.org CVS tree. See patch * notes for 595/1 for more information. * - Drop 12bpp (it's 16bpp with different colour register mappings). * - This hardware can not do direct colour. Therefore we don't * support it. * * 2001/07/27: <rmk@arm.linux.org.uk> * - Halve YRES on dual scan LCDs. * * 2001/08/22: <rmk@arm.linux.org.uk> * - Add b/w iPAQ pixclock value. * * 2001/10/12: <rmk@arm.linux.org.uk> * - Add patch 681/1 and clean up stork definitions. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/interrupt.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/init.h>#include <linux/cpufreq.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/mach-types.h>#include <asm/uaccess.h>#include <asm/arch/assabet.h>#include <video/fbcon.h>#include <video/fbcon-mfb.h>#include <video/fbcon-cfb4.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>/* * enable this if your panel appears to have broken */#undef CHECK_COMPAT/* * debugging? */#define DEBUG 0/* * Complain if VAR is out of range. */#define DEBUG_VAR 1#undef ASSABET_PAL_VIDEO#include "sa1100fb.h"void (*sa1100fb_blank_helper)(int blank);EXPORT_SYMBOL(sa1100fb_blank_helper);#ifdef CHECK_COMPATstatic voidsa1100fb_check_shadow(struct sa1100fb_lcd_reg *new_regs, struct fb_var_screeninfo *var, u_int pcd){ struct sa1100fb_lcd_reg shadow; int different = 0; /* * These machines are good machines! */ if (machine_is_assabet() || machine_is_h3600()) return; /* * The following ones are bad, bad, bad. * Please make yours good! */ if (machine_is_pangolin()) { DPRINTK("Configuring Pangolin LCD\n"); shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Act + LCCR0_LtlEnd + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(64) + LCCR1_BegLnDel(160) + LCCR1_EndLnDel(24); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(7) + LCCR2_BegFrmDel(7) + LCCR2_EndFrmDel(1); shadow.lccr3 = LCCR3_PixClkDiv(pcd) + LCCR3_HorSnchH + LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnH; DPRINTK("pcd = %x, PixCldDiv(pcd)=%x\n", pcd, LCCR3_PixClkDiv(pcd)); } if (machine_is_freebird()) { DPRINTK("Configuring Freebird LCD\n");#if 1 shadow.lccr0 = 0x00000038; shadow.lccr1 = 0x010108e0; shadow.lccr2 = 0x0000053f; shadow.lccr3 = 0x00000c20;#else shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_Pas + LCCR0_LtlEnd + LCCR0_DMADel(0); /* Check ,Chester */ shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(5) + LCCR1_BegLnDel(61) + LCCR1_EndLnDel(9); /* Check ,Chester */ shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + LCCR2_BegFrmDel(3) + LCCR2_EndFrmDel(0); /* Check ,Chester */ shadow.lccr3 = LCCR3_OutEnH + LCCR3_PixFlEdg + LCCR3_VrtSnchH + LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(pcd);#endif } if (machine_is_brutus()) { DPRINTK("Configuring Brutus LCD\n"); shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Pas + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) + LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); shadow.lccr3 = LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH + LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2) + LCCR3_PixClkDiv(44); } if (machine_is_huw_webpanel()) { DPRINTK("Configuring HuW LCD\n"); shadow.lccr0 = LCCR0_LEN + LCCR0_Dual + LCCR0_LDM; shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(3) + LCCR1_BegLnDel(41) + LCCR1_EndLnDel(101); shadow.lccr2 = 239 + LCCR2_VrtSnchWdth(1); shadow.lccr3 = 8 + LCCR3_OutEnH + LCCR3_PixRsEdg + LCCR3_VrtSnchH + LCCR3_HorSnchH + LCCR3_ACBsCntOff + LCCR3_ACBsDiv(2); } if (machine_is_lart()) { DPRINTK("Configuring LART LCD\n");#if defined LART_GREY_LCD shadow.lccr0 = LCCR0_LEN + LCCR0_Mono + LCCR0_Sngl + LCCR0_Pas + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(1) + LCCR1_BegLnDel(4) + LCCR1_EndLnDel(2); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(1) + LCCR2_BegFrmDel(0) + LCCR2_EndFrmDel(0); shadow.lccr3 = LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) + LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH;#endif#if defined LART_COLOR_LCD shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(2) + LCCR1_BegLnDel(69) + LCCR1_EndLnDel(8); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(3) + LCCR2_BegFrmDel(14) + LCCR2_EndFrmDel(4); shadow.lccr3 = LCCR3_PixClkDiv(34) + LCCR3_ACBsDiv(512) + LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL + LCCR3_PixFlEdg;#endif#if defined LART_VIDEO_OUT shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_BAM + LCCR0_ERM + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(640) + LCCR1_HorSnchWdth(95) + LCCR1_BegLnDel(40) + LCCR1_EndLnDel(24); shadow.lccr2 = LCCR2_DisHght(480) + LCCR2_VrtSnchWdth(2) + LCCR2_BegFrmDel(32) + LCCR2_EndFrmDel(11); shadow.lccr3 = LCCR3_PixClkDiv(8) + LCCR3_ACBsDiv(512) + LCCR3_ACBsCntOff + LCCR3_HorSnchH + LCCR3_VrtSnchH + LCCR3_PixFlEdg + LCCR3_OutEnL;#endif } if (machine_is_graphicsclient()) { DPRINTK("Configuring GraphicsClient LCD\n"); shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act; shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(9) + LCCR1_EndLnDel(54) + LCCR1_BegLnDel(54); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(9) + LCCR2_EndFrmDel(32) + LCCR2_BegFrmDel(24); shadow.lccr3 = LCCR3_PixClkDiv(10) + LCCR3_ACBsDiv(2) + LCCR3_ACBsCntOff + LCCR3_HorSnchL + LCCR3_VrtSnchL; } if (machine_is_omnimeter()) { DPRINTK("Configuring OMNI LCD\n"); shadow.lccr0 = LCCR0_LEN | LCCR0_CMS | LCCR0_DPD; shadow.lccr1 = LCCR1_BegLnDel(10) + LCCR1_EndLnDel(10) + LCCR1_HorSnchWdth(1) + LCCR1_DisWdth(var->xres); shadow.lccr2 = LCCR2_DisHght(var->yres); shadow.lccr3 = LCCR3_ACBsDiv(0xFF) + LCCR3_PixClkDiv(44);//jca (GetPCD(25) << LCD3_V_PCD); } if (machine_is_xp860()) { DPRINTK("Configuring XP860 LCD\n"); shadow.lccr0 = LCCR0_LEN + LCCR0_Color + LCCR0_Sngl + LCCR0_Act + LCCR0_LtlEnd + LCCR0_LDM + LCCR0_ERM + LCCR0_DMADel(0); shadow.lccr1 = LCCR1_DisWdth(var->xres) + LCCR1_HorSnchWdth(var->hsync_len) + LCCR1_BegLnDel(var->left_margin) + LCCR1_EndLnDel(var->right_margin); shadow.lccr2 = LCCR2_DisHght(var->yres) + LCCR2_VrtSnchWdth(var->vsync_len) + LCCR2_BegFrmDel(var->upper_margin) + LCCR2_EndFrmDel(var->lower_margin); shadow.lccr3 = LCCR3_PixClkDiv(6) + LCCR3_HorSnchL + LCCR3_VrtSnchL; } /* * Ok, since we're calculating these values, we want to know * if the calculation is correct. If you see any of these * messages _PLEASE_ report the incident to me for diagnosis, * including details about what was happening when the * messages appeared. --rmk, 30 March 2001 */ if (shadow.lccr0 != new_regs->lccr0) { printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n", shadow.lccr1, new_regs->lccr1); different = 1; } if (shadow.lccr1 != new_regs->lccr1) { printk(KERN_ERR "LCCR1 mismatch: 0x%08x != 0x%08x\n", shadow.lccr1, new_regs->lccr1); different = 1; } if (shadow.lccr2 != new_regs->lccr2) { printk(KERN_ERR "LCCR2 mismatch: 0x%08x != 0x%08x\n", shadow.lccr2, new_regs->lccr2); different = 1; } if (shadow.lccr3 != new_regs->lccr3) { printk(KERN_ERR "LCCR3 mismatch: 0x%08x != 0x%08x\n", shadow.lccr3, new_regs->lccr3); different = 1; } if (different) { printk(KERN_ERR "var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, var->left_margin, var->right_margin); printk(KERN_ERR "var: yres=%d vslen=%d um=%d bm=%d\n", var->yres, var->vsync_len, var->upper_margin, var->lower_margin); printk(KERN_ERR "Please report this to Russell King " "<rmk@arm.linux.org.uk>\n"); } DPRINTK("olccr0 = 0x%08x\n", shadow.lccr0); DPRINTK("olccr1 = 0x%08x\n", shadow.lccr1); DPRINTK("olccr2 = 0x%08x\n", shadow.lccr2); DPRINTK("olccr3 = 0x%08x\n", shadow.lccr3);}#else#define sa1100fb_check_shadow(regs,var,pcd)#endif/* * IMHO this looks wrong. In 8BPP, length should be 8. */static struct sa1100fb_rgb rgb_8 = { red: { offset: 0, length: 4, }, green: { offset: 0, length: 4, }, blue: { offset: 0, length: 4, }, transp: { offset: 0, length: 0, },};static struct sa1100fb_rgb def_rgb_16 = { red: { offset: 11, length: 5, }, green: { offset: 5, length: 6, }, blue: { offset: 0, length: 5, }, transp: { offset: 0, length: 0, },};#ifdef CONFIG_SA1100_ASSABET#ifndef ASSABET_PAL_VIDEO/* * The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually * takes an RGB666 signal, but we provide it with an RGB565 signal * instead (def_rgb_16). */static struct sa1100fb_mach_info lq039q2ds54_info __initdata = { pixclock: 171521, bpp: 16, xres: 320, yres: 240, hsync_len: 5, vsync_len: 1, left_margin: 61, upper_margin: 3, right_margin: 9, lower_margin: 0, sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),};#elsestatic struct sa1100fb_mach_info pal_info __initdata = { pixclock: 67797, bpp: 16, xres: 640, yres: 512, hsync_len: 64, vsync_len: 6, left_margin: 125, upper_margin: 70,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -