cirrusfb.c
来自「linux 内核源代码」· C语言 代码 · 共 2,477 行 · 第 1/5 页
C
2,477 行
/* * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets * * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com> * * Contributors (thanks, all!) * * David Eger: * Overhaul for Linux 2.6 * * Jeff Rugen: * Major contributions; Motorola PowerStack (PPC and PCI) support, * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. * * Geert Uytterhoeven: * Excellent code review. * * Lars Hecking: * Amiga updates and testing. * * Original cirrusfb author: Frank Neumann * * Based on retz3fb.c and cirrusfb.c: * Copyright (C) 1997 Jes Sorensen * Copyright (C) 1996 Frank Neumann * *************************************************************** * * Format this code with GNU indent '-kr -i8 -pcs' options. * * 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. * */#define CIRRUSFB_VERSION "2.0-pre2"#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <asm/pgtable.h>#ifdef CONFIG_ZORRO#include <linux/zorro.h>#endif#ifdef CONFIG_PCI#include <linux/pci.h>#endif#ifdef CONFIG_AMIGA#include <asm/amigahw.h>#endif#ifdef CONFIG_PPC_PREP#include <asm/machdep.h>#define isPReP machine_is(prep)#else#define isPReP 0#endif#include <video/vga.h>#include <video/cirrus.h>/***************************************************************** * * debugging and utility macros * *//* enable debug output? *//* #define CIRRUSFB_DEBUG 1 *//* disable runtime assertions? *//* #define CIRRUSFB_NDEBUG *//* debug output */#ifdef CIRRUSFB_DEBUG#define DPRINTK(fmt, args...) \ printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#define DPRINTK(fmt, args...)#endif/* debugging assertions */#ifndef CIRRUSFB_NDEBUG#define assert(expr) \ if (!(expr)) { \ printk("Assertion failed! %s,%s,%s,line=%d\n", \ #expr, __FILE__, __FUNCTION__, __LINE__); \ }#else#define assert(expr)#endif#define MB_ (1024 * 1024)/***************************************************************** * * chipset information * *//* board types */enum cirrus_board { BT_NONE = 0, BT_SD64, BT_PICCOLO, BT_PICASSO, BT_SPECTRUM, BT_PICASSO4, /* GD5446 */ BT_ALPINE, /* GD543x/4x */ BT_GD5480, BT_LAGUNA, /* GD546x */};/* * per-board-type information, used for enumerating and abstracting * chip-specific information * NOTE: MUST be in the same order as enum cirrus_board in order to * use direct indexing on this array * NOTE: '__initdata' cannot be used as some of this info * is required at runtime. Maybe separate into an init-only and * a run-time table? */static const struct cirrusfb_board_info_rec { char *name; /* ASCII name of chipset */ long maxclock[5]; /* maximum video clock */ /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ bool init_sr07 : 1; /* init SR07 during init_vgachip() */ bool init_sr1f : 1; /* write SR1F during init_vgachip() */ /* construct bit 19 of screen start address */ bool scrn_start_bit19 : 1; /* initial SR07 value, then for each mode */ unsigned char sr07; unsigned char sr07_1bpp; unsigned char sr07_1bpp_mux; unsigned char sr07_8bpp; unsigned char sr07_8bpp_mux; unsigned char sr1f; /* SR1F VGA initial register value */} cirrusfb_board_info[] = { [BT_SD64] = { .name = "CL SD64", .maxclock = { /* guess */ /* the SD64/P4 have a higher max. videoclock */ 140000, 140000, 140000, 140000, 140000, }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = true, .sr07 = 0xF0, .sr07_1bpp = 0xF0, .sr07_8bpp = 0xF1, .sr1f = 0x20 }, [BT_PICCOLO] = { .name = "CL Piccolo", .maxclock = { /* guess */ 90000, 90000, 90000, 90000, 90000 }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = false, .sr07 = 0x80, .sr07_1bpp = 0x80, .sr07_8bpp = 0x81, .sr1f = 0x22 }, [BT_PICASSO] = { .name = "CL Picasso", .maxclock = { /* guess */ 90000, 90000, 90000, 90000, 90000 }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = false, .sr07 = 0x20, .sr07_1bpp = 0x20, .sr07_8bpp = 0x21, .sr1f = 0x22 }, [BT_SPECTRUM] = { .name = "CL Spectrum", .maxclock = { /* guess */ 90000, 90000, 90000, 90000, 90000 }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = false, .sr07 = 0x80, .sr07_1bpp = 0x80, .sr07_8bpp = 0x81, .sr1f = 0x22 }, [BT_PICASSO4] = { .name = "CL Picasso4", .maxclock = { 135100, 135100, 85500, 85500, 0 }, .init_sr07 = true, .init_sr1f = false, .scrn_start_bit19 = true, .sr07 = 0x20, .sr07_1bpp = 0x20, .sr07_8bpp = 0x21, .sr1f = 0 }, [BT_ALPINE] = { .name = "CL Alpine", .maxclock = { /* for the GD5430. GD5446 can do more... */ 85500, 85500, 50000, 28500, 0 }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = true, .sr07 = 0xA0, .sr07_1bpp = 0xA1, .sr07_1bpp_mux = 0xA7, .sr07_8bpp = 0xA1, .sr07_8bpp_mux = 0xA7, .sr1f = 0x1C }, [BT_GD5480] = { .name = "CL GD5480", .maxclock = { 135100, 200000, 200000, 135100, 135100 }, .init_sr07 = true, .init_sr1f = true, .scrn_start_bit19 = true, .sr07 = 0x10, .sr07_1bpp = 0x11, .sr07_8bpp = 0x11, .sr1f = 0x1C }, [BT_LAGUNA] = { .name = "CL Laguna", .maxclock = { /* guess */ 135100, 135100, 135100, 135100, 135100, }, .init_sr07 = false, .init_sr1f = false, .scrn_start_bit19 = true, }};#ifdef CONFIG_PCI#define CHIP(id, btype) \ { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }static struct pci_device_id cirrusfb_pci_table[] = { CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE), CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE), CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */ CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/ { 0, }};MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);#undef CHIP#endif /* CONFIG_PCI */#ifdef CONFIG_ZORROstatic const struct zorro_device_id cirrusfb_zorro_table[] = { { .id = ZORRO_PROD_HELFRICH_SD64_RAM, .driver_data = BT_SD64, }, { .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, .driver_data = BT_PICCOLO, }, { .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, .driver_data = BT_PICASSO, }, { .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, .driver_data = BT_SPECTRUM, }, { .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, .driver_data = BT_PICASSO4, }, { 0 }};static const struct { zorro_id id2; unsigned long size;} cirrusfb_zorro_table2[] = { [BT_SD64] = { .id2 = ZORRO_PROD_HELFRICH_SD64_REG, .size = 0x400000 }, [BT_PICCOLO] = { .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG, .size = 0x200000 }, [BT_PICASSO] = { .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, .size = 0x200000 }, [BT_SPECTRUM] = { .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, .size = 0x200000 }, [BT_PICASSO4] = { .id2 = 0, .size = 0x400000 }};#endif /* CONFIG_ZORRO */struct cirrusfb_regs { long freq; long nom; long den; long div; long multiplexing; long mclk; long divMCLK; long HorizRes; /* The x resolution in pixel */ long HorizTotal; long HorizDispEnd; long HorizBlankStart; long HorizBlankEnd; long HorizSyncStart; long HorizSyncEnd; long VertRes; /* the physical y resolution in scanlines */ long VertTotal; long VertDispEnd; long VertSyncStart; long VertSyncEnd; long VertBlankStart; long VertBlankEnd;};#ifdef CIRRUSFB_DEBUGenum cirrusfb_dbg_reg_class { CRT, SEQ};#endif /* CIRRUSFB_DEBUG *//* info about board */struct cirrusfb_info { u8 __iomem *regbase; enum cirrus_board btype; unsigned char SFR; /* Shadow of special function register */ struct cirrusfb_regs currentmode; int blank_mode; u32 pseudo_palette[16];#ifdef CONFIG_ZORRO struct zorro_dev *zdev;#endif#ifdef CONFIG_PCI struct pci_dev *pdev;#endif void (*unmap)(struct fb_info *info);};static unsigned cirrusfb_def_mode = 1;static int noaccel;/* * Predefined Video Modes */static const struct { const char *name; struct fb_var_screeninfo var;} cirrusfb_predefined[] = { { /* autodetect mode */ .name = "Autodetect", }, { /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ .name = "640x480", .var = { .xres = 640, .yres = 480, .xres_virtual = 640, .yres_virtual = 480, .bits_per_pixel = 8, .red = { .length = 8 }, .green = { .length = 8 }, .blue = { .length = 8 }, .width = -1, .height = -1, .pixclock = 40000, .left_margin = 48, .right_margin = 16, .upper_margin = 32, .lower_margin = 8, .hsync_len = 96, .vsync_len = 4, .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, .vmode = FB_VMODE_NONINTERLACED } }, { /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */ .name = "800x600", .var = { .xres = 800, .yres = 600, .xres_virtual = 800, .yres_virtual = 600, .bits_per_pixel = 8, .red = { .length = 8 }, .green = { .length = 8 }, .blue = { .length = 8 }, .width = -1, .height = -1, .pixclock = 20000, .left_margin = 128, .right_margin = 16, .upper_margin = 24, .lower_margin = 2, .hsync_len = 96, .vsync_len = 6, .vmode = FB_VMODE_NONINTERLACED } }, { /* * Modeline from XF86Config: * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 */ /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ .name = "1024x768", .var = { .xres = 1024, .yres = 768, .xres_virtual = 1024, .yres_virtual = 768, .bits_per_pixel = 8, .red = { .length = 8 }, .green = { .length = 8 }, .blue = { .length = 8 }, .width = -1, .height = -1, .pixclock = 12500, .left_margin = 144, .right_margin = 32, .upper_margin = 30, .lower_margin = 2, .hsync_len = 192, .vsync_len = 6, .vmode = FB_VMODE_NONINTERLACED } }};#define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined)/****************************************************************************//**** BEGIN PROTOTYPES ******************************************************//*--- Interface used by the world ------------------------------------------*/static int cirrusfb_init(void);#ifndef MODULEstatic int cirrusfb_setup(char *options);#endifstatic int cirrusfb_open(struct fb_info *info, int user);static int cirrusfb_release(struct fb_info *info, int user);static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);static int cirrusfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);static int cirrusfb_set_par(struct fb_info *info);static int cirrusfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);static int cirrusfb_blank(int blank_mode, struct fb_info *info);static void cirrusfb_fillrect(struct fb_info *info, const struct fb_fillrect *region);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?