/*
* Frame buffer device for IBM GXT4500P and GXT6000P display adaptors
*
* Copyright (C) 2006 Paul Mackerras, IBM Corp. <paulus@samba.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/delay.h>
#include <linux/string.h>
#define PCI_DEVICE_ID_IBM_GXT4500P 0x21c
#define PCI_DEVICE_ID_IBM_GXT6000P 0x170
/* GXT4500P registers */
/* Registers in PCI config space */
#define CFG_ENDIAN0 0x40
/* Misc control/status registers */
#define STATUS 0x1000
#define CTRL_REG0 0x1004
#define CR0_HALT_DMA 0x4
#define CR0_RASTER_RESET 0x8
#define CR0_GEOM_RESET 0x10
#define CR0_MEM_CTRLER_RESET 0x20
/* Framebuffer control registers */
#define FB_AB_CTRL 0x1100
#define FB_CD_CTRL 0x1104
#define FB_WID_CTRL 0x1108
#define FB_Z_CTRL 0x110c
#define FB_VGA_CTRL 0x1110
#define REFRESH_AB_CTRL 0x1114
#define REFRESH_CD_CTRL 0x1118
#define FB_OVL_CTRL 0x111c
#define FB_CTRL_TYPE 0x80000000
#define FB_CTRL_WIDTH_MASK 0x007f0000
#define FB_CTRL_WIDTH_SHIFT 16
#define FB_CTRL_START_SEG_MASK 0x00003fff
#define REFRESH_START 0x1098
#define REFRESH_SIZE 0x109c
/* "Direct" framebuffer access registers */
#define DFA_FB_A 0x11e0
#define DFA_FB_B 0x11e4
#define DFA_FB_C 0x11e8
#define DFA_FB_D 0x11ec
#define DFA_FB_ENABLE 0x80000000
#define DFA_FB_BASE_MASK 0x03f00000
#define DFA_FB_STRIDE_1k 0x00000000
#define DFA_FB_STRIDE_2k 0x00000010
#define DFA_FB_STRIDE_4k 0x00000020
#define DFA_PIX_8BIT 0x00000000
#define DFA_PIX_16BIT_565 0x00000001
#define DFA_PIX_16BIT_1555 0x00000002
#define DFA_PIX_24BIT 0x00000004
#define DFA_PIX_32BIT 0x00000005
/* maps DFA_PIX_* to pixel size in bytes */
static const unsigned char pixsize[] = {
1, 2, 2, 2, 4, 4
};
/* Display timing generator registers */
#define DTG_CONTROL 0x1900
#define DTG_CTL_SCREEN_REFRESH 2
#define DTG_CTL_ENABLE 1
#define DTG_HORIZ_EXTENT 0x1904
#define DTG_HORIZ_DISPLAY 0x1908
#define DTG_HSYNC_START 0x190c
#define DTG_HSYNC_END 0x1910
#define DTG_HSYNC_END_COMP 0x1914
#define DTG_VERT_EXTENT 0x1918
#define DTG_VERT_DISPLAY 0x191c
#define DTG_VSYNC_START 0x1920
#define DTG_VSYNC_END 0x1924
#define DTG_VERT_SHORT 0x1928
/* PLL/RAMDAC registers */
#define DISP_CTL 0x402c
#define DISP_CTL_OFF 2
#define SYNC_CTL 0x4034
#define SYNC_CTL_SYNC_ON_RGB 1
#define SYNC_CTL_SYNC_OFF 2
#define SYNC_CTL_HSYNC_INV 8
#define SYNC_CTL_VSYNC_INV 0x10
#define SYNC_CTL_HSYNC_OFF 0x20
#define SYNC_CTL_VSYNC_OFF 0x40
#define PLL_M 0x4040
#define PLL_N 0x4044
#define PLL_POSTDIV 0x4048
#define PLL_C 0x404c
/* Hardware cursor */
#define CURSOR_X 0x4078
#define CURSOR_Y 0x407c
#define CURSOR_HOTSPOT 0x4080
#define CURSOR_MODE 0x4084
#define CURSOR_MODE_OFF 0
#define CURSOR_MODE_4BPP 1
#define CURSOR_PIXMAP 0x5000
#define CURSOR_CMAP 0x7400
/* Window attribute table */
#define WAT_FMT 0x4100
#define WAT_FMT_24BIT 0
#define WAT_FMT_16BIT_565 1
#define WAT_FMT_16BIT_1555 2
#define WAT_FMT_32BIT 3 /* 0 vs. 3 is a guess */
#define WAT_FMT_8BIT_332 9
#define WAT_FMT_8BIT 0xa
#define WAT_FMT_NO_CMAP 4 /* ORd in to other values */
#define WAT_CMAP_OFFSET 0x4104 /* 4-bit value gets << 6 */
#define WAT_CTRL 0x4108
#define WAT_CTRL_SEL_B 1 /* select B buffer if 1 */
#define WAT_CTRL_NO_INC 2
#define WAT_GAMMA_CTRL 0x410c
#define WAT_GAMMA_DISABLE 1 /* disables gamma cmap */
#define WAT_OVL_CTRL 0x430c /* controls overlay */
/* Indexed by DFA_PIX_* values */
static const unsigned char watfmt[] = {
WAT_FMT_8BIT, WAT_FMT_16BIT_565, WAT_FMT_16BIT_1555, 0,
WAT_FMT_24BIT, WAT_FMT_32BIT
};
/* Colormap array; 1k entries of 4 bytes each */
#define CMAP 0x6000
#define readreg(par, reg) readl((par)->regs + (reg))
#define writereg(par, reg, val) writel((val), (par)->regs + (reg))
struct gxt4500_par {