📄 amifb.c
字号:
/* * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device * * Copyright (C) 1995-2003 Geert Uytterhoeven * * with work by Roman Zippel * * * This file is based on the Atari frame buffer device (atafb.c): * * Copyright (C) 1994 Martin Schaller * Roman Hodek * * with work by Andreas Schwab * Guenther Kelleter * * and on the original Amiga console driver (amicon.c): * * Copyright (C) 1993 Hamish Macdonald * Greg Harp * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] * * with work by William Rucklidge (wjr@cs.cornell.edu) * Geert Uytterhoeven * Jes Sorensen (jds@kom.auc.dk) * * * History: * * - 24 Jul 96: Copper generates now vblank interrupt and * VESA Power Saving Protocol is fully implemented * - 14 Jul 96: Rework and hopefully last ECS bugs fixed * - 7 Mar 96: Hardware sprite support by Roman Zippel * - 18 Feb 96: OCS and ECS support by Roman Zippel * Hardware functions completely rewritten * - 2 Dec 95: AGA version by Geert Uytterhoeven * * 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. */#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/interrupt.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/uaccess.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/amigahw.h>#include <asm/amigaints.h>#include <asm/setup.h>#include "c2p.h"#define DEBUG#if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)#define CONFIG_FB_AMIGA_OCS /* define at least one fb driver, this will change later */#endif#if !defined(CONFIG_FB_AMIGA_OCS)# define IS_OCS (0)#elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)# define IS_OCS (chipset == TAG_OCS)#else# define CONFIG_FB_AMIGA_OCS_ONLY# define IS_OCS (1)#endif#if !defined(CONFIG_FB_AMIGA_ECS)# define IS_ECS (0)#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)# define IS_ECS (chipset == TAG_ECS)#else# define CONFIG_FB_AMIGA_ECS_ONLY# define IS_ECS (1)#endif#if !defined(CONFIG_FB_AMIGA_AGA)# define IS_AGA (0)#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)# define IS_AGA (chipset == TAG_AGA)#else# define CONFIG_FB_AMIGA_AGA_ONLY# define IS_AGA (1)#endif#ifdef DEBUG# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)#else# define DPRINTK(fmt, args...)#endif/******************************************************************************* Generic video timings --------------------- Timings used by the frame buffer interface: +----------+---------------------------------------------+----------+-------+ | | ^ | | | | | |upper_margin | | | | | v | | | +----------###############################################----------+-------+ | # ^ # | | | # | # | | | # | # | | | # | # | | | left # | # right | hsync | | margin # | xres # margin | len | |<-------->#<---------------+--------------------------->#<-------->|<----->| | # | # | | | # | # | | | # | # | | | # |yres # | | | # | # | | | # | # | | | # | # | | | # | # | | | # | # | | | # | # | | | # | # | | | # | # | | | # v # | | +----------###############################################----------+-------+ | | ^ | | | | | |lower_margin | | | | | v | | | +----------+---------------------------------------------+----------+-------+ | | ^ | | | | | |vsync_len | | | | | v | | | +----------+---------------------------------------------+----------+-------+ Amiga video timings ------------------- The Amiga native chipsets uses another timing scheme: - hsstrt: Start of horizontal synchronization pulse - hsstop: End of horizontal synchronization pulse - htotal: Last value on the line (i.e. line length = htotal+1) - vsstrt: Start of vertical synchronization pulse - vsstop: End of vertical synchronization pulse - vtotal: Last line value (i.e. number of lines = vtotal+1) - hcenter: Start of vertical retrace for interlace You can specify the blanking timings independently. Currently I just set them equal to the respective synchronization values: - hbstrt: Start of horizontal blank - hbstop: End of horizontal blank - vbstrt: Start of vertical blank - vbstop: End of vertical blank Horizontal values are in color clock cycles (280 ns), vertical values are in scanlines. (0, 0) is somewhere in the upper-left corner :-) Amiga visible window definitions -------------------------------- Currently I only have values for AGA, SHRES (28 MHz dotclock). Feel free to make corrections and/or additions. Within the above synchronization specifications, the visible window is defined by the following parameters (actual register resolutions may be different; all horizontal values are normalized with respect to the pixel clock): - diwstrt_h: Horizontal start of the visible window - diwstop_h: Horizontal stop+1(*) of the visible window - diwstrt_v: Vertical start of the visible window - diwstop_v: Vertical stop of the visible window - ddfstrt: Horizontal start of display DMA - ddfstop: Horizontal stop of display DMA - hscroll: Horizontal display output delay Sprite positioning: - sprstrt_h: Horizontal start-4 of sprite - sprstrt_v: Vertical start of sprite (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1. Horizontal values are in dotclock cycles (35 ns), vertical values are in scanlines. (0, 0) is somewhere in the upper-left corner :-) Dependencies (AGA, SHRES (35 ns dotclock)) ------------------------------------------- Since there are much more parameters for the Amiga display than for the frame buffer interface, there must be some dependencies among the Amiga display parameters. Here's what I found out: - ddfstrt and ddfstop are best aligned to 64 pixels. - the chipset needs 64+4 horizontal pixels after the DMA start before the first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to display the first pixel on the line too. Increase diwstrt_h for virtual screen panning. - the display DMA always fetches 64 pixels at a time (fmode = 3). - ddfstop is ddfstrt+#pixels-64. - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1 more than htotal. - hscroll simply adds a delay to the display output. Smooth horizontal panning needs an extra 64 pixels on the left to prefetch the pixels that `fall off' on the left. - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane DMA, so it's best to make the DMA start as late as possible. - you really don't want to make ddfstrt < 128, since this will steal DMA cycles from the other DMA channels (audio, floppy and Chip RAM refresh). - I make diwstop_h and diwstop_v as large as possible. General dependencies -------------------- - all values are SHRES pixel (35ns) table 1:fetchstart table 2:prefetch table 3:fetchsize ------------------ ---------------- ----------------- Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES -------------#------+-----+------#------+-----+------#------+-----+------ Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64 Bus width 2x # 32 | 64 | 128 # 32 | 64 | 64 # 64 | 64 | 128 Bus width 4x # 64 | 128 | 256 # 64 | 64 | 64 # 64 | 128 | 256 - chipset needs 4 pixels before the first pixel is output - ddfstrt must be aligned to fetchstart (table 1) - chipset needs also prefetch (table 2) to get first pixel data, so ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch - for horizontal panning decrease diwstrt_h - the length of a fetchline must be aligned to fetchsize (table 3) - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit moved to optimize use of dma (useful for OCS/ECS overscan displays) - ddfstop is ddfstrt+ddfsize-fetchsize - If C= didn't change anything for AGA, then at following positions the dma bus is already used: ddfstrt < 48 -> memory refresh < 96 -> disk dma < 160 -> audio dma < 192 -> sprite 0 dma < 416 -> sprite dma (32 per sprite) - in accordance with the hardware reference manual a hardware stop is at 192, but AGA (ECS?) can go below this. DMA priorities -------------- Since there are limits on the earliest start value for display DMA and the display of sprites, I use the following policy on horizontal panning and the hardware cursor: - if you want to start display DMA too early, you lose the ability to do smooth horizontal panning (xpanstep 1 -> 64). - if you want to go even further, you lose the hardware cursor too. IMHO a hardware cursor is more important for X than horizontal scrolling, so that's my motivation. Implementation -------------- ami_decode_var() converts the frame buffer values to the Amiga values. It's just a `straightforward' implementation of the above rules. Standard VGA timings -------------------- xres yres left right upper lower hsync vsync ---- ---- ---- ----- ----- ----- ----- ----- 80x25 720 400 27 45 35 12 108 2 80x30 720 480 27 45 30 9 108 2 These were taken from a XFree86 configuration file, recalculated for a 28 MHz dotclock (Amigas don't have a 25 MHz dotclock) and converted to frame buffer generic timings. As a comparison, graphics/monitor.h suggests the following: xres yres left right upper lower hsync vsync ---- ---- ---- ----- ----- ----- ----- ----- VGA 640 480 52 112 24 19 112 - 2 + VGA70 640 400 52 112 27 21 112 - 2 - Sync polarities --------------- VSYNC HSYNC Vertical size Vertical total ----- ----- ------------- -------------- + + Reserved Reserved + - 400 414 - + 350 362 - - 480 496 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992 Broadcast video timings ----------------------- According to the CCIR and RETMA specifications, we have the following values: CCIR -> PAL ----------- - a scanline is 64 µs long, of which 52.48 µs are visible. This is about 736 visible 70 ns pixels per line. - we have 625 scanlines, of which 575 are visible (interlaced); after rounding this becomes 576. RETMA -> NTSC ------------- - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about 736 visible 70 ns pixels per line. - we have 525 scanlines, of which 485 are visible (interlaced); after rounding this becomes 484. Thus if you want a PAL compatible display, you have to do the following: - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast timings are to be used. - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an interlaced, 312 for a non-interlaced and 156 for a doublescanned display. - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES, 908 for a HIRES and 454 for a LORES display. - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90), left_margin+2*hsync_len must be greater or equal. - the upper visible part begins at 48 (interlaced; non-interlaced:24, doublescanned:12), upper_margin+2*vsync_len must be greater or equal. - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync of 4 scanlines The settings for a NTSC compatible display are straightforward. Note that in a strict sense the PAL and NTSC standards only define the encoding of the color part (chrominance) of the video signal and don't say anything about horizontal/vertical synchronization nor refresh rates. -- Geert --*******************************************************************************/ /* * Custom Chipset Definitions */#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld) /* * BPLCON0 -- Bitplane Control Register 0 */#define BPC0_HIRES (0x8000)#define BPC0_BPU2 (0x4000) /* Bit plane used count */#define BPC0_BPU1 (0x2000)#define BPC0_BPU0 (0x1000)#define BPC0_HAM (0x0800) /* HAM mode */#define BPC0_DPF (0x0400) /* Double playfield */#define BPC0_COLOR (0x0200) /* Enable colorburst */#define BPC0_GAUD (0x0100) /* Genlock audio enable */#define BPC0_UHRES (0x0080) /* Ultrahi res enable */#define BPC0_SHRES (0x0040) /* Super hi res mode */#define BPC0_BYPASS (0x0020) /* Bypass LUT - AGA */#define BPC0_BPU3 (0x0010) /* AGA */#define BPC0_LPEN (0x0008) /* Light pen enable */#define BPC0_LACE (0x0004) /* Interlace */#define BPC0_ERSY (0x0002) /* External resync */#define BPC0_ECSENA (0x0001) /* ECS enable */ /* * BPLCON2 -- Bitplane Control Register 2 */#define BPC2_ZDBPSEL2 (0x4000) /* Bitplane to be used for ZD - AGA */#define BPC2_ZDBPSEL1 (0x2000)#define BPC2_ZDBPSEL0 (0x1000)#define BPC2_ZDBPEN (0x0800) /* Enable ZD with ZDBPSELx - AGA */#define BPC2_ZDCTEN (0x0400) /* Enable ZD with palette bit #31 - AGA */#define BPC2_KILLEHB (0x0200) /* Kill EHB mode - AGA */#define BPC2_RDRAM (0x0100) /* Color table accesses read, not write - AGA */#define BPC2_SOGEN (0x0080) /* SOG output pin high - AGA */#define BPC2_PF2PRI (0x0040) /* PF2 priority over PF1 */#define BPC2_PF2P2 (0x0020) /* PF2 priority wrt sprites */#define BPC2_PF2P1 (0x0010)#define BPC2_PF2P0 (0x0008)#define BPC2_PF1P2 (0x0004) /* ditto PF1 */#define BPC2_PF1P1 (0x0002)#define BPC2_PF1P0 (0x0001) /* * BPLCON3 -- Bitplane Control Register 3 (AGA) */#define BPC3_BANK2 (0x8000) /* Bits to select color register bank */#define BPC3_BANK1 (0x4000)#define BPC3_BANK0 (0x2000)#define BPC3_PF2OF2 (0x1000) /* Bits for color table offset when PF2 */#define BPC3_PF2OF1 (0x0800)#define BPC3_PF2OF0 (0x0400)#define BPC3_LOCT (0x0200) /* Color register writes go to low bits */#define BPC3_SPRES1 (0x0080) /* Sprite resolution bits */#define BPC3_SPRES0 (0x0040)#define BPC3_BRDRBLNK (0x0020) /* Border blanked? */#define BPC3_BRDRTRAN (0x0010) /* Border transparent? */#define BPC3_ZDCLKEN (0x0004) /* ZD pin is 14 MHz (HIRES) clock output */#define BPC3_BRDRSPRT (0x0002) /* Sprites in border? */#define BPC3_EXTBLKEN (0x0001) /* BLANK programmable */ /* * BPLCON4 -- Bitplane Control Register 4 (AGA) */#define BPC4_BPLAM7 (0x8000) /* bitplane color XOR field */#define BPC4_BPLAM6 (0x4000)#define BPC4_BPLAM5 (0x2000)#define BPC4_BPLAM4 (0x1000)#define BPC4_BPLAM3 (0x0800)#define BPC4_BPLAM2 (0x0400)#define BPC4_BPLAM1 (0x0200)#define BPC4_BPLAM0 (0x0100)#define BPC4_ESPRM7 (0x0080) /* 4 high bits for even sprite colors */#define BPC4_ESPRM6 (0x0040)#define BPC4_ESPRM5 (0x0020)#define BPC4_ESPRM4 (0x0010)#define BPC4_OSPRM7 (0x0008) /* 4 high bits for odd sprite colors */#define BPC4_OSPRM6 (0x0004)#define BPC4_OSPRM5 (0x0002)#define BPC4_OSPRM4 (0x0001) /* * BEAMCON0 -- Beam Control Register */#define BMC0_HARDDIS (0x4000) /* Disable hardware limits */#define BMC0_LPENDIS (0x2000) /* Disable light pen latch */#define BMC0_VARVBEN (0x1000) /* Enable variable vertical blank */#define BMC0_LOLDIS (0x0800) /* Disable long/short line toggle */#define BMC0_CSCBEN (0x0400) /* Composite sync/blank */#define BMC0_VARVSYEN (0x0200) /* Enable variable vertical sync */#define BMC0_VARHSYEN (0x0100) /* Enable variable horizontal sync */#define BMC0_VARBEAMEN (0x0080) /* Enable variable beam counters */#define BMC0_DUAL (0x0040) /* Enable alternate horizontal beam counter */#define BMC0_PAL (0x0020) /* Set decodes for PAL */#define BMC0_VARCSYEN (0x0010) /* Enable variable composite sync */#define BMC0_BLANKEN (0x0008) /* Blank enable (no longer used on AGA) */#define BMC0_CSYTRUE (0x0004) /* CSY polarity */#define BMC0_VSYTRUE (0x0002) /* VSY polarity */#define BMC0_HSYTRUE (0x0001) /* HSY polarity */ /* * FMODE -- Fetch Mode Control Register (AGA) */#define FMODE_SSCAN2 (0x8000) /* Sprite scan-doubling */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -