162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com> 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Contributors (thanks, all!) 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * David Eger: 962306a36Sopenharmony_ci * Overhaul for Linux 2.6 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * Jeff Rugen: 1262306a36Sopenharmony_ci * Major contributions; Motorola PowerStack (PPC and PCI) support, 1362306a36Sopenharmony_ci * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Geert Uytterhoeven: 1662306a36Sopenharmony_ci * Excellent code review. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Lars Hecking: 1962306a36Sopenharmony_ci * Amiga updates and testing. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Original cirrusfb author: Frank Neumann 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * Based on retz3fb.c and cirrusfb.c: 2462306a36Sopenharmony_ci * Copyright (C) 1997 Jes Sorensen 2562306a36Sopenharmony_ci * Copyright (C) 1996 Frank Neumann 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci *************************************************************** 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Format this code with GNU indent '-kr -i8 -pcs' options. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 3262306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 3362306a36Sopenharmony_ci * for more details. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <linux/aperture.h> 3862306a36Sopenharmony_ci#include <linux/module.h> 3962306a36Sopenharmony_ci#include <linux/kernel.h> 4062306a36Sopenharmony_ci#include <linux/errno.h> 4162306a36Sopenharmony_ci#include <linux/string.h> 4262306a36Sopenharmony_ci#include <linux/mm.h> 4362306a36Sopenharmony_ci#include <linux/delay.h> 4462306a36Sopenharmony_ci#include <linux/fb.h> 4562306a36Sopenharmony_ci#include <linux/init.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 4862306a36Sopenharmony_ci#include <linux/zorro.h> 4962306a36Sopenharmony_ci#endif 5062306a36Sopenharmony_ci#ifdef CONFIG_PCI 5162306a36Sopenharmony_ci#include <linux/pci.h> 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci#ifdef CONFIG_AMIGA 5462306a36Sopenharmony_ci#include <asm/amigahw.h> 5562306a36Sopenharmony_ci#endif 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#include <video/vga.h> 5862306a36Sopenharmony_ci#include <video/cirrus.h> 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/***************************************************************** 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * debugging and utility macros 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* disable runtime assertions? */ 6762306a36Sopenharmony_ci/* #define CIRRUSFB_NDEBUG */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* debugging assertions */ 7062306a36Sopenharmony_ci#ifndef CIRRUSFB_NDEBUG 7162306a36Sopenharmony_ci#define assert(expr) \ 7262306a36Sopenharmony_ci if (!(expr)) { \ 7362306a36Sopenharmony_ci printk("Assertion failed! %s,%s,%s,line=%d\n", \ 7462306a36Sopenharmony_ci #expr, __FILE__, __func__, __LINE__); \ 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci#else 7762306a36Sopenharmony_ci#define assert(expr) 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define MB_ (1024 * 1024) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/***************************************************************** 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * chipset information 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* board types */ 8962306a36Sopenharmony_cienum cirrus_board { 9062306a36Sopenharmony_ci BT_NONE = 0, 9162306a36Sopenharmony_ci BT_SD64, /* GD5434 */ 9262306a36Sopenharmony_ci BT_PICCOLO, /* GD5426 */ 9362306a36Sopenharmony_ci BT_PICASSO, /* GD5426 or GD5428 */ 9462306a36Sopenharmony_ci BT_SPECTRUM, /* GD5426 or GD5428 */ 9562306a36Sopenharmony_ci BT_PICASSO4, /* GD5446 */ 9662306a36Sopenharmony_ci BT_ALPINE, /* GD543x/4x */ 9762306a36Sopenharmony_ci BT_GD5480, 9862306a36Sopenharmony_ci BT_LAGUNA, /* GD5462/64 */ 9962306a36Sopenharmony_ci BT_LAGUNAB, /* GD5465 */ 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* 10362306a36Sopenharmony_ci * per-board-type information, used for enumerating and abstracting 10462306a36Sopenharmony_ci * chip-specific information 10562306a36Sopenharmony_ci * NOTE: MUST be in the same order as enum cirrus_board in order to 10662306a36Sopenharmony_ci * use direct indexing on this array 10762306a36Sopenharmony_ci * NOTE: '__initdata' cannot be used as some of this info 10862306a36Sopenharmony_ci * is required at runtime. Maybe separate into an init-only and 10962306a36Sopenharmony_ci * a run-time table? 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cistatic const struct cirrusfb_board_info_rec { 11262306a36Sopenharmony_ci char *name; /* ASCII name of chipset */ 11362306a36Sopenharmony_ci long maxclock[5]; /* maximum video clock */ 11462306a36Sopenharmony_ci /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ 11562306a36Sopenharmony_ci bool init_sr07 : 1; /* init SR07 during init_vgachip() */ 11662306a36Sopenharmony_ci bool init_sr1f : 1; /* write SR1F during init_vgachip() */ 11762306a36Sopenharmony_ci /* construct bit 19 of screen start address */ 11862306a36Sopenharmony_ci bool scrn_start_bit19 : 1; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* initial SR07 value, then for each mode */ 12162306a36Sopenharmony_ci unsigned char sr07; 12262306a36Sopenharmony_ci unsigned char sr07_1bpp; 12362306a36Sopenharmony_ci unsigned char sr07_1bpp_mux; 12462306a36Sopenharmony_ci unsigned char sr07_8bpp; 12562306a36Sopenharmony_ci unsigned char sr07_8bpp_mux; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci unsigned char sr1f; /* SR1F VGA initial register value */ 12862306a36Sopenharmony_ci} cirrusfb_board_info[] = { 12962306a36Sopenharmony_ci [BT_SD64] = { 13062306a36Sopenharmony_ci .name = "CL SD64", 13162306a36Sopenharmony_ci .maxclock = { 13262306a36Sopenharmony_ci /* guess */ 13362306a36Sopenharmony_ci /* the SD64/P4 have a higher max. videoclock */ 13462306a36Sopenharmony_ci 135100, 135100, 85500, 85500, 0 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci .init_sr07 = true, 13762306a36Sopenharmony_ci .init_sr1f = true, 13862306a36Sopenharmony_ci .scrn_start_bit19 = true, 13962306a36Sopenharmony_ci .sr07 = 0xF0, 14062306a36Sopenharmony_ci .sr07_1bpp = 0xF0, 14162306a36Sopenharmony_ci .sr07_1bpp_mux = 0xF6, 14262306a36Sopenharmony_ci .sr07_8bpp = 0xF1, 14362306a36Sopenharmony_ci .sr07_8bpp_mux = 0xF7, 14462306a36Sopenharmony_ci .sr1f = 0x1E 14562306a36Sopenharmony_ci }, 14662306a36Sopenharmony_ci [BT_PICCOLO] = { 14762306a36Sopenharmony_ci .name = "CL Piccolo", 14862306a36Sopenharmony_ci .maxclock = { 14962306a36Sopenharmony_ci /* guess */ 15062306a36Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 15162306a36Sopenharmony_ci }, 15262306a36Sopenharmony_ci .init_sr07 = true, 15362306a36Sopenharmony_ci .init_sr1f = true, 15462306a36Sopenharmony_ci .scrn_start_bit19 = false, 15562306a36Sopenharmony_ci .sr07 = 0x80, 15662306a36Sopenharmony_ci .sr07_1bpp = 0x80, 15762306a36Sopenharmony_ci .sr07_8bpp = 0x81, 15862306a36Sopenharmony_ci .sr1f = 0x22 15962306a36Sopenharmony_ci }, 16062306a36Sopenharmony_ci [BT_PICASSO] = { 16162306a36Sopenharmony_ci .name = "CL Picasso", 16262306a36Sopenharmony_ci .maxclock = { 16362306a36Sopenharmony_ci /* guess */ 16462306a36Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 16562306a36Sopenharmony_ci }, 16662306a36Sopenharmony_ci .init_sr07 = true, 16762306a36Sopenharmony_ci .init_sr1f = true, 16862306a36Sopenharmony_ci .scrn_start_bit19 = false, 16962306a36Sopenharmony_ci .sr07 = 0x20, 17062306a36Sopenharmony_ci .sr07_1bpp = 0x20, 17162306a36Sopenharmony_ci .sr07_8bpp = 0x21, 17262306a36Sopenharmony_ci .sr1f = 0x22 17362306a36Sopenharmony_ci }, 17462306a36Sopenharmony_ci [BT_SPECTRUM] = { 17562306a36Sopenharmony_ci .name = "CL Spectrum", 17662306a36Sopenharmony_ci .maxclock = { 17762306a36Sopenharmony_ci /* guess */ 17862306a36Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 17962306a36Sopenharmony_ci }, 18062306a36Sopenharmony_ci .init_sr07 = true, 18162306a36Sopenharmony_ci .init_sr1f = true, 18262306a36Sopenharmony_ci .scrn_start_bit19 = false, 18362306a36Sopenharmony_ci .sr07 = 0x80, 18462306a36Sopenharmony_ci .sr07_1bpp = 0x80, 18562306a36Sopenharmony_ci .sr07_8bpp = 0x81, 18662306a36Sopenharmony_ci .sr1f = 0x22 18762306a36Sopenharmony_ci }, 18862306a36Sopenharmony_ci [BT_PICASSO4] = { 18962306a36Sopenharmony_ci .name = "CL Picasso4", 19062306a36Sopenharmony_ci .maxclock = { 19162306a36Sopenharmony_ci 135100, 135100, 85500, 85500, 0 19262306a36Sopenharmony_ci }, 19362306a36Sopenharmony_ci .init_sr07 = true, 19462306a36Sopenharmony_ci .init_sr1f = false, 19562306a36Sopenharmony_ci .scrn_start_bit19 = true, 19662306a36Sopenharmony_ci .sr07 = 0xA0, 19762306a36Sopenharmony_ci .sr07_1bpp = 0xA0, 19862306a36Sopenharmony_ci .sr07_1bpp_mux = 0xA6, 19962306a36Sopenharmony_ci .sr07_8bpp = 0xA1, 20062306a36Sopenharmony_ci .sr07_8bpp_mux = 0xA7, 20162306a36Sopenharmony_ci .sr1f = 0 20262306a36Sopenharmony_ci }, 20362306a36Sopenharmony_ci [BT_ALPINE] = { 20462306a36Sopenharmony_ci .name = "CL Alpine", 20562306a36Sopenharmony_ci .maxclock = { 20662306a36Sopenharmony_ci /* for the GD5430. GD5446 can do more... */ 20762306a36Sopenharmony_ci 85500, 85500, 50000, 28500, 0 20862306a36Sopenharmony_ci }, 20962306a36Sopenharmony_ci .init_sr07 = true, 21062306a36Sopenharmony_ci .init_sr1f = true, 21162306a36Sopenharmony_ci .scrn_start_bit19 = true, 21262306a36Sopenharmony_ci .sr07 = 0xA0, 21362306a36Sopenharmony_ci .sr07_1bpp = 0xA0, 21462306a36Sopenharmony_ci .sr07_1bpp_mux = 0xA6, 21562306a36Sopenharmony_ci .sr07_8bpp = 0xA1, 21662306a36Sopenharmony_ci .sr07_8bpp_mux = 0xA7, 21762306a36Sopenharmony_ci .sr1f = 0x1C 21862306a36Sopenharmony_ci }, 21962306a36Sopenharmony_ci [BT_GD5480] = { 22062306a36Sopenharmony_ci .name = "CL GD5480", 22162306a36Sopenharmony_ci .maxclock = { 22262306a36Sopenharmony_ci 135100, 200000, 200000, 135100, 135100 22362306a36Sopenharmony_ci }, 22462306a36Sopenharmony_ci .init_sr07 = true, 22562306a36Sopenharmony_ci .init_sr1f = true, 22662306a36Sopenharmony_ci .scrn_start_bit19 = true, 22762306a36Sopenharmony_ci .sr07 = 0x10, 22862306a36Sopenharmony_ci .sr07_1bpp = 0x11, 22962306a36Sopenharmony_ci .sr07_8bpp = 0x11, 23062306a36Sopenharmony_ci .sr1f = 0x1C 23162306a36Sopenharmony_ci }, 23262306a36Sopenharmony_ci [BT_LAGUNA] = { 23362306a36Sopenharmony_ci .name = "CL Laguna", 23462306a36Sopenharmony_ci .maxclock = { 23562306a36Sopenharmony_ci /* taken from X11 code */ 23662306a36Sopenharmony_ci 170000, 170000, 170000, 170000, 135100, 23762306a36Sopenharmony_ci }, 23862306a36Sopenharmony_ci .init_sr07 = false, 23962306a36Sopenharmony_ci .init_sr1f = false, 24062306a36Sopenharmony_ci .scrn_start_bit19 = true, 24162306a36Sopenharmony_ci }, 24262306a36Sopenharmony_ci [BT_LAGUNAB] = { 24362306a36Sopenharmony_ci .name = "CL Laguna AGP", 24462306a36Sopenharmony_ci .maxclock = { 24562306a36Sopenharmony_ci /* taken from X11 code */ 24662306a36Sopenharmony_ci 170000, 250000, 170000, 170000, 135100, 24762306a36Sopenharmony_ci }, 24862306a36Sopenharmony_ci .init_sr07 = false, 24962306a36Sopenharmony_ci .init_sr1f = false, 25062306a36Sopenharmony_ci .scrn_start_bit19 = true, 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci#ifdef CONFIG_PCI 25562306a36Sopenharmony_ci#define CHIP(id, btype) \ 25662306a36Sopenharmony_ci { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) } 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic struct pci_device_id cirrusfb_pci_table[] = { 25962306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), 26062306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64), 26162306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64), 26262306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ 26362306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), 26462306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), 26562306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */ 26662306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ 26762306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ 26862306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ 26962306a36Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/ 27062306a36Sopenharmony_ci { 0, } 27162306a36Sopenharmony_ci}; 27262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); 27362306a36Sopenharmony_ci#undef CHIP 27462306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 27762306a36Sopenharmony_cistruct zorrocl { 27862306a36Sopenharmony_ci enum cirrus_board type; /* Board type */ 27962306a36Sopenharmony_ci u32 regoffset; /* Offset of registers in first Zorro device */ 28062306a36Sopenharmony_ci u32 ramsize; /* Size of video RAM in first Zorro device */ 28162306a36Sopenharmony_ci /* If zero, use autoprobe on RAM device */ 28262306a36Sopenharmony_ci u32 ramoffset; /* Offset of video RAM in first Zorro device */ 28362306a36Sopenharmony_ci zorro_id ramid; /* Zorro ID of RAM device */ 28462306a36Sopenharmony_ci zorro_id ramid2; /* Zorro ID of optional second RAM device */ 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic const struct zorrocl zcl_sd64 = { 28862306a36Sopenharmony_ci .type = BT_SD64, 28962306a36Sopenharmony_ci .ramid = ZORRO_PROD_HELFRICH_SD64_RAM, 29062306a36Sopenharmony_ci}; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_cistatic const struct zorrocl zcl_piccolo = { 29362306a36Sopenharmony_ci .type = BT_PICCOLO, 29462306a36Sopenharmony_ci .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic const struct zorrocl zcl_picasso = { 29862306a36Sopenharmony_ci .type = BT_PICASSO, 29962306a36Sopenharmony_ci .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 30062306a36Sopenharmony_ci}; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const struct zorrocl zcl_spectrum = { 30362306a36Sopenharmony_ci .type = BT_SPECTRUM, 30462306a36Sopenharmony_ci .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 30562306a36Sopenharmony_ci}; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic const struct zorrocl zcl_picasso4_z3 = { 30862306a36Sopenharmony_ci .type = BT_PICASSO4, 30962306a36Sopenharmony_ci .regoffset = 0x00600000, 31062306a36Sopenharmony_ci .ramsize = 4 * MB_, 31162306a36Sopenharmony_ci .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */ 31262306a36Sopenharmony_ci}; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic const struct zorrocl zcl_picasso4_z2 = { 31562306a36Sopenharmony_ci .type = BT_PICASSO4, 31662306a36Sopenharmony_ci .regoffset = 0x10000, 31762306a36Sopenharmony_ci .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1, 31862306a36Sopenharmony_ci .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2, 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic const struct zorro_device_id cirrusfb_zorro_table[] = { 32362306a36Sopenharmony_ci { 32462306a36Sopenharmony_ci .id = ZORRO_PROD_HELFRICH_SD64_REG, 32562306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_sd64, 32662306a36Sopenharmony_ci }, { 32762306a36Sopenharmony_ci .id = ZORRO_PROD_HELFRICH_PICCOLO_REG, 32862306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_piccolo, 32962306a36Sopenharmony_ci }, { 33062306a36Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 33162306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso, 33262306a36Sopenharmony_ci }, { 33362306a36Sopenharmony_ci .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 33462306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_spectrum, 33562306a36Sopenharmony_ci }, { 33662306a36Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 33762306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso4_z3, 33862306a36Sopenharmony_ci }, { 33962306a36Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG, 34062306a36Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso4_z2, 34162306a36Sopenharmony_ci }, 34262306a36Sopenharmony_ci { 0 } 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 34562306a36Sopenharmony_ci#endif /* CONFIG_ZORRO */ 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 34862306a36Sopenharmony_cienum cirrusfb_dbg_reg_class { 34962306a36Sopenharmony_ci CRT, 35062306a36Sopenharmony_ci SEQ 35162306a36Sopenharmony_ci}; 35262306a36Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci/* info about board */ 35562306a36Sopenharmony_cistruct cirrusfb_info { 35662306a36Sopenharmony_ci u8 __iomem *regbase; 35762306a36Sopenharmony_ci u8 __iomem *laguna_mmio; 35862306a36Sopenharmony_ci enum cirrus_board btype; 35962306a36Sopenharmony_ci unsigned char SFR; /* Shadow of special function register */ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci int multiplexing; 36262306a36Sopenharmony_ci int doubleVCLK; 36362306a36Sopenharmony_ci int blank_mode; 36462306a36Sopenharmony_ci u32 pseudo_palette[16]; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci void (*unmap)(struct fb_info *info); 36762306a36Sopenharmony_ci}; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic bool noaccel; 37062306a36Sopenharmony_cistatic char *mode_option = "640x480@60"; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci/****************************************************************************/ 37362306a36Sopenharmony_ci/**** BEGIN PROTOTYPES ******************************************************/ 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/*--- Interface used by the world ------------------------------------------*/ 37662306a36Sopenharmony_cistatic int cirrusfb_pan_display(struct fb_var_screeninfo *var, 37762306a36Sopenharmony_ci struct fb_info *info); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci/*--- Internal routines ----------------------------------------------------*/ 38062306a36Sopenharmony_cistatic void init_vgachip(struct fb_info *info); 38162306a36Sopenharmony_cistatic void switch_monitor(struct cirrusfb_info *cinfo, int on); 38262306a36Sopenharmony_cistatic void WGen(const struct cirrusfb_info *cinfo, 38362306a36Sopenharmony_ci int regnum, unsigned char val); 38462306a36Sopenharmony_cistatic unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum); 38562306a36Sopenharmony_cistatic void AttrOn(const struct cirrusfb_info *cinfo); 38662306a36Sopenharmony_cistatic void WHDR(const struct cirrusfb_info *cinfo, unsigned char val); 38762306a36Sopenharmony_cistatic void WSFR(struct cirrusfb_info *cinfo, unsigned char val); 38862306a36Sopenharmony_cistatic void WSFR2(struct cirrusfb_info *cinfo, unsigned char val); 38962306a36Sopenharmony_cistatic void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, 39062306a36Sopenharmony_ci unsigned char red, unsigned char green, unsigned char blue); 39162306a36Sopenharmony_ci#if 0 39262306a36Sopenharmony_cistatic void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, 39362306a36Sopenharmony_ci unsigned char *red, unsigned char *green, 39462306a36Sopenharmony_ci unsigned char *blue); 39562306a36Sopenharmony_ci#endif 39662306a36Sopenharmony_cistatic void cirrusfb_WaitBLT(u8 __iomem *regbase); 39762306a36Sopenharmony_cistatic void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, 39862306a36Sopenharmony_ci u_short curx, u_short cury, 39962306a36Sopenharmony_ci u_short destx, u_short desty, 40062306a36Sopenharmony_ci u_short width, u_short height, 40162306a36Sopenharmony_ci u_short line_length); 40262306a36Sopenharmony_cistatic void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 40362306a36Sopenharmony_ci u_short x, u_short y, 40462306a36Sopenharmony_ci u_short width, u_short height, 40562306a36Sopenharmony_ci u32 fg_color, u32 bg_color, 40662306a36Sopenharmony_ci u_short line_length, u_char blitmode); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic void bestclock(long freq, int *nom, int *den, int *div); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 41162306a36Sopenharmony_cistatic void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase); 41262306a36Sopenharmony_cistatic void cirrusfb_dbg_print_regs(struct fb_info *info, 41362306a36Sopenharmony_ci caddr_t regbase, 41462306a36Sopenharmony_ci enum cirrusfb_dbg_reg_class reg_class, ...); 41562306a36Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci/*** END PROTOTYPES ********************************************************/ 41862306a36Sopenharmony_ci/*****************************************************************************/ 41962306a36Sopenharmony_ci/*** BEGIN Interface Used by the World ***************************************/ 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic inline int is_laguna(const struct cirrusfb_info *cinfo) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB; 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic int opencount; 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci/*--- Open /dev/fbx ---------------------------------------------------------*/ 42962306a36Sopenharmony_cistatic int cirrusfb_open(struct fb_info *info, int user) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci if (opencount++ == 0) 43262306a36Sopenharmony_ci switch_monitor(info->par, 1); 43362306a36Sopenharmony_ci return 0; 43462306a36Sopenharmony_ci} 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci/*--- Close /dev/fbx --------------------------------------------------------*/ 43762306a36Sopenharmony_cistatic int cirrusfb_release(struct fb_info *info, int user) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci if (--opencount == 0) 44062306a36Sopenharmony_ci switch_monitor(info->par, 0); 44162306a36Sopenharmony_ci return 0; 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci/**** END Interface used by the World *************************************/ 44562306a36Sopenharmony_ci/****************************************************************************/ 44662306a36Sopenharmony_ci/**** BEGIN Hardware specific Routines **************************************/ 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci/* Check if the MCLK is not a better clock source */ 44962306a36Sopenharmony_cistatic int cirrusfb_check_mclk(struct fb_info *info, long freq) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 45262306a36Sopenharmony_ci long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Read MCLK value */ 45562306a36Sopenharmony_ci mclk = (14318 * mclk) >> 3; 45662306a36Sopenharmony_ci dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* Determine if we should use MCLK instead of VCLK, and if so, what we 45962306a36Sopenharmony_ci * should divide it by to get VCLK 46062306a36Sopenharmony_ci */ 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (abs(freq - mclk) < 250) { 46362306a36Sopenharmony_ci dev_dbg(info->device, "Using VCLK = MCLK\n"); 46462306a36Sopenharmony_ci return 1; 46562306a36Sopenharmony_ci } else if (abs(freq - (mclk / 2)) < 250) { 46662306a36Sopenharmony_ci dev_dbg(info->device, "Using VCLK = MCLK/2\n"); 46762306a36Sopenharmony_ci return 2; 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci return 0; 47162306a36Sopenharmony_ci} 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_cistatic int cirrusfb_check_pixclock(struct fb_var_screeninfo *var, 47462306a36Sopenharmony_ci struct fb_info *info) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci long freq; 47762306a36Sopenharmony_ci long maxclock; 47862306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 47962306a36Sopenharmony_ci unsigned maxclockidx = var->bits_per_pixel >> 3; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* convert from ps to kHz */ 48262306a36Sopenharmony_ci freq = PICOS2KHZ(var->pixclock ? : 1); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; 48562306a36Sopenharmony_ci cinfo->multiplexing = 0; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci /* If the frequency is greater than we can support, we might be able 48862306a36Sopenharmony_ci * to use multiplexing for the video mode */ 48962306a36Sopenharmony_ci if (freq > maxclock) { 49062306a36Sopenharmony_ci var->pixclock = KHZ2PICOS(maxclock); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci while ((freq = PICOS2KHZ(var->pixclock)) > maxclock) 49362306a36Sopenharmony_ci var->pixclock++; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq); 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* 49862306a36Sopenharmony_ci * Additional constraint: 8bpp uses DAC clock doubling to allow maximum 49962306a36Sopenharmony_ci * pixel clock 50062306a36Sopenharmony_ci */ 50162306a36Sopenharmony_ci if (var->bits_per_pixel == 8) { 50262306a36Sopenharmony_ci switch (cinfo->btype) { 50362306a36Sopenharmony_ci case BT_ALPINE: 50462306a36Sopenharmony_ci case BT_SD64: 50562306a36Sopenharmony_ci case BT_PICASSO4: 50662306a36Sopenharmony_ci if (freq > 85500) 50762306a36Sopenharmony_ci cinfo->multiplexing = 1; 50862306a36Sopenharmony_ci break; 50962306a36Sopenharmony_ci case BT_GD5480: 51062306a36Sopenharmony_ci if (freq > 135100) 51162306a36Sopenharmony_ci cinfo->multiplexing = 1; 51262306a36Sopenharmony_ci break; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci default: 51562306a36Sopenharmony_ci break; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* If we have a 1MB 5434, we need to put ourselves in a mode where 52062306a36Sopenharmony_ci * the VCLK is double the pixel clock. */ 52162306a36Sopenharmony_ci cinfo->doubleVCLK = 0; 52262306a36Sopenharmony_ci if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ && 52362306a36Sopenharmony_ci var->bits_per_pixel == 16) { 52462306a36Sopenharmony_ci cinfo->doubleVCLK = 1; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci return 0; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic int cirrusfb_check_var(struct fb_var_screeninfo *var, 53162306a36Sopenharmony_ci struct fb_info *info) 53262306a36Sopenharmony_ci{ 53362306a36Sopenharmony_ci int yres; 53462306a36Sopenharmony_ci /* memory size in pixels */ 53562306a36Sopenharmony_ci unsigned int pixels; 53662306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci switch (var->bits_per_pixel) { 53962306a36Sopenharmony_ci case 1: 54062306a36Sopenharmony_ci var->red.offset = 0; 54162306a36Sopenharmony_ci var->red.length = 1; 54262306a36Sopenharmony_ci var->green = var->red; 54362306a36Sopenharmony_ci var->blue = var->red; 54462306a36Sopenharmony_ci break; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci case 8: 54762306a36Sopenharmony_ci var->red.offset = 0; 54862306a36Sopenharmony_ci var->red.length = 8; 54962306a36Sopenharmony_ci var->green = var->red; 55062306a36Sopenharmony_ci var->blue = var->red; 55162306a36Sopenharmony_ci break; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci case 16: 55462306a36Sopenharmony_ci var->red.offset = 11; 55562306a36Sopenharmony_ci var->green.offset = 5; 55662306a36Sopenharmony_ci var->blue.offset = 0; 55762306a36Sopenharmony_ci var->red.length = 5; 55862306a36Sopenharmony_ci var->green.length = 6; 55962306a36Sopenharmony_ci var->blue.length = 5; 56062306a36Sopenharmony_ci break; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci case 24: 56362306a36Sopenharmony_ci var->red.offset = 16; 56462306a36Sopenharmony_ci var->green.offset = 8; 56562306a36Sopenharmony_ci var->blue.offset = 0; 56662306a36Sopenharmony_ci var->red.length = 8; 56762306a36Sopenharmony_ci var->green.length = 8; 56862306a36Sopenharmony_ci var->blue.length = 8; 56962306a36Sopenharmony_ci break; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci default: 57262306a36Sopenharmony_ci dev_dbg(info->device, 57362306a36Sopenharmony_ci "Unsupported bpp size: %d\n", var->bits_per_pixel); 57462306a36Sopenharmony_ci return -EINVAL; 57562306a36Sopenharmony_ci } 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci pixels = info->screen_size * 8 / var->bits_per_pixel; 57862306a36Sopenharmony_ci if (var->xres_virtual < var->xres) 57962306a36Sopenharmony_ci var->xres_virtual = var->xres; 58062306a36Sopenharmony_ci /* use highest possible virtual resolution */ 58162306a36Sopenharmony_ci if (var->yres_virtual == -1) { 58262306a36Sopenharmony_ci var->yres_virtual = pixels / var->xres_virtual; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci dev_info(info->device, 58562306a36Sopenharmony_ci "virtual resolution set to maximum of %dx%d\n", 58662306a36Sopenharmony_ci var->xres_virtual, var->yres_virtual); 58762306a36Sopenharmony_ci } 58862306a36Sopenharmony_ci if (var->yres_virtual < var->yres) 58962306a36Sopenharmony_ci var->yres_virtual = var->yres; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci if (var->xres_virtual * var->yres_virtual > pixels) { 59262306a36Sopenharmony_ci dev_err(info->device, "mode %dx%dx%d rejected... " 59362306a36Sopenharmony_ci "virtual resolution too high to fit into video memory!\n", 59462306a36Sopenharmony_ci var->xres_virtual, var->yres_virtual, 59562306a36Sopenharmony_ci var->bits_per_pixel); 59662306a36Sopenharmony_ci return -EINVAL; 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* truncate xoffset and yoffset to maximum if too high */ 60062306a36Sopenharmony_ci if (var->xoffset > var->xres_virtual - var->xres) 60162306a36Sopenharmony_ci var->xoffset = var->xres_virtual - var->xres - 1; 60262306a36Sopenharmony_ci if (var->yoffset > var->yres_virtual - var->yres) 60362306a36Sopenharmony_ci var->yoffset = var->yres_virtual - var->yres - 1; 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci var->red.msb_right = 60662306a36Sopenharmony_ci var->green.msb_right = 60762306a36Sopenharmony_ci var->blue.msb_right = 60862306a36Sopenharmony_ci var->transp.offset = 60962306a36Sopenharmony_ci var->transp.length = 61062306a36Sopenharmony_ci var->transp.msb_right = 0; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci yres = var->yres; 61362306a36Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) 61462306a36Sopenharmony_ci yres *= 2; 61562306a36Sopenharmony_ci else if (var->vmode & FB_VMODE_INTERLACED) 61662306a36Sopenharmony_ci yres = (yres + 1) / 2; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (yres >= 1280) { 61962306a36Sopenharmony_ci dev_err(info->device, "ERROR: VerticalTotal >= 1280; " 62062306a36Sopenharmony_ci "special treatment required! (TODO)\n"); 62162306a36Sopenharmony_ci return -EINVAL; 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (cirrusfb_check_pixclock(var, info)) 62562306a36Sopenharmony_ci return -EINVAL; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci if (!is_laguna(cinfo)) 62862306a36Sopenharmony_ci var->accel_flags = FB_ACCELF_TEXT; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci return 0; 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 63662306a36Sopenharmony_ci unsigned char old1f, old1e; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci assert(cinfo != NULL); 63962306a36Sopenharmony_ci old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci if (div) { 64262306a36Sopenharmony_ci dev_dbg(info->device, "Set %s as pixclock source.\n", 64362306a36Sopenharmony_ci (div == 2) ? "MCLK/2" : "MCLK"); 64462306a36Sopenharmony_ci old1f |= 0x40; 64562306a36Sopenharmony_ci old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; 64662306a36Sopenharmony_ci if (div == 2) 64762306a36Sopenharmony_ci old1e |= 1; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1E, old1e); 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1F, old1f); 65262306a36Sopenharmony_ci} 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci/************************************************************************* 65562306a36Sopenharmony_ci cirrusfb_set_par_foo() 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci actually writes the values for a new video mode into the hardware, 65862306a36Sopenharmony_ci**************************************************************************/ 65962306a36Sopenharmony_cistatic int cirrusfb_set_par_foo(struct fb_info *info) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 66262306a36Sopenharmony_ci struct fb_var_screeninfo *var = &info->var; 66362306a36Sopenharmony_ci u8 __iomem *regbase = cinfo->regbase; 66462306a36Sopenharmony_ci unsigned char tmp; 66562306a36Sopenharmony_ci int pitch; 66662306a36Sopenharmony_ci const struct cirrusfb_board_info_rec *bi; 66762306a36Sopenharmony_ci int hdispend, hsyncstart, hsyncend, htotal; 66862306a36Sopenharmony_ci int yres, vdispend, vsyncstart, vsyncend, vtotal; 66962306a36Sopenharmony_ci long freq; 67062306a36Sopenharmony_ci int nom, den, div; 67162306a36Sopenharmony_ci unsigned int control = 0, format = 0, threshold = 0; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci dev_dbg(info->device, "Requested mode: %dx%dx%d\n", 67462306a36Sopenharmony_ci var->xres, var->yres, var->bits_per_pixel); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci switch (var->bits_per_pixel) { 67762306a36Sopenharmony_ci case 1: 67862306a36Sopenharmony_ci info->fix.line_length = var->xres_virtual / 8; 67962306a36Sopenharmony_ci info->fix.visual = FB_VISUAL_MONO10; 68062306a36Sopenharmony_ci break; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci case 8: 68362306a36Sopenharmony_ci info->fix.line_length = var->xres_virtual; 68462306a36Sopenharmony_ci info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 68562306a36Sopenharmony_ci break; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci case 16: 68862306a36Sopenharmony_ci case 24: 68962306a36Sopenharmony_ci info->fix.line_length = var->xres_virtual * 69062306a36Sopenharmony_ci var->bits_per_pixel >> 3; 69162306a36Sopenharmony_ci info->fix.visual = FB_VISUAL_TRUECOLOR; 69262306a36Sopenharmony_ci break; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci info->fix.type = FB_TYPE_PACKED_PIXELS; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci init_vgachip(info); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci bi = &cirrusfb_board_info[cinfo->btype]; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci hsyncstart = var->xres + var->right_margin; 70162306a36Sopenharmony_ci hsyncend = hsyncstart + var->hsync_len; 70262306a36Sopenharmony_ci htotal = (hsyncend + var->left_margin) / 8; 70362306a36Sopenharmony_ci hdispend = var->xres / 8; 70462306a36Sopenharmony_ci hsyncstart = hsyncstart / 8; 70562306a36Sopenharmony_ci hsyncend = hsyncend / 8; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci vdispend = var->yres; 70862306a36Sopenharmony_ci vsyncstart = vdispend + var->lower_margin; 70962306a36Sopenharmony_ci vsyncend = vsyncstart + var->vsync_len; 71062306a36Sopenharmony_ci vtotal = vsyncend + var->upper_margin; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) { 71362306a36Sopenharmony_ci vdispend *= 2; 71462306a36Sopenharmony_ci vsyncstart *= 2; 71562306a36Sopenharmony_ci vsyncend *= 2; 71662306a36Sopenharmony_ci vtotal *= 2; 71762306a36Sopenharmony_ci } else if (var->vmode & FB_VMODE_INTERLACED) { 71862306a36Sopenharmony_ci vdispend = (vdispend + 1) / 2; 71962306a36Sopenharmony_ci vsyncstart = (vsyncstart + 1) / 2; 72062306a36Sopenharmony_ci vsyncend = (vsyncend + 1) / 2; 72162306a36Sopenharmony_ci vtotal = (vtotal + 1) / 2; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci yres = vdispend; 72462306a36Sopenharmony_ci if (yres >= 1024) { 72562306a36Sopenharmony_ci vtotal /= 2; 72662306a36Sopenharmony_ci vsyncstart /= 2; 72762306a36Sopenharmony_ci vsyncend /= 2; 72862306a36Sopenharmony_ci vdispend /= 2; 72962306a36Sopenharmony_ci } 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci vdispend -= 1; 73262306a36Sopenharmony_ci vsyncstart -= 1; 73362306a36Sopenharmony_ci vsyncend -= 1; 73462306a36Sopenharmony_ci vtotal -= 2; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci if (cinfo->multiplexing) { 73762306a36Sopenharmony_ci htotal /= 2; 73862306a36Sopenharmony_ci hsyncstart /= 2; 73962306a36Sopenharmony_ci hsyncend /= 2; 74062306a36Sopenharmony_ci hdispend /= 2; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci htotal -= 5; 74462306a36Sopenharmony_ci hdispend -= 1; 74562306a36Sopenharmony_ci hsyncstart += 1; 74662306a36Sopenharmony_ci hsyncend += 1; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ 74962306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci /* if debugging is enabled, all parameters get output before writing */ 75262306a36Sopenharmony_ci dev_dbg(info->device, "CRT0: %d\n", htotal); 75362306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci dev_dbg(info->device, "CRT1: %d\n", hdispend); 75662306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci dev_dbg(info->device, "CRT2: %d\n", var->xres / 8); 75962306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci /* + 128: Compatible read */ 76262306a36Sopenharmony_ci dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32); 76362306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, 76462306a36Sopenharmony_ci 128 + ((htotal + 5) % 32)); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci dev_dbg(info->device, "CRT4: %d\n", hsyncstart); 76762306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci tmp = hsyncend % 32; 77062306a36Sopenharmony_ci if ((htotal + 5) & 32) 77162306a36Sopenharmony_ci tmp += 128; 77262306a36Sopenharmony_ci dev_dbg(info->device, "CRT5: %d\n", tmp); 77362306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff); 77662306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci tmp = 16; /* LineCompare bit #9 */ 77962306a36Sopenharmony_ci if (vtotal & 256) 78062306a36Sopenharmony_ci tmp |= 1; 78162306a36Sopenharmony_ci if (vdispend & 256) 78262306a36Sopenharmony_ci tmp |= 2; 78362306a36Sopenharmony_ci if (vsyncstart & 256) 78462306a36Sopenharmony_ci tmp |= 4; 78562306a36Sopenharmony_ci if ((vdispend + 1) & 256) 78662306a36Sopenharmony_ci tmp |= 8; 78762306a36Sopenharmony_ci if (vtotal & 512) 78862306a36Sopenharmony_ci tmp |= 32; 78962306a36Sopenharmony_ci if (vdispend & 512) 79062306a36Sopenharmony_ci tmp |= 64; 79162306a36Sopenharmony_ci if (vsyncstart & 512) 79262306a36Sopenharmony_ci tmp |= 128; 79362306a36Sopenharmony_ci dev_dbg(info->device, "CRT7: %d\n", tmp); 79462306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci tmp = 0x40; /* LineCompare bit #8 */ 79762306a36Sopenharmony_ci if ((vdispend + 1) & 512) 79862306a36Sopenharmony_ci tmp |= 0x20; 79962306a36Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) 80062306a36Sopenharmony_ci tmp |= 0x80; 80162306a36Sopenharmony_ci dev_dbg(info->device, "CRT9: %d\n", tmp); 80262306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff); 80562306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16); 80862306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff); 81162306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff); 81462306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff); 81762306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci dev_dbg(info->device, "CRT18: 0xff\n"); 82062306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci tmp = 0; 82362306a36Sopenharmony_ci if (var->vmode & FB_VMODE_INTERLACED) 82462306a36Sopenharmony_ci tmp |= 1; 82562306a36Sopenharmony_ci if ((htotal + 5) & 64) 82662306a36Sopenharmony_ci tmp |= 16; 82762306a36Sopenharmony_ci if ((htotal + 5) & 128) 82862306a36Sopenharmony_ci tmp |= 32; 82962306a36Sopenharmony_ci if (vtotal & 256) 83062306a36Sopenharmony_ci tmp |= 64; 83162306a36Sopenharmony_ci if (vtotal & 512) 83262306a36Sopenharmony_ci tmp |= 128; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci dev_dbg(info->device, "CRT1a: %d\n", tmp); 83562306a36Sopenharmony_ci vga_wcrt(regbase, CL_CRT1A, tmp); 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci freq = PICOS2KHZ(var->pixclock); 83862306a36Sopenharmony_ci if (var->bits_per_pixel == 24) 83962306a36Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) 84062306a36Sopenharmony_ci freq *= 3; 84162306a36Sopenharmony_ci if (cinfo->multiplexing) 84262306a36Sopenharmony_ci freq /= 2; 84362306a36Sopenharmony_ci if (cinfo->doubleVCLK) 84462306a36Sopenharmony_ci freq *= 2; 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci bestclock(freq, &nom, &den, &div); 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n", 84962306a36Sopenharmony_ci freq, nom, den, div); 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci /* set VCLK0 */ 85262306a36Sopenharmony_ci /* hardware RefClock: 14.31818 MHz */ 85362306a36Sopenharmony_ci /* formula: VClk = (OSC * N) / (D * (1+P)) */ 85462306a36Sopenharmony_ci /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 || 85762306a36Sopenharmony_ci cinfo->btype == BT_SD64) { 85862306a36Sopenharmony_ci /* if freq is close to mclk or mclk/2 select mclk 85962306a36Sopenharmony_ci * as clock source 86062306a36Sopenharmony_ci */ 86162306a36Sopenharmony_ci int divMCLK = cirrusfb_check_mclk(info, freq); 86262306a36Sopenharmony_ci if (divMCLK) 86362306a36Sopenharmony_ci nom = 0; 86462306a36Sopenharmony_ci cirrusfb_set_mclk_as_source(info, divMCLK); 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci if (is_laguna(cinfo)) { 86762306a36Sopenharmony_ci long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); 86862306a36Sopenharmony_ci unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407); 86962306a36Sopenharmony_ci unsigned short tile_control; 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci if (cinfo->btype == BT_LAGUNAB) { 87262306a36Sopenharmony_ci tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4); 87362306a36Sopenharmony_ci tile_control &= ~0x80; 87462306a36Sopenharmony_ci fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4); 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc); 87862306a36Sopenharmony_ci fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407); 87962306a36Sopenharmony_ci control = fb_readw(cinfo->laguna_mmio + 0x402); 88062306a36Sopenharmony_ci threshold = fb_readw(cinfo->laguna_mmio + 0xea); 88162306a36Sopenharmony_ci control &= ~0x6800; 88262306a36Sopenharmony_ci format = 0; 88362306a36Sopenharmony_ci threshold &= 0xffc0 & 0x3fbf; 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci if (nom) { 88662306a36Sopenharmony_ci tmp = den << 1; 88762306a36Sopenharmony_ci if (div != 0) 88862306a36Sopenharmony_ci tmp |= 1; 88962306a36Sopenharmony_ci /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ 89062306a36Sopenharmony_ci if ((cinfo->btype == BT_SD64) || 89162306a36Sopenharmony_ci (cinfo->btype == BT_ALPINE) || 89262306a36Sopenharmony_ci (cinfo->btype == BT_GD5480)) 89362306a36Sopenharmony_ci tmp |= 0x80; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci /* Laguna chipset has reversed clock registers */ 89662306a36Sopenharmony_ci if (is_laguna(cinfo)) { 89762306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRE, tmp); 89862306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR1E, nom); 89962306a36Sopenharmony_ci } else { 90062306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRE, nom); 90162306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR1E, tmp); 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci if (yres >= 1024) 90662306a36Sopenharmony_ci /* 1280x1024 */ 90762306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); 90862306a36Sopenharmony_ci else 90962306a36Sopenharmony_ci /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 91062306a36Sopenharmony_ci * address wrap, no compat. */ 91162306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci /* don't know if it would hurt to also program this if no interlaced */ 91462306a36Sopenharmony_ci /* mode is used, but I feel better this way.. :-) */ 91562306a36Sopenharmony_ci if (var->vmode & FB_VMODE_INTERLACED) 91662306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2); 91762306a36Sopenharmony_ci else 91862306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci /* adjust horizontal/vertical sync type (low/high), use VCLK3 */ 92162306a36Sopenharmony_ci /* enable display memory & CRTC I/O address for color mode */ 92262306a36Sopenharmony_ci tmp = 0x03 | 0xc; 92362306a36Sopenharmony_ci if (var->sync & FB_SYNC_HOR_HIGH_ACT) 92462306a36Sopenharmony_ci tmp |= 0x40; 92562306a36Sopenharmony_ci if (var->sync & FB_SYNC_VERT_HIGH_ACT) 92662306a36Sopenharmony_ci tmp |= 0x80; 92762306a36Sopenharmony_ci WGen(cinfo, VGA_MIS_W, tmp); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci /* text cursor on and start line */ 93062306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); 93162306a36Sopenharmony_ci /* text cursor end line */ 93262306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31); 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci /****************************************************** 93562306a36Sopenharmony_ci * 93662306a36Sopenharmony_ci * 1 bpp 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci */ 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci /* programming for different color depths */ 94162306a36Sopenharmony_ci if (var->bits_per_pixel == 1) { 94262306a36Sopenharmony_ci dev_dbg(info->device, "preparing for 1 bit deep display\n"); 94362306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci /* SR07 */ 94662306a36Sopenharmony_ci switch (cinfo->btype) { 94762306a36Sopenharmony_ci case BT_SD64: 94862306a36Sopenharmony_ci case BT_PICCOLO: 94962306a36Sopenharmony_ci case BT_PICASSO: 95062306a36Sopenharmony_ci case BT_SPECTRUM: 95162306a36Sopenharmony_ci case BT_PICASSO4: 95262306a36Sopenharmony_ci case BT_ALPINE: 95362306a36Sopenharmony_ci case BT_GD5480: 95462306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 95562306a36Sopenharmony_ci cinfo->multiplexing ? 95662306a36Sopenharmony_ci bi->sr07_1bpp_mux : bi->sr07_1bpp); 95762306a36Sopenharmony_ci break; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci case BT_LAGUNA: 96062306a36Sopenharmony_ci case BT_LAGUNAB: 96162306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 96262306a36Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci default: 96662306a36Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 96762306a36Sopenharmony_ci break; 96862306a36Sopenharmony_ci } 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* Extended Sequencer Mode */ 97162306a36Sopenharmony_ci switch (cinfo->btype) { 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci case BT_PICCOLO: 97462306a36Sopenharmony_ci case BT_SPECTRUM: 97562306a36Sopenharmony_ci /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ 97662306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 97762306a36Sopenharmony_ci break; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci case BT_PICASSO: 98062306a36Sopenharmony_ci /* ## vorher d0 avoid FIFO underruns..? */ 98162306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xd0); 98262306a36Sopenharmony_ci break; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci case BT_SD64: 98562306a36Sopenharmony_ci case BT_PICASSO4: 98662306a36Sopenharmony_ci case BT_ALPINE: 98762306a36Sopenharmony_ci case BT_GD5480: 98862306a36Sopenharmony_ci case BT_LAGUNA: 98962306a36Sopenharmony_ci case BT_LAGUNAB: 99062306a36Sopenharmony_ci /* do nothing */ 99162306a36Sopenharmony_ci break; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci default: 99462306a36Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 99562306a36Sopenharmony_ci break; 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci /* pixel mask: pass-through for first plane */ 99962306a36Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0x01); 100062306a36Sopenharmony_ci if (cinfo->multiplexing) 100162306a36Sopenharmony_ci /* hidden dac reg: 1280x1024 */ 100262306a36Sopenharmony_ci WHDR(cinfo, 0x4a); 100362306a36Sopenharmony_ci else 100462306a36Sopenharmony_ci /* hidden dac: nothing */ 100562306a36Sopenharmony_ci WHDR(cinfo, 0); 100662306a36Sopenharmony_ci /* memory mode: odd/even, ext. memory */ 100762306a36Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); 100862306a36Sopenharmony_ci /* plane mask: only write to first plane */ 100962306a36Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci /****************************************************** 101362306a36Sopenharmony_ci * 101462306a36Sopenharmony_ci * 8 bpp 101562306a36Sopenharmony_ci * 101662306a36Sopenharmony_ci */ 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci else if (var->bits_per_pixel == 8) { 101962306a36Sopenharmony_ci dev_dbg(info->device, "preparing for 8 bit deep display\n"); 102062306a36Sopenharmony_ci switch (cinfo->btype) { 102162306a36Sopenharmony_ci case BT_SD64: 102262306a36Sopenharmony_ci case BT_PICCOLO: 102362306a36Sopenharmony_ci case BT_PICASSO: 102462306a36Sopenharmony_ci case BT_SPECTRUM: 102562306a36Sopenharmony_ci case BT_PICASSO4: 102662306a36Sopenharmony_ci case BT_ALPINE: 102762306a36Sopenharmony_ci case BT_GD5480: 102862306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 102962306a36Sopenharmony_ci cinfo->multiplexing ? 103062306a36Sopenharmony_ci bi->sr07_8bpp_mux : bi->sr07_8bpp); 103162306a36Sopenharmony_ci break; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci case BT_LAGUNA: 103462306a36Sopenharmony_ci case BT_LAGUNAB: 103562306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 103662306a36Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) | 0x01); 103762306a36Sopenharmony_ci threshold |= 0x10; 103862306a36Sopenharmony_ci break; 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci default: 104162306a36Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 104262306a36Sopenharmony_ci break; 104362306a36Sopenharmony_ci } 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci switch (cinfo->btype) { 104662306a36Sopenharmony_ci case BT_PICCOLO: 104762306a36Sopenharmony_ci case BT_PICASSO: 104862306a36Sopenharmony_ci case BT_SPECTRUM: 104962306a36Sopenharmony_ci /* Fast Page-Mode writes */ 105062306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 105162306a36Sopenharmony_ci break; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci case BT_PICASSO4: 105462306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 105562306a36Sopenharmony_ci /* ### INCOMPLETE!! */ 105662306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb8); 105762306a36Sopenharmony_ci#endif 105862306a36Sopenharmony_ci case BT_ALPINE: 105962306a36Sopenharmony_ci case BT_SD64: 106062306a36Sopenharmony_ci case BT_GD5480: 106162306a36Sopenharmony_ci case BT_LAGUNA: 106262306a36Sopenharmony_ci case BT_LAGUNAB: 106362306a36Sopenharmony_ci /* do nothing */ 106462306a36Sopenharmony_ci break; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci default: 106762306a36Sopenharmony_ci dev_warn(info->device, "unknown board\n"); 106862306a36Sopenharmony_ci break; 106962306a36Sopenharmony_ci } 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci /* mode register: 256 color mode */ 107262306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 107362306a36Sopenharmony_ci if (cinfo->multiplexing) 107462306a36Sopenharmony_ci /* hidden dac reg: 1280x1024 */ 107562306a36Sopenharmony_ci WHDR(cinfo, 0x4a); 107662306a36Sopenharmony_ci else 107762306a36Sopenharmony_ci /* hidden dac: nothing */ 107862306a36Sopenharmony_ci WHDR(cinfo, 0); 107962306a36Sopenharmony_ci } 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci /****************************************************** 108262306a36Sopenharmony_ci * 108362306a36Sopenharmony_ci * 16 bpp 108462306a36Sopenharmony_ci * 108562306a36Sopenharmony_ci */ 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci else if (var->bits_per_pixel == 16) { 108862306a36Sopenharmony_ci dev_dbg(info->device, "preparing for 16 bit deep display\n"); 108962306a36Sopenharmony_ci switch (cinfo->btype) { 109062306a36Sopenharmony_ci case BT_PICCOLO: 109162306a36Sopenharmony_ci case BT_SPECTRUM: 109262306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x87); 109362306a36Sopenharmony_ci /* Fast Page-Mode writes */ 109462306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 109562306a36Sopenharmony_ci break; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci case BT_PICASSO: 109862306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x27); 109962306a36Sopenharmony_ci /* Fast Page-Mode writes */ 110062306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 110162306a36Sopenharmony_ci break; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci case BT_SD64: 110462306a36Sopenharmony_ci case BT_PICASSO4: 110562306a36Sopenharmony_ci case BT_ALPINE: 110662306a36Sopenharmony_ci /* Extended Sequencer Mode: 256c col. mode */ 110762306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 110862306a36Sopenharmony_ci cinfo->doubleVCLK ? 0xa3 : 0xa7); 110962306a36Sopenharmony_ci break; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci case BT_GD5480: 111262306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x17); 111362306a36Sopenharmony_ci /* We already set SRF and SR1F */ 111462306a36Sopenharmony_ci break; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci case BT_LAGUNA: 111762306a36Sopenharmony_ci case BT_LAGUNAB: 111862306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 111962306a36Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 112062306a36Sopenharmony_ci control |= 0x2000; 112162306a36Sopenharmony_ci format |= 0x1400; 112262306a36Sopenharmony_ci threshold |= 0x10; 112362306a36Sopenharmony_ci break; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci default: 112662306a36Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 112762306a36Sopenharmony_ci break; 112862306a36Sopenharmony_ci } 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci /* mode register: 256 color mode */ 113162306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 113262306a36Sopenharmony_ci#ifdef CONFIG_PCI 113362306a36Sopenharmony_ci WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1); 113462306a36Sopenharmony_ci#elif defined(CONFIG_ZORRO) 113562306a36Sopenharmony_ci /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ 113662306a36Sopenharmony_ci WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ 113762306a36Sopenharmony_ci#endif 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci 114062306a36Sopenharmony_ci /****************************************************** 114162306a36Sopenharmony_ci * 114262306a36Sopenharmony_ci * 24 bpp 114362306a36Sopenharmony_ci * 114462306a36Sopenharmony_ci */ 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci else if (var->bits_per_pixel == 24) { 114762306a36Sopenharmony_ci dev_dbg(info->device, "preparing for 24 bit deep display\n"); 114862306a36Sopenharmony_ci switch (cinfo->btype) { 114962306a36Sopenharmony_ci case BT_PICCOLO: 115062306a36Sopenharmony_ci case BT_SPECTRUM: 115162306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x85); 115262306a36Sopenharmony_ci /* Fast Page-Mode writes */ 115362306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 115462306a36Sopenharmony_ci break; 115562306a36Sopenharmony_ci 115662306a36Sopenharmony_ci case BT_PICASSO: 115762306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x25); 115862306a36Sopenharmony_ci /* Fast Page-Mode writes */ 115962306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 116062306a36Sopenharmony_ci break; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci case BT_SD64: 116362306a36Sopenharmony_ci case BT_PICASSO4: 116462306a36Sopenharmony_ci case BT_ALPINE: 116562306a36Sopenharmony_ci /* Extended Sequencer Mode: 256c col. mode */ 116662306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0xa5); 116762306a36Sopenharmony_ci break; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci case BT_GD5480: 117062306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x15); 117162306a36Sopenharmony_ci /* We already set SRF and SR1F */ 117262306a36Sopenharmony_ci break; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci case BT_LAGUNA: 117562306a36Sopenharmony_ci case BT_LAGUNAB: 117662306a36Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 117762306a36Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 117862306a36Sopenharmony_ci control |= 0x4000; 117962306a36Sopenharmony_ci format |= 0x2400; 118062306a36Sopenharmony_ci threshold |= 0x20; 118162306a36Sopenharmony_ci break; 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci default: 118462306a36Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 118562306a36Sopenharmony_ci break; 118662306a36Sopenharmony_ci } 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ci /* mode register: 256 color mode */ 118962306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 119062306a36Sopenharmony_ci /* hidden dac reg: 8-8-8 mode (24 or 32) */ 119162306a36Sopenharmony_ci WHDR(cinfo, 0xc5); 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci /****************************************************** 119562306a36Sopenharmony_ci * 119662306a36Sopenharmony_ci * unknown/unsupported bpp 119762306a36Sopenharmony_ci * 119862306a36Sopenharmony_ci */ 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci else 120162306a36Sopenharmony_ci dev_err(info->device, 120262306a36Sopenharmony_ci "What's this? requested color depth == %d.\n", 120362306a36Sopenharmony_ci var->bits_per_pixel); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci pitch = info->fix.line_length >> 3; 120662306a36Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff); 120762306a36Sopenharmony_ci tmp = 0x22; 120862306a36Sopenharmony_ci if (pitch & 0x100) 120962306a36Sopenharmony_ci tmp |= 0x10; /* offset overflow bit */ 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci /* screen start addr #16-18, fastpagemode cycles */ 121262306a36Sopenharmony_ci vga_wcrt(regbase, CL_CRT1B, tmp); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci /* screen start address bit 19 */ 121562306a36Sopenharmony_ci if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) 121662306a36Sopenharmony_ci vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1); 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci if (is_laguna(cinfo)) { 121962306a36Sopenharmony_ci tmp = 0; 122062306a36Sopenharmony_ci if ((htotal + 5) & 256) 122162306a36Sopenharmony_ci tmp |= 128; 122262306a36Sopenharmony_ci if (hdispend & 256) 122362306a36Sopenharmony_ci tmp |= 64; 122462306a36Sopenharmony_ci if (hsyncstart & 256) 122562306a36Sopenharmony_ci tmp |= 48; 122662306a36Sopenharmony_ci if (vtotal & 1024) 122762306a36Sopenharmony_ci tmp |= 8; 122862306a36Sopenharmony_ci if (vdispend & 1024) 122962306a36Sopenharmony_ci tmp |= 4; 123062306a36Sopenharmony_ci if (vsyncstart & 1024) 123162306a36Sopenharmony_ci tmp |= 3; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci vga_wcrt(regbase, CL_CRT1E, tmp); 123462306a36Sopenharmony_ci dev_dbg(info->device, "CRT1e: %d\n", tmp); 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci /* pixel panning */ 123862306a36Sopenharmony_ci vga_wattr(regbase, CL_AR33, 0); 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci /* [ EGS: SetOffset(); ] */ 124162306a36Sopenharmony_ci /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 124262306a36Sopenharmony_ci AttrOn(cinfo); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci if (is_laguna(cinfo)) { 124562306a36Sopenharmony_ci /* no tiles */ 124662306a36Sopenharmony_ci fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402); 124762306a36Sopenharmony_ci fb_writew(format, cinfo->laguna_mmio + 0xc0); 124862306a36Sopenharmony_ci fb_writew(threshold, cinfo->laguna_mmio + 0xea); 124962306a36Sopenharmony_ci } 125062306a36Sopenharmony_ci /* finally, turn on everything - turn off "FullBandwidth" bit */ 125162306a36Sopenharmony_ci /* also, set "DotClock%2" bit where requested */ 125262306a36Sopenharmony_ci tmp = 0x01; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? 125562306a36Sopenharmony_ci if (var->vmode & FB_VMODE_CLOCK_HALVE) 125662306a36Sopenharmony_ci tmp |= 0x08; 125762306a36Sopenharmony_ci*/ 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); 126062306a36Sopenharmony_ci dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 126362306a36Sopenharmony_ci cirrusfb_dbg_reg_dump(info, NULL); 126462306a36Sopenharmony_ci#endif 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci return 0; 126762306a36Sopenharmony_ci} 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci/* for some reason incomprehensible to me, cirrusfb requires that you write 127062306a36Sopenharmony_ci * the registers twice for the settings to take..grr. -dte */ 127162306a36Sopenharmony_cistatic int cirrusfb_set_par(struct fb_info *info) 127262306a36Sopenharmony_ci{ 127362306a36Sopenharmony_ci cirrusfb_set_par_foo(info); 127462306a36Sopenharmony_ci return cirrusfb_set_par_foo(info); 127562306a36Sopenharmony_ci} 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_cistatic int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, 127862306a36Sopenharmony_ci unsigned blue, unsigned transp, 127962306a36Sopenharmony_ci struct fb_info *info) 128062306a36Sopenharmony_ci{ 128162306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (regno > 255) 128462306a36Sopenharmony_ci return -EINVAL; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 128762306a36Sopenharmony_ci u32 v; 128862306a36Sopenharmony_ci red >>= (16 - info->var.red.length); 128962306a36Sopenharmony_ci green >>= (16 - info->var.green.length); 129062306a36Sopenharmony_ci blue >>= (16 - info->var.blue.length); 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci if (regno >= 16) 129362306a36Sopenharmony_ci return 1; 129462306a36Sopenharmony_ci v = (red << info->var.red.offset) | 129562306a36Sopenharmony_ci (green << info->var.green.offset) | 129662306a36Sopenharmony_ci (blue << info->var.blue.offset); 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci cinfo->pseudo_palette[regno] = v; 129962306a36Sopenharmony_ci return 0; 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci if (info->var.bits_per_pixel == 8) 130362306a36Sopenharmony_ci WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10); 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci return 0; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci} 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci/************************************************************************* 131062306a36Sopenharmony_ci cirrusfb_pan_display() 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci performs display panning - provided hardware permits this 131362306a36Sopenharmony_ci**************************************************************************/ 131462306a36Sopenharmony_cistatic int cirrusfb_pan_display(struct fb_var_screeninfo *var, 131562306a36Sopenharmony_ci struct fb_info *info) 131662306a36Sopenharmony_ci{ 131762306a36Sopenharmony_ci int xoffset; 131862306a36Sopenharmony_ci unsigned long base; 131962306a36Sopenharmony_ci unsigned char tmp, xpix; 132062306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci /* no range checks for xoffset and yoffset, */ 132362306a36Sopenharmony_ci /* as fb_pan_display has already done this */ 132462306a36Sopenharmony_ci if (var->vmode & FB_VMODE_YWRAP) 132562306a36Sopenharmony_ci return -EINVAL; 132662306a36Sopenharmony_ci 132762306a36Sopenharmony_ci xoffset = var->xoffset * info->var.bits_per_pixel / 8; 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci base = var->yoffset * info->fix.line_length + xoffset; 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci if (info->var.bits_per_pixel == 1) { 133262306a36Sopenharmony_ci /* base is already correct */ 133362306a36Sopenharmony_ci xpix = (unsigned char) (var->xoffset % 8); 133462306a36Sopenharmony_ci } else { 133562306a36Sopenharmony_ci base /= 4; 133662306a36Sopenharmony_ci xpix = (unsigned char) ((xoffset % 4) * 2); 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci if (!is_laguna(cinfo)) 134062306a36Sopenharmony_ci cirrusfb_WaitBLT(cinfo->regbase); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci /* lower 8 + 8 bits of screen start address */ 134362306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff); 134462306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci /* 0xf2 is %11110010, exclude tmp bits */ 134762306a36Sopenharmony_ci tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2; 134862306a36Sopenharmony_ci /* construct bits 16, 17 and 18 of screen start address */ 134962306a36Sopenharmony_ci if (base & 0x10000) 135062306a36Sopenharmony_ci tmp |= 0x01; 135162306a36Sopenharmony_ci if (base & 0x20000) 135262306a36Sopenharmony_ci tmp |= 0x04; 135362306a36Sopenharmony_ci if (base & 0x40000) 135462306a36Sopenharmony_ci tmp |= 0x08; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1B, tmp); 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci /* construct bit 19 of screen start address */ 135962306a36Sopenharmony_ci if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { 136062306a36Sopenharmony_ci tmp = vga_rcrt(cinfo->regbase, CL_CRT1D); 136162306a36Sopenharmony_ci if (is_laguna(cinfo)) 136262306a36Sopenharmony_ci tmp = (tmp & ~0x18) | ((base >> 16) & 0x18); 136362306a36Sopenharmony_ci else 136462306a36Sopenharmony_ci tmp = (tmp & ~0x80) | ((base >> 12) & 0x80); 136562306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci /* write pixel panning value to AR33; this does not quite work in 8bpp 136962306a36Sopenharmony_ci * 137062306a36Sopenharmony_ci * ### Piccolo..? Will this work? 137162306a36Sopenharmony_ci */ 137262306a36Sopenharmony_ci if (info->var.bits_per_pixel == 1) 137362306a36Sopenharmony_ci vga_wattr(cinfo->regbase, CL_AR33, xpix); 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci return 0; 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_cistatic int cirrusfb_blank(int blank_mode, struct fb_info *info) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci /* 138162306a36Sopenharmony_ci * Blank the screen if blank_mode != 0, else unblank. If blank == NULL 138262306a36Sopenharmony_ci * then the caller blanks by setting the CLUT (Color Look Up Table) 138362306a36Sopenharmony_ci * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking 138462306a36Sopenharmony_ci * failed due to e.g. a video mode which doesn't support it. 138562306a36Sopenharmony_ci * Implements VESA suspend and powerdown modes on hardware that 138662306a36Sopenharmony_ci * supports disabling hsync/vsync: 138762306a36Sopenharmony_ci * blank_mode == 2: suspend vsync 138862306a36Sopenharmony_ci * blank_mode == 3: suspend hsync 138962306a36Sopenharmony_ci * blank_mode == 4: powerdown 139062306a36Sopenharmony_ci */ 139162306a36Sopenharmony_ci unsigned char val; 139262306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 139362306a36Sopenharmony_ci int current_mode = cinfo->blank_mode; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING || 139862306a36Sopenharmony_ci current_mode == blank_mode) { 139962306a36Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 0\n"); 140062306a36Sopenharmony_ci return 0; 140162306a36Sopenharmony_ci } 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci /* Undo current */ 140462306a36Sopenharmony_ci if (current_mode == FB_BLANK_NORMAL || 140562306a36Sopenharmony_ci current_mode == FB_BLANK_UNBLANK) 140662306a36Sopenharmony_ci /* clear "FullBandwidth" bit */ 140762306a36Sopenharmony_ci val = 0; 140862306a36Sopenharmony_ci else 140962306a36Sopenharmony_ci /* set "FullBandwidth" bit */ 141062306a36Sopenharmony_ci val = 0x20; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf; 141362306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val); 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci switch (blank_mode) { 141662306a36Sopenharmony_ci case FB_BLANK_UNBLANK: 141762306a36Sopenharmony_ci case FB_BLANK_NORMAL: 141862306a36Sopenharmony_ci val = 0x00; 141962306a36Sopenharmony_ci break; 142062306a36Sopenharmony_ci case FB_BLANK_VSYNC_SUSPEND: 142162306a36Sopenharmony_ci val = 0x04; 142262306a36Sopenharmony_ci break; 142362306a36Sopenharmony_ci case FB_BLANK_HSYNC_SUSPEND: 142462306a36Sopenharmony_ci val = 0x02; 142562306a36Sopenharmony_ci break; 142662306a36Sopenharmony_ci case FB_BLANK_POWERDOWN: 142762306a36Sopenharmony_ci val = 0x06; 142862306a36Sopenharmony_ci break; 142962306a36Sopenharmony_ci default: 143062306a36Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 1\n"); 143162306a36Sopenharmony_ci return 1; 143262306a36Sopenharmony_ci } 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRE, val); 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci cinfo->blank_mode = blank_mode; 143762306a36Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 0\n"); 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci /* Let fbcon do a soft blank for us */ 144062306a36Sopenharmony_ci return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; 144162306a36Sopenharmony_ci} 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci/**** END Hardware specific Routines **************************************/ 144462306a36Sopenharmony_ci/****************************************************************************/ 144562306a36Sopenharmony_ci/**** BEGIN Internal Routines ***********************************************/ 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_cistatic void init_vgachip(struct fb_info *info) 144862306a36Sopenharmony_ci{ 144962306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 145062306a36Sopenharmony_ci const struct cirrusfb_board_info_rec *bi; 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci assert(cinfo != NULL); 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci bi = &cirrusfb_board_info[cinfo->btype]; 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci /* reset board globally */ 145762306a36Sopenharmony_ci switch (cinfo->btype) { 145862306a36Sopenharmony_ci case BT_PICCOLO: 145962306a36Sopenharmony_ci WSFR(cinfo, 0x01); 146062306a36Sopenharmony_ci udelay(500); 146162306a36Sopenharmony_ci WSFR(cinfo, 0x51); 146262306a36Sopenharmony_ci udelay(500); 146362306a36Sopenharmony_ci break; 146462306a36Sopenharmony_ci case BT_PICASSO: 146562306a36Sopenharmony_ci WSFR2(cinfo, 0xff); 146662306a36Sopenharmony_ci udelay(500); 146762306a36Sopenharmony_ci break; 146862306a36Sopenharmony_ci case BT_SD64: 146962306a36Sopenharmony_ci case BT_SPECTRUM: 147062306a36Sopenharmony_ci WSFR(cinfo, 0x1f); 147162306a36Sopenharmony_ci udelay(500); 147262306a36Sopenharmony_ci WSFR(cinfo, 0x4f); 147362306a36Sopenharmony_ci udelay(500); 147462306a36Sopenharmony_ci break; 147562306a36Sopenharmony_ci case BT_PICASSO4: 147662306a36Sopenharmony_ci /* disable flickerfixer */ 147762306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); 147862306a36Sopenharmony_ci mdelay(100); 147962306a36Sopenharmony_ci /* mode */ 148062306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x00); 148162306a36Sopenharmony_ci fallthrough; 148262306a36Sopenharmony_ci case BT_GD5480: 148362306a36Sopenharmony_ci /* from Klaus' NetBSD driver: */ 148462306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); 148562306a36Sopenharmony_ci fallthrough; 148662306a36Sopenharmony_ci case BT_ALPINE: 148762306a36Sopenharmony_ci /* put blitter into 542x compat */ 148862306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR33, 0x00); 148962306a36Sopenharmony_ci break; 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci case BT_LAGUNA: 149262306a36Sopenharmony_ci case BT_LAGUNAB: 149362306a36Sopenharmony_ci /* Nothing to do to reset the board. */ 149462306a36Sopenharmony_ci break; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci default: 149762306a36Sopenharmony_ci dev_err(info->device, "Warning: Unknown board type\n"); 149862306a36Sopenharmony_ci break; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci /* make sure RAM size set by this point */ 150262306a36Sopenharmony_ci assert(info->screen_size > 0); 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci /* the P4 is not fully initialized here; I rely on it having been */ 150562306a36Sopenharmony_ci /* inited under AmigaOS already, which seems to work just fine */ 150662306a36Sopenharmony_ci /* (Klaus advised to do it this way) */ 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci if (cinfo->btype != BT_PICASSO4) { 150962306a36Sopenharmony_ci WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */ 151062306a36Sopenharmony_ci WGen(cinfo, CL_POS102, 0x01); 151162306a36Sopenharmony_ci WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */ 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci if (cinfo->btype != BT_SD64) 151462306a36Sopenharmony_ci WGen(cinfo, CL_VSSM2, 0x01); 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci /* reset sequencer logic */ 151762306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci /* FullBandwidth (video off) and 8/9 dot clock */ 152062306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci /* "magic cookie" - doesn't make any sense to me.. */ 152362306a36Sopenharmony_ci/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ 152462306a36Sopenharmony_ci /* unlock all extension registers */ 152562306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci switch (cinfo->btype) { 152862306a36Sopenharmony_ci case BT_GD5480: 152962306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); 153062306a36Sopenharmony_ci break; 153162306a36Sopenharmony_ci case BT_ALPINE: 153262306a36Sopenharmony_ci case BT_LAGUNA: 153362306a36Sopenharmony_ci case BT_LAGUNAB: 153462306a36Sopenharmony_ci break; 153562306a36Sopenharmony_ci case BT_SD64: 153662306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 153762306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); 153862306a36Sopenharmony_ci#endif 153962306a36Sopenharmony_ci break; 154062306a36Sopenharmony_ci default: 154162306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); 154262306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0); 154362306a36Sopenharmony_ci break; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci } 154662306a36Sopenharmony_ci /* plane mask: nothing */ 154762306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); 154862306a36Sopenharmony_ci /* character map select: doesn't even matter in gx mode */ 154962306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); 155062306a36Sopenharmony_ci /* memory mode: chain4, ext. memory */ 155162306a36Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* controller-internal base address of video memory */ 155462306a36Sopenharmony_ci if (bi->init_sr07) 155562306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07); 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */ 155862306a36Sopenharmony_ci /* EEPROM control: shouldn't be necessary to write to this at all.. */ 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci /* graphics cursor X position (incomplete; position gives rem. 3 bits */ 156162306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR10, 0x00); 156262306a36Sopenharmony_ci /* graphics cursor Y position (..."... ) */ 156362306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR11, 0x00); 156462306a36Sopenharmony_ci /* graphics cursor attributes */ 156562306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR12, 0x00); 156662306a36Sopenharmony_ci /* graphics cursor pattern address */ 156762306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR13, 0x00); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci /* writing these on a P4 might give problems.. */ 157062306a36Sopenharmony_ci if (cinfo->btype != BT_PICASSO4) { 157162306a36Sopenharmony_ci /* configuration readback and ext. color */ 157262306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR17, 0x00); 157362306a36Sopenharmony_ci /* signature generator */ 157462306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci /* Screen A preset row scan: none */ 157862306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); 157962306a36Sopenharmony_ci /* Text cursor start: disable text cursor */ 158062306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); 158162306a36Sopenharmony_ci /* Text cursor end: - */ 158262306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); 158362306a36Sopenharmony_ci /* text cursor location high: 0 */ 158462306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); 158562306a36Sopenharmony_ci /* text cursor location low: 0 */ 158662306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci /* Underline Row scanline: - */ 158962306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); 159062306a36Sopenharmony_ci /* ### add 0x40 for text modes with > 30 MHz pixclock */ 159162306a36Sopenharmony_ci /* ext. display controls: ext.adr. wrap */ 159262306a36Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci /* Set/Reset registers: - */ 159562306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); 159662306a36Sopenharmony_ci /* Set/Reset enable: - */ 159762306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); 159862306a36Sopenharmony_ci /* Color Compare: - */ 159962306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); 160062306a36Sopenharmony_ci /* Data Rotate: - */ 160162306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); 160262306a36Sopenharmony_ci /* Read Map Select: - */ 160362306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); 160462306a36Sopenharmony_ci /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ 160562306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00); 160662306a36Sopenharmony_ci /* Miscellaneous: memory map base address, graphics mode */ 160762306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01); 160862306a36Sopenharmony_ci /* Color Don't care: involve all planes */ 160962306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); 161062306a36Sopenharmony_ci /* Bit Mask: no mask at all */ 161162306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 || 161462306a36Sopenharmony_ci is_laguna(cinfo)) 161562306a36Sopenharmony_ci /* (5434 can't have bit 3 set for bitblt) */ 161662306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRB, 0x20); 161762306a36Sopenharmony_ci else 161862306a36Sopenharmony_ci /* Graphics controller mode extensions: finer granularity, 161962306a36Sopenharmony_ci * 8byte data latches 162062306a36Sopenharmony_ci */ 162162306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRB, 0x28); 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */ 162462306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */ 162562306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */ 162662306a36Sopenharmony_ci /* Background color byte 1: - */ 162762306a36Sopenharmony_ci /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */ 162862306a36Sopenharmony_ci /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */ 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci /* Attribute Controller palette registers: "identity mapping" */ 163162306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00); 163262306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01); 163362306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02); 163462306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03); 163562306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04); 163662306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05); 163762306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06); 163862306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07); 163962306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08); 164062306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09); 164162306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a); 164262306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b); 164362306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c); 164462306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d); 164562306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e); 164662306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci /* Attribute Controller mode: graphics mode */ 164962306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01); 165062306a36Sopenharmony_ci /* Overscan color reg.: reg. 0 */ 165162306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); 165262306a36Sopenharmony_ci /* Color Plane enable: Enable all 4 planes */ 165362306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); 165462306a36Sopenharmony_ci /* Color Select: - */ 165562306a36Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci /* BLT Start/status: Blitter reset */ 166062306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x04); 166162306a36Sopenharmony_ci /* - " - : "end-of-reset" */ 166262306a36Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x00); 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci /* misc... */ 166562306a36Sopenharmony_ci WHDR(cinfo, 0); /* Hidden DAC register: - */ 166662306a36Sopenharmony_ci return; 166762306a36Sopenharmony_ci} 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_cistatic void switch_monitor(struct cirrusfb_info *cinfo, int on) 167062306a36Sopenharmony_ci{ 167162306a36Sopenharmony_ci#ifdef CONFIG_ZORRO /* only works on Zorro boards */ 167262306a36Sopenharmony_ci static int IsOn = 0; /* XXX not ok for multiple boards */ 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO4) 167562306a36Sopenharmony_ci return; /* nothing to switch */ 167662306a36Sopenharmony_ci if (cinfo->btype == BT_ALPINE) 167762306a36Sopenharmony_ci return; /* nothing to switch */ 167862306a36Sopenharmony_ci if (cinfo->btype == BT_GD5480) 167962306a36Sopenharmony_ci return; /* nothing to switch */ 168062306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 168162306a36Sopenharmony_ci if ((on && !IsOn) || (!on && IsOn)) 168262306a36Sopenharmony_ci WSFR(cinfo, 0xff); 168362306a36Sopenharmony_ci return; 168462306a36Sopenharmony_ci } 168562306a36Sopenharmony_ci if (on) { 168662306a36Sopenharmony_ci switch (cinfo->btype) { 168762306a36Sopenharmony_ci case BT_SD64: 168862306a36Sopenharmony_ci WSFR(cinfo, cinfo->SFR | 0x21); 168962306a36Sopenharmony_ci break; 169062306a36Sopenharmony_ci case BT_PICCOLO: 169162306a36Sopenharmony_ci WSFR(cinfo, cinfo->SFR | 0x28); 169262306a36Sopenharmony_ci break; 169362306a36Sopenharmony_ci case BT_SPECTRUM: 169462306a36Sopenharmony_ci WSFR(cinfo, 0x6f); 169562306a36Sopenharmony_ci break; 169662306a36Sopenharmony_ci default: /* do nothing */ break; 169762306a36Sopenharmony_ci } 169862306a36Sopenharmony_ci } else { 169962306a36Sopenharmony_ci switch (cinfo->btype) { 170062306a36Sopenharmony_ci case BT_SD64: 170162306a36Sopenharmony_ci WSFR(cinfo, cinfo->SFR & 0xde); 170262306a36Sopenharmony_ci break; 170362306a36Sopenharmony_ci case BT_PICCOLO: 170462306a36Sopenharmony_ci WSFR(cinfo, cinfo->SFR & 0xd7); 170562306a36Sopenharmony_ci break; 170662306a36Sopenharmony_ci case BT_SPECTRUM: 170762306a36Sopenharmony_ci WSFR(cinfo, 0x4f); 170862306a36Sopenharmony_ci break; 170962306a36Sopenharmony_ci default: /* do nothing */ 171062306a36Sopenharmony_ci break; 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci } 171362306a36Sopenharmony_ci#endif /* CONFIG_ZORRO */ 171462306a36Sopenharmony_ci} 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci/******************************************/ 171762306a36Sopenharmony_ci/* Linux 2.6-style accelerated functions */ 171862306a36Sopenharmony_ci/******************************************/ 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_cistatic int cirrusfb_sync(struct fb_info *info) 172162306a36Sopenharmony_ci{ 172262306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 172362306a36Sopenharmony_ci 172462306a36Sopenharmony_ci if (!is_laguna(cinfo)) { 172562306a36Sopenharmony_ci while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03) 172662306a36Sopenharmony_ci cpu_relax(); 172762306a36Sopenharmony_ci } 172862306a36Sopenharmony_ci return 0; 172962306a36Sopenharmony_ci} 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_cistatic void cirrusfb_fillrect(struct fb_info *info, 173262306a36Sopenharmony_ci const struct fb_fillrect *region) 173362306a36Sopenharmony_ci{ 173462306a36Sopenharmony_ci struct fb_fillrect modded; 173562306a36Sopenharmony_ci int vxres, vyres; 173662306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 173762306a36Sopenharmony_ci int m = info->var.bits_per_pixel; 173862306a36Sopenharmony_ci u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? 173962306a36Sopenharmony_ci cinfo->pseudo_palette[region->color] : region->color; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 174262306a36Sopenharmony_ci return; 174362306a36Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED) { 174462306a36Sopenharmony_ci cfb_fillrect(info, region); 174562306a36Sopenharmony_ci return; 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci vxres = info->var.xres_virtual; 174962306a36Sopenharmony_ci vyres = info->var.yres_virtual; 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci memcpy(&modded, region, sizeof(struct fb_fillrect)); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci if (!modded.width || !modded.height || 175462306a36Sopenharmony_ci modded.dx >= vxres || modded.dy >= vyres) 175562306a36Sopenharmony_ci return; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci if (modded.dx + modded.width > vxres) 175862306a36Sopenharmony_ci modded.width = vxres - modded.dx; 175962306a36Sopenharmony_ci if (modded.dy + modded.height > vyres) 176062306a36Sopenharmony_ci modded.height = vyres - modded.dy; 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 176362306a36Sopenharmony_ci info->var.bits_per_pixel, 176462306a36Sopenharmony_ci (region->dx * m) / 8, region->dy, 176562306a36Sopenharmony_ci (region->width * m) / 8, region->height, 176662306a36Sopenharmony_ci color, color, 176762306a36Sopenharmony_ci info->fix.line_length, 0x40); 176862306a36Sopenharmony_ci} 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_cistatic void cirrusfb_copyarea(struct fb_info *info, 177162306a36Sopenharmony_ci const struct fb_copyarea *area) 177262306a36Sopenharmony_ci{ 177362306a36Sopenharmony_ci struct fb_copyarea modded; 177462306a36Sopenharmony_ci u32 vxres, vyres; 177562306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 177662306a36Sopenharmony_ci int m = info->var.bits_per_pixel; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 177962306a36Sopenharmony_ci return; 178062306a36Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED) { 178162306a36Sopenharmony_ci cfb_copyarea(info, area); 178262306a36Sopenharmony_ci return; 178362306a36Sopenharmony_ci } 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci vxres = info->var.xres_virtual; 178662306a36Sopenharmony_ci vyres = info->var.yres_virtual; 178762306a36Sopenharmony_ci memcpy(&modded, area, sizeof(struct fb_copyarea)); 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci if (!modded.width || !modded.height || 179062306a36Sopenharmony_ci modded.sx >= vxres || modded.sy >= vyres || 179162306a36Sopenharmony_ci modded.dx >= vxres || modded.dy >= vyres) 179262306a36Sopenharmony_ci return; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci if (modded.sx + modded.width > vxres) 179562306a36Sopenharmony_ci modded.width = vxres - modded.sx; 179662306a36Sopenharmony_ci if (modded.dx + modded.width > vxres) 179762306a36Sopenharmony_ci modded.width = vxres - modded.dx; 179862306a36Sopenharmony_ci if (modded.sy + modded.height > vyres) 179962306a36Sopenharmony_ci modded.height = vyres - modded.sy; 180062306a36Sopenharmony_ci if (modded.dy + modded.height > vyres) 180162306a36Sopenharmony_ci modded.height = vyres - modded.dy; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel, 180462306a36Sopenharmony_ci (area->sx * m) / 8, area->sy, 180562306a36Sopenharmony_ci (area->dx * m) / 8, area->dy, 180662306a36Sopenharmony_ci (area->width * m) / 8, area->height, 180762306a36Sopenharmony_ci info->fix.line_length); 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci} 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_cistatic void cirrusfb_imageblit(struct fb_info *info, 181262306a36Sopenharmony_ci const struct fb_image *image) 181362306a36Sopenharmony_ci{ 181462306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 181562306a36Sopenharmony_ci unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4; 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 181862306a36Sopenharmony_ci return; 181962306a36Sopenharmony_ci /* Alpine/SD64 does not work at 24bpp ??? */ 182062306a36Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) 182162306a36Sopenharmony_ci cfb_imageblit(info, image); 182262306a36Sopenharmony_ci else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) && 182362306a36Sopenharmony_ci op == 0xc) 182462306a36Sopenharmony_ci cfb_imageblit(info, image); 182562306a36Sopenharmony_ci else { 182662306a36Sopenharmony_ci unsigned size = ((image->width + 7) >> 3) * image->height; 182762306a36Sopenharmony_ci int m = info->var.bits_per_pixel; 182862306a36Sopenharmony_ci u32 fg, bg; 182962306a36Sopenharmony_ci 183062306a36Sopenharmony_ci if (info->var.bits_per_pixel == 8) { 183162306a36Sopenharmony_ci fg = image->fg_color; 183262306a36Sopenharmony_ci bg = image->bg_color; 183362306a36Sopenharmony_ci } else { 183462306a36Sopenharmony_ci fg = ((u32 *)(info->pseudo_palette))[image->fg_color]; 183562306a36Sopenharmony_ci bg = ((u32 *)(info->pseudo_palette))[image->bg_color]; 183662306a36Sopenharmony_ci } 183762306a36Sopenharmony_ci if (info->var.bits_per_pixel == 24) { 183862306a36Sopenharmony_ci /* clear background first */ 183962306a36Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 184062306a36Sopenharmony_ci info->var.bits_per_pixel, 184162306a36Sopenharmony_ci (image->dx * m) / 8, image->dy, 184262306a36Sopenharmony_ci (image->width * m) / 8, 184362306a36Sopenharmony_ci image->height, 184462306a36Sopenharmony_ci bg, bg, 184562306a36Sopenharmony_ci info->fix.line_length, 0x40); 184662306a36Sopenharmony_ci } 184762306a36Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 184862306a36Sopenharmony_ci info->var.bits_per_pixel, 184962306a36Sopenharmony_ci (image->dx * m) / 8, image->dy, 185062306a36Sopenharmony_ci (image->width * m) / 8, image->height, 185162306a36Sopenharmony_ci fg, bg, 185262306a36Sopenharmony_ci info->fix.line_length, op); 185362306a36Sopenharmony_ci memcpy(info->screen_base, image->data, size); 185462306a36Sopenharmony_ci } 185562306a36Sopenharmony_ci} 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci#ifdef CONFIG_PCI 185862306a36Sopenharmony_cistatic int release_io_ports; 185962306a36Sopenharmony_ci 186062306a36Sopenharmony_ci/* Pulled the logic from XFree86 Cirrus driver to get the memory size, 186162306a36Sopenharmony_ci * based on the DRAM bandwidth bit and DRAM bank switching bit. This 186262306a36Sopenharmony_ci * works with 1MB, 2MB and 4MB configurations (which the Motorola boards 186362306a36Sopenharmony_ci * seem to have. */ 186462306a36Sopenharmony_cistatic unsigned int cirrusfb_get_memsize(struct fb_info *info, 186562306a36Sopenharmony_ci u8 __iomem *regbase) 186662306a36Sopenharmony_ci{ 186762306a36Sopenharmony_ci unsigned long mem; 186862306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci if (is_laguna(cinfo)) { 187162306a36Sopenharmony_ci unsigned char SR14 = vga_rseq(regbase, CL_SEQR14); 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci mem = ((SR14 & 7) + 1) << 20; 187462306a36Sopenharmony_ci } else { 187562306a36Sopenharmony_ci unsigned char SRF = vga_rseq(regbase, CL_SEQRF); 187662306a36Sopenharmony_ci switch ((SRF & 0x18)) { 187762306a36Sopenharmony_ci case 0x08: 187862306a36Sopenharmony_ci mem = 512 * 1024; 187962306a36Sopenharmony_ci break; 188062306a36Sopenharmony_ci case 0x10: 188162306a36Sopenharmony_ci mem = 1024 * 1024; 188262306a36Sopenharmony_ci break; 188362306a36Sopenharmony_ci /* 64-bit DRAM data bus width; assume 2MB. 188462306a36Sopenharmony_ci * Also indicates 2MB memory on the 5430. 188562306a36Sopenharmony_ci */ 188662306a36Sopenharmony_ci case 0x18: 188762306a36Sopenharmony_ci mem = 2048 * 1024; 188862306a36Sopenharmony_ci break; 188962306a36Sopenharmony_ci default: 189062306a36Sopenharmony_ci dev_warn(info->device, "Unknown memory size!\n"); 189162306a36Sopenharmony_ci mem = 1024 * 1024; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci /* If DRAM bank switching is enabled, there must be 189462306a36Sopenharmony_ci * twice as much memory installed. (4MB on the 5434) 189562306a36Sopenharmony_ci */ 189662306a36Sopenharmony_ci if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0) 189762306a36Sopenharmony_ci mem *= 2; 189862306a36Sopenharmony_ci } 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ 190162306a36Sopenharmony_ci return mem; 190262306a36Sopenharmony_ci} 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_cistatic void get_pci_addrs(const struct pci_dev *pdev, 190562306a36Sopenharmony_ci unsigned long *display, unsigned long *registers) 190662306a36Sopenharmony_ci{ 190762306a36Sopenharmony_ci assert(pdev != NULL); 190862306a36Sopenharmony_ci assert(display != NULL); 190962306a36Sopenharmony_ci assert(registers != NULL); 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci *display = 0; 191262306a36Sopenharmony_ci *registers = 0; 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci /* This is a best-guess for now */ 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 191762306a36Sopenharmony_ci *display = pci_resource_start(pdev, 1); 191862306a36Sopenharmony_ci *registers = pci_resource_start(pdev, 0); 191962306a36Sopenharmony_ci } else { 192062306a36Sopenharmony_ci *display = pci_resource_start(pdev, 0); 192162306a36Sopenharmony_ci *registers = pci_resource_start(pdev, 1); 192262306a36Sopenharmony_ci } 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci assert(*display != 0); 192562306a36Sopenharmony_ci} 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_cistatic void cirrusfb_pci_unmap(struct fb_info *info) 192862306a36Sopenharmony_ci{ 192962306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(info->device); 193062306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci if (cinfo->laguna_mmio == NULL) 193362306a36Sopenharmony_ci iounmap(cinfo->laguna_mmio); 193462306a36Sopenharmony_ci iounmap(info->screen_base); 193562306a36Sopenharmony_ci#if 0 /* if system didn't claim this region, we would... */ 193662306a36Sopenharmony_ci release_mem_region(0xA0000, 65535); 193762306a36Sopenharmony_ci#endif 193862306a36Sopenharmony_ci if (release_io_ports) 193962306a36Sopenharmony_ci release_region(0x3C0, 32); 194062306a36Sopenharmony_ci pci_release_regions(pdev); 194162306a36Sopenharmony_ci} 194262306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 194562306a36Sopenharmony_cistatic void cirrusfb_zorro_unmap(struct fb_info *info) 194662306a36Sopenharmony_ci{ 194762306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 194862306a36Sopenharmony_ci struct zorro_dev *zdev = to_zorro_dev(info->device); 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci if (info->fix.smem_start > 16 * MB_) 195162306a36Sopenharmony_ci iounmap(info->screen_base); 195262306a36Sopenharmony_ci if (info->fix.mmio_start > 16 * MB_) 195362306a36Sopenharmony_ci iounmap(cinfo->regbase); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci zorro_release_device(zdev); 195662306a36Sopenharmony_ci} 195762306a36Sopenharmony_ci#endif /* CONFIG_ZORRO */ 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci/* function table of the above functions */ 196062306a36Sopenharmony_cistatic const struct fb_ops cirrusfb_ops = { 196162306a36Sopenharmony_ci .owner = THIS_MODULE, 196262306a36Sopenharmony_ci .fb_open = cirrusfb_open, 196362306a36Sopenharmony_ci .fb_release = cirrusfb_release, 196462306a36Sopenharmony_ci .fb_setcolreg = cirrusfb_setcolreg, 196562306a36Sopenharmony_ci .fb_check_var = cirrusfb_check_var, 196662306a36Sopenharmony_ci .fb_set_par = cirrusfb_set_par, 196762306a36Sopenharmony_ci .fb_pan_display = cirrusfb_pan_display, 196862306a36Sopenharmony_ci .fb_blank = cirrusfb_blank, 196962306a36Sopenharmony_ci .fb_fillrect = cirrusfb_fillrect, 197062306a36Sopenharmony_ci .fb_copyarea = cirrusfb_copyarea, 197162306a36Sopenharmony_ci .fb_sync = cirrusfb_sync, 197262306a36Sopenharmony_ci .fb_imageblit = cirrusfb_imageblit, 197362306a36Sopenharmony_ci}; 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_cistatic int cirrusfb_set_fbinfo(struct fb_info *info) 197662306a36Sopenharmony_ci{ 197762306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 197862306a36Sopenharmony_ci struct fb_var_screeninfo *var = &info->var; 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci info->pseudo_palette = cinfo->pseudo_palette; 198162306a36Sopenharmony_ci info->flags = FBINFO_HWACCEL_XPAN 198262306a36Sopenharmony_ci | FBINFO_HWACCEL_YPAN 198362306a36Sopenharmony_ci | FBINFO_HWACCEL_FILLRECT 198462306a36Sopenharmony_ci | FBINFO_HWACCEL_IMAGEBLIT 198562306a36Sopenharmony_ci | FBINFO_HWACCEL_COPYAREA; 198662306a36Sopenharmony_ci if (noaccel || is_laguna(cinfo)) { 198762306a36Sopenharmony_ci info->flags |= FBINFO_HWACCEL_DISABLED; 198862306a36Sopenharmony_ci info->fix.accel = FB_ACCEL_NONE; 198962306a36Sopenharmony_ci } else 199062306a36Sopenharmony_ci info->fix.accel = FB_ACCEL_CIRRUS_ALPINE; 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci info->fbops = &cirrusfb_ops; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci if (cinfo->btype == BT_GD5480) { 199562306a36Sopenharmony_ci if (var->bits_per_pixel == 16) 199662306a36Sopenharmony_ci info->screen_base += 1 * MB_; 199762306a36Sopenharmony_ci if (var->bits_per_pixel == 32) 199862306a36Sopenharmony_ci info->screen_base += 2 * MB_; 199962306a36Sopenharmony_ci } 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci /* Fill fix common fields */ 200262306a36Sopenharmony_ci strscpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name, 200362306a36Sopenharmony_ci sizeof(info->fix.id)); 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci /* monochrome: only 1 memory plane */ 200662306a36Sopenharmony_ci /* 8 bit and above: Use whole memory area */ 200762306a36Sopenharmony_ci info->fix.smem_len = info->screen_size; 200862306a36Sopenharmony_ci if (var->bits_per_pixel == 1) 200962306a36Sopenharmony_ci info->fix.smem_len /= 4; 201062306a36Sopenharmony_ci info->fix.type_aux = 0; 201162306a36Sopenharmony_ci info->fix.xpanstep = 1; 201262306a36Sopenharmony_ci info->fix.ypanstep = 1; 201362306a36Sopenharmony_ci info->fix.ywrapstep = 0; 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_ci /* FIXME: map region at 0xB8000 if available, fill in here */ 201662306a36Sopenharmony_ci info->fix.mmio_len = 0; 201762306a36Sopenharmony_ci 201862306a36Sopenharmony_ci fb_alloc_cmap(&info->cmap, 256, 0); 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci return 0; 202162306a36Sopenharmony_ci} 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_cistatic int cirrusfb_register(struct fb_info *info) 202462306a36Sopenharmony_ci{ 202562306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 202662306a36Sopenharmony_ci int err; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci /* sanity checks */ 202962306a36Sopenharmony_ci assert(cinfo->btype != BT_NONE); 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci /* set all the vital stuff */ 203262306a36Sopenharmony_ci cirrusfb_set_fbinfo(info); 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base); 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 203762306a36Sopenharmony_ci if (!err) { 203862306a36Sopenharmony_ci dev_dbg(info->device, "wrong initial video mode\n"); 203962306a36Sopenharmony_ci err = -EINVAL; 204062306a36Sopenharmony_ci goto err_dealloc_cmap; 204162306a36Sopenharmony_ci } 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci info->var.activate = FB_ACTIVATE_NOW; 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci err = cirrusfb_check_var(&info->var, info); 204662306a36Sopenharmony_ci if (err < 0) { 204762306a36Sopenharmony_ci /* should never happen */ 204862306a36Sopenharmony_ci dev_dbg(info->device, 204962306a36Sopenharmony_ci "choking on default var... umm, no good.\n"); 205062306a36Sopenharmony_ci goto err_dealloc_cmap; 205162306a36Sopenharmony_ci } 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci err = register_framebuffer(info); 205462306a36Sopenharmony_ci if (err < 0) { 205562306a36Sopenharmony_ci dev_err(info->device, 205662306a36Sopenharmony_ci "could not register fb device; err = %d!\n", err); 205762306a36Sopenharmony_ci goto err_dealloc_cmap; 205862306a36Sopenharmony_ci } 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci return 0; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_cierr_dealloc_cmap: 206362306a36Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 206462306a36Sopenharmony_ci return err; 206562306a36Sopenharmony_ci} 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_cistatic void cirrusfb_cleanup(struct fb_info *info) 206862306a36Sopenharmony_ci{ 206962306a36Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci switch_monitor(cinfo, 0); 207262306a36Sopenharmony_ci unregister_framebuffer(info); 207362306a36Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 207462306a36Sopenharmony_ci dev_dbg(info->device, "Framebuffer unregistered\n"); 207562306a36Sopenharmony_ci cinfo->unmap(info); 207662306a36Sopenharmony_ci framebuffer_release(info); 207762306a36Sopenharmony_ci} 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_ci#ifdef CONFIG_PCI 208062306a36Sopenharmony_cistatic int cirrusfb_pci_register(struct pci_dev *pdev, 208162306a36Sopenharmony_ci const struct pci_device_id *ent) 208262306a36Sopenharmony_ci{ 208362306a36Sopenharmony_ci struct cirrusfb_info *cinfo; 208462306a36Sopenharmony_ci struct fb_info *info; 208562306a36Sopenharmony_ci unsigned long board_addr, board_size; 208662306a36Sopenharmony_ci int ret; 208762306a36Sopenharmony_ci 208862306a36Sopenharmony_ci ret = aperture_remove_conflicting_pci_devices(pdev, "cirrusfb"); 208962306a36Sopenharmony_ci if (ret) 209062306a36Sopenharmony_ci return ret; 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci ret = pci_enable_device(pdev); 209362306a36Sopenharmony_ci if (ret < 0) { 209462306a36Sopenharmony_ci printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n"); 209562306a36Sopenharmony_ci goto err_out; 209662306a36Sopenharmony_ci } 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ci info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); 209962306a36Sopenharmony_ci if (!info) { 210062306a36Sopenharmony_ci ret = -ENOMEM; 210162306a36Sopenharmony_ci goto err_out; 210262306a36Sopenharmony_ci } 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci cinfo = info->par; 210562306a36Sopenharmony_ci cinfo->btype = (enum cirrus_board) ent->driver_data; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci dev_dbg(info->device, 210862306a36Sopenharmony_ci " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n", 210962306a36Sopenharmony_ci (unsigned long long)pdev->resource[0].start, cinfo->btype); 211062306a36Sopenharmony_ci dev_dbg(info->device, " base address 1 is 0x%Lx\n", 211162306a36Sopenharmony_ci (unsigned long long)pdev->resource[1].start); 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci dev_dbg(info->device, 211462306a36Sopenharmony_ci "Attempt to get PCI info for Cirrus Graphics Card\n"); 211562306a36Sopenharmony_ci get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); 211662306a36Sopenharmony_ci /* FIXME: this forces VGA. alternatives? */ 211762306a36Sopenharmony_ci cinfo->regbase = NULL; 211862306a36Sopenharmony_ci cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000); 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", 212162306a36Sopenharmony_ci board_addr, info->fix.mmio_start); 212262306a36Sopenharmony_ci 212362306a36Sopenharmony_ci board_size = (cinfo->btype == BT_GD5480) ? 212462306a36Sopenharmony_ci 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase); 212562306a36Sopenharmony_ci 212662306a36Sopenharmony_ci ret = pci_request_regions(pdev, "cirrusfb"); 212762306a36Sopenharmony_ci if (ret < 0) { 212862306a36Sopenharmony_ci dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 212962306a36Sopenharmony_ci board_addr); 213062306a36Sopenharmony_ci goto err_release_fb; 213162306a36Sopenharmony_ci } 213262306a36Sopenharmony_ci#if 0 /* if the system didn't claim this region, we would... */ 213362306a36Sopenharmony_ci if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { 213462306a36Sopenharmony_ci dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 213562306a36Sopenharmony_ci 0xA0000L); 213662306a36Sopenharmony_ci ret = -EBUSY; 213762306a36Sopenharmony_ci goto err_release_regions; 213862306a36Sopenharmony_ci } 213962306a36Sopenharmony_ci#endif 214062306a36Sopenharmony_ci if (request_region(0x3C0, 32, "cirrusfb")) 214162306a36Sopenharmony_ci release_io_ports = 1; 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci info->screen_base = ioremap(board_addr, board_size); 214462306a36Sopenharmony_ci if (!info->screen_base) { 214562306a36Sopenharmony_ci ret = -EIO; 214662306a36Sopenharmony_ci goto err_release_legacy; 214762306a36Sopenharmony_ci } 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci info->fix.smem_start = board_addr; 215062306a36Sopenharmony_ci info->screen_size = board_size; 215162306a36Sopenharmony_ci cinfo->unmap = cirrusfb_pci_unmap; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci dev_info(info->device, 215462306a36Sopenharmony_ci "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n", 215562306a36Sopenharmony_ci info->screen_size >> 10, board_addr); 215662306a36Sopenharmony_ci pci_set_drvdata(pdev, info); 215762306a36Sopenharmony_ci 215862306a36Sopenharmony_ci ret = cirrusfb_register(info); 215962306a36Sopenharmony_ci if (!ret) 216062306a36Sopenharmony_ci return 0; 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_ci iounmap(info->screen_base); 216362306a36Sopenharmony_cierr_release_legacy: 216462306a36Sopenharmony_ci if (release_io_ports) 216562306a36Sopenharmony_ci release_region(0x3C0, 32); 216662306a36Sopenharmony_ci#if 0 216762306a36Sopenharmony_ci release_mem_region(0xA0000, 65535); 216862306a36Sopenharmony_cierr_release_regions: 216962306a36Sopenharmony_ci#endif 217062306a36Sopenharmony_ci pci_release_regions(pdev); 217162306a36Sopenharmony_cierr_release_fb: 217262306a36Sopenharmony_ci if (cinfo->laguna_mmio != NULL) 217362306a36Sopenharmony_ci iounmap(cinfo->laguna_mmio); 217462306a36Sopenharmony_ci framebuffer_release(info); 217562306a36Sopenharmony_cierr_out: 217662306a36Sopenharmony_ci return ret; 217762306a36Sopenharmony_ci} 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_cistatic void cirrusfb_pci_unregister(struct pci_dev *pdev) 218062306a36Sopenharmony_ci{ 218162306a36Sopenharmony_ci struct fb_info *info = pci_get_drvdata(pdev); 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci cirrusfb_cleanup(info); 218462306a36Sopenharmony_ci} 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_cistatic struct pci_driver cirrusfb_pci_driver = { 218762306a36Sopenharmony_ci .name = "cirrusfb", 218862306a36Sopenharmony_ci .id_table = cirrusfb_pci_table, 218962306a36Sopenharmony_ci .probe = cirrusfb_pci_register, 219062306a36Sopenharmony_ci .remove = cirrusfb_pci_unregister, 219162306a36Sopenharmony_ci}; 219262306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 219562306a36Sopenharmony_cistatic int cirrusfb_zorro_register(struct zorro_dev *z, 219662306a36Sopenharmony_ci const struct zorro_device_id *ent) 219762306a36Sopenharmony_ci{ 219862306a36Sopenharmony_ci struct fb_info *info; 219962306a36Sopenharmony_ci int error; 220062306a36Sopenharmony_ci const struct zorrocl *zcl; 220162306a36Sopenharmony_ci enum cirrus_board btype; 220262306a36Sopenharmony_ci unsigned long regbase, ramsize, rambase; 220362306a36Sopenharmony_ci struct cirrusfb_info *cinfo; 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 220662306a36Sopenharmony_ci if (!info) 220762306a36Sopenharmony_ci return -ENOMEM; 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci zcl = (const struct zorrocl *)ent->driver_data; 221062306a36Sopenharmony_ci btype = zcl->type; 221162306a36Sopenharmony_ci regbase = zorro_resource_start(z) + zcl->regoffset; 221262306a36Sopenharmony_ci ramsize = zcl->ramsize; 221362306a36Sopenharmony_ci if (ramsize) { 221462306a36Sopenharmony_ci rambase = zorro_resource_start(z) + zcl->ramoffset; 221562306a36Sopenharmony_ci if (zorro_resource_len(z) == 64 * MB_) { 221662306a36Sopenharmony_ci /* Quirk for 64 MiB Picasso IV */ 221762306a36Sopenharmony_ci rambase += zcl->ramoffset; 221862306a36Sopenharmony_ci } 221962306a36Sopenharmony_ci } else { 222062306a36Sopenharmony_ci struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL); 222162306a36Sopenharmony_ci if (!ram || !zorro_resource_len(ram)) { 222262306a36Sopenharmony_ci dev_err(info->device, "No video RAM found\n"); 222362306a36Sopenharmony_ci error = -ENODEV; 222462306a36Sopenharmony_ci goto err_release_fb; 222562306a36Sopenharmony_ci } 222662306a36Sopenharmony_ci rambase = zorro_resource_start(ram); 222762306a36Sopenharmony_ci ramsize = zorro_resource_len(ram); 222862306a36Sopenharmony_ci if (zcl->ramid2 && 222962306a36Sopenharmony_ci (ram = zorro_find_device(zcl->ramid2, NULL))) { 223062306a36Sopenharmony_ci if (zorro_resource_start(ram) != rambase + ramsize) { 223162306a36Sopenharmony_ci dev_warn(info->device, 223262306a36Sopenharmony_ci "Skipping non-contiguous RAM at %pR\n", 223362306a36Sopenharmony_ci &ram->resource); 223462306a36Sopenharmony_ci } else { 223562306a36Sopenharmony_ci ramsize += zorro_resource_len(ram); 223662306a36Sopenharmony_ci } 223762306a36Sopenharmony_ci } 223862306a36Sopenharmony_ci } 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_ci dev_info(info->device, 224162306a36Sopenharmony_ci "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n", 224262306a36Sopenharmony_ci cirrusfb_board_info[btype].name, regbase, ramsize / MB_, 224362306a36Sopenharmony_ci rambase); 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci if (!zorro_request_device(z, "cirrusfb")) { 224662306a36Sopenharmony_ci dev_err(info->device, "Cannot reserve %pR\n", &z->resource); 224762306a36Sopenharmony_ci error = -EBUSY; 224862306a36Sopenharmony_ci goto err_release_fb; 224962306a36Sopenharmony_ci } 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci cinfo = info->par; 225262306a36Sopenharmony_ci cinfo->btype = btype; 225362306a36Sopenharmony_ci 225462306a36Sopenharmony_ci info->fix.mmio_start = regbase; 225562306a36Sopenharmony_ci cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) 225662306a36Sopenharmony_ci : ZTWO_VADDR(regbase); 225762306a36Sopenharmony_ci if (!cinfo->regbase) { 225862306a36Sopenharmony_ci dev_err(info->device, "Cannot map registers\n"); 225962306a36Sopenharmony_ci error = -EIO; 226062306a36Sopenharmony_ci goto err_release_dev; 226162306a36Sopenharmony_ci } 226262306a36Sopenharmony_ci 226362306a36Sopenharmony_ci info->fix.smem_start = rambase; 226462306a36Sopenharmony_ci info->screen_size = ramsize; 226562306a36Sopenharmony_ci info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) 226662306a36Sopenharmony_ci : ZTWO_VADDR(rambase); 226762306a36Sopenharmony_ci if (!info->screen_base) { 226862306a36Sopenharmony_ci dev_err(info->device, "Cannot map video RAM\n"); 226962306a36Sopenharmony_ci error = -EIO; 227062306a36Sopenharmony_ci goto err_unmap_reg; 227162306a36Sopenharmony_ci } 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci cinfo->unmap = cirrusfb_zorro_unmap; 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ci dev_info(info->device, 227662306a36Sopenharmony_ci "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n", 227762306a36Sopenharmony_ci ramsize / MB_, rambase); 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci /* MCLK select etc. */ 228062306a36Sopenharmony_ci if (cirrusfb_board_info[btype].init_sr1f) 228162306a36Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1F, 228262306a36Sopenharmony_ci cirrusfb_board_info[btype].sr1f); 228362306a36Sopenharmony_ci 228462306a36Sopenharmony_ci error = cirrusfb_register(info); 228562306a36Sopenharmony_ci if (error) { 228662306a36Sopenharmony_ci dev_err(info->device, "Failed to register device, error %d\n", 228762306a36Sopenharmony_ci error); 228862306a36Sopenharmony_ci goto err_unmap_ram; 228962306a36Sopenharmony_ci } 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci zorro_set_drvdata(z, info); 229262306a36Sopenharmony_ci return 0; 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_cierr_unmap_ram: 229562306a36Sopenharmony_ci if (rambase > 16 * MB_) 229662306a36Sopenharmony_ci iounmap(info->screen_base); 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_cierr_unmap_reg: 229962306a36Sopenharmony_ci if (regbase > 16 * MB_) 230062306a36Sopenharmony_ci iounmap(cinfo->regbase); 230162306a36Sopenharmony_cierr_release_dev: 230262306a36Sopenharmony_ci zorro_release_device(z); 230362306a36Sopenharmony_cierr_release_fb: 230462306a36Sopenharmony_ci framebuffer_release(info); 230562306a36Sopenharmony_ci return error; 230662306a36Sopenharmony_ci} 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_cistatic void cirrusfb_zorro_unregister(struct zorro_dev *z) 230962306a36Sopenharmony_ci{ 231062306a36Sopenharmony_ci struct fb_info *info = zorro_get_drvdata(z); 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci cirrusfb_cleanup(info); 231362306a36Sopenharmony_ci zorro_set_drvdata(z, NULL); 231462306a36Sopenharmony_ci} 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_cistatic struct zorro_driver cirrusfb_zorro_driver = { 231762306a36Sopenharmony_ci .name = "cirrusfb", 231862306a36Sopenharmony_ci .id_table = cirrusfb_zorro_table, 231962306a36Sopenharmony_ci .probe = cirrusfb_zorro_register, 232062306a36Sopenharmony_ci .remove = cirrusfb_zorro_unregister, 232162306a36Sopenharmony_ci}; 232262306a36Sopenharmony_ci#endif /* CONFIG_ZORRO */ 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci#ifndef MODULE 232562306a36Sopenharmony_cistatic int __init cirrusfb_setup(char *options) 232662306a36Sopenharmony_ci{ 232762306a36Sopenharmony_ci char *this_opt; 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci if (!options || !*options) 233062306a36Sopenharmony_ci return 0; 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci while ((this_opt = strsep(&options, ",")) != NULL) { 233362306a36Sopenharmony_ci if (!*this_opt) 233462306a36Sopenharmony_ci continue; 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci if (!strcmp(this_opt, "noaccel")) 233762306a36Sopenharmony_ci noaccel = 1; 233862306a36Sopenharmony_ci else if (!strncmp(this_opt, "mode:", 5)) 233962306a36Sopenharmony_ci mode_option = this_opt + 5; 234062306a36Sopenharmony_ci else 234162306a36Sopenharmony_ci mode_option = this_opt; 234262306a36Sopenharmony_ci } 234362306a36Sopenharmony_ci return 0; 234462306a36Sopenharmony_ci} 234562306a36Sopenharmony_ci#endif 234662306a36Sopenharmony_ci 234762306a36Sopenharmony_ci /* 234862306a36Sopenharmony_ci * Modularization 234962306a36Sopenharmony_ci */ 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_ciMODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); 235262306a36Sopenharmony_ciMODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); 235362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_cistatic int __init cirrusfb_init(void) 235662306a36Sopenharmony_ci{ 235762306a36Sopenharmony_ci int error = 0; 235862306a36Sopenharmony_ci 235962306a36Sopenharmony_ci#ifndef MODULE 236062306a36Sopenharmony_ci char *option = NULL; 236162306a36Sopenharmony_ci#endif 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci if (fb_modesetting_disabled("cirrusfb")) 236462306a36Sopenharmony_ci return -ENODEV; 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci#ifndef MODULE 236762306a36Sopenharmony_ci if (fb_get_options("cirrusfb", &option)) 236862306a36Sopenharmony_ci return -ENODEV; 236962306a36Sopenharmony_ci cirrusfb_setup(option); 237062306a36Sopenharmony_ci#endif 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 237362306a36Sopenharmony_ci error |= zorro_register_driver(&cirrusfb_zorro_driver); 237462306a36Sopenharmony_ci#endif 237562306a36Sopenharmony_ci#ifdef CONFIG_PCI 237662306a36Sopenharmony_ci error |= pci_register_driver(&cirrusfb_pci_driver); 237762306a36Sopenharmony_ci#endif 237862306a36Sopenharmony_ci return error; 237962306a36Sopenharmony_ci} 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_cistatic void __exit cirrusfb_exit(void) 238262306a36Sopenharmony_ci{ 238362306a36Sopenharmony_ci#ifdef CONFIG_PCI 238462306a36Sopenharmony_ci pci_unregister_driver(&cirrusfb_pci_driver); 238562306a36Sopenharmony_ci#endif 238662306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 238762306a36Sopenharmony_ci zorro_unregister_driver(&cirrusfb_zorro_driver); 238862306a36Sopenharmony_ci#endif 238962306a36Sopenharmony_ci} 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_cimodule_init(cirrusfb_init); 239262306a36Sopenharmony_ci 239362306a36Sopenharmony_cimodule_param(mode_option, charp, 0); 239462306a36Sopenharmony_ciMODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); 239562306a36Sopenharmony_cimodule_param(noaccel, bool, 0); 239662306a36Sopenharmony_ciMODULE_PARM_DESC(noaccel, "Disable acceleration"); 239762306a36Sopenharmony_ci 239862306a36Sopenharmony_ci#ifdef MODULE 239962306a36Sopenharmony_cimodule_exit(cirrusfb_exit); 240062306a36Sopenharmony_ci#endif 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci/**********************************************************************/ 240362306a36Sopenharmony_ci/* about the following functions - I have used the same names for the */ 240462306a36Sopenharmony_ci/* functions as Markus Wild did in his Retina driver for NetBSD as */ 240562306a36Sopenharmony_ci/* they just made sense for this purpose. Apart from that, I wrote */ 240662306a36Sopenharmony_ci/* these functions myself. */ 240762306a36Sopenharmony_ci/**********************************************************************/ 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci/*** WGen() - write into one of the external/general registers ***/ 241062306a36Sopenharmony_cistatic void WGen(const struct cirrusfb_info *cinfo, 241162306a36Sopenharmony_ci int regnum, unsigned char val) 241262306a36Sopenharmony_ci{ 241362306a36Sopenharmony_ci unsigned long regofs = 0; 241462306a36Sopenharmony_ci 241562306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 241662306a36Sopenharmony_ci /* Picasso II specific hack */ 241762306a36Sopenharmony_ci/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || 241862306a36Sopenharmony_ci regnum == CL_VSSM2) */ 241962306a36Sopenharmony_ci if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 242062306a36Sopenharmony_ci regofs = 0xfff; 242162306a36Sopenharmony_ci } 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci vga_w(cinfo->regbase, regofs + regnum, val); 242462306a36Sopenharmony_ci} 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci/*** RGen() - read out one of the external/general registers ***/ 242762306a36Sopenharmony_cistatic unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum) 242862306a36Sopenharmony_ci{ 242962306a36Sopenharmony_ci unsigned long regofs = 0; 243062306a36Sopenharmony_ci 243162306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 243262306a36Sopenharmony_ci /* Picasso II specific hack */ 243362306a36Sopenharmony_ci/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || 243462306a36Sopenharmony_ci regnum == CL_VSSM2) */ 243562306a36Sopenharmony_ci if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 243662306a36Sopenharmony_ci regofs = 0xfff; 243762306a36Sopenharmony_ci } 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_ci return vga_r(cinfo->regbase, regofs + regnum); 244062306a36Sopenharmony_ci} 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ 244362306a36Sopenharmony_cistatic void AttrOn(const struct cirrusfb_info *cinfo) 244462306a36Sopenharmony_ci{ 244562306a36Sopenharmony_ci assert(cinfo != NULL); 244662306a36Sopenharmony_ci 244762306a36Sopenharmony_ci if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { 244862306a36Sopenharmony_ci /* if we're just in "write value" mode, write back the */ 244962306a36Sopenharmony_ci /* same value as before to not modify anything */ 245062306a36Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 245162306a36Sopenharmony_ci vga_r(cinfo->regbase, VGA_ATT_R)); 245262306a36Sopenharmony_ci } 245362306a36Sopenharmony_ci /* turn on video bit */ 245462306a36Sopenharmony_ci/* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */ 245562306a36Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 0x33); 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci /* dummy write on Reg0 to be on "write index" mode next time */ 245862306a36Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); 245962306a36Sopenharmony_ci} 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci/*** WHDR() - write into the Hidden DAC register ***/ 246262306a36Sopenharmony_ci/* as the HDR is the only extension register that requires special treatment 246362306a36Sopenharmony_ci * (the other extension registers are accessible just like the "ordinary" 246462306a36Sopenharmony_ci * registers of their functional group) here is a specialized routine for 246562306a36Sopenharmony_ci * accessing the HDR 246662306a36Sopenharmony_ci */ 246762306a36Sopenharmony_cistatic void WHDR(const struct cirrusfb_info *cinfo, unsigned char val) 246862306a36Sopenharmony_ci{ 246962306a36Sopenharmony_ci if (is_laguna(cinfo)) 247062306a36Sopenharmony_ci return; 247162306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 247262306a36Sopenharmony_ci /* Klaus' hint for correct access to HDR on some boards */ 247362306a36Sopenharmony_ci /* first write 0 to pixel mask (3c6) */ 247462306a36Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0x00); 247562306a36Sopenharmony_ci udelay(200); 247662306a36Sopenharmony_ci /* next read dummy from pixel address (3c8) */ 247762306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_IW); 247862306a36Sopenharmony_ci udelay(200); 247962306a36Sopenharmony_ci } 248062306a36Sopenharmony_ci /* now do the usual stuff to access the HDR */ 248162306a36Sopenharmony_ci 248262306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_MSK); 248362306a36Sopenharmony_ci udelay(200); 248462306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_MSK); 248562306a36Sopenharmony_ci udelay(200); 248662306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_MSK); 248762306a36Sopenharmony_ci udelay(200); 248862306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_MSK); 248962306a36Sopenharmony_ci udelay(200); 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, val); 249262306a36Sopenharmony_ci udelay(200); 249362306a36Sopenharmony_ci 249462306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 249562306a36Sopenharmony_ci /* now first reset HDR access counter */ 249662306a36Sopenharmony_ci RGen(cinfo, VGA_PEL_IW); 249762306a36Sopenharmony_ci udelay(200); 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci /* and at the end, restore the mask value */ 250062306a36Sopenharmony_ci /* ## is this mask always 0xff? */ 250162306a36Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0xff); 250262306a36Sopenharmony_ci udelay(200); 250362306a36Sopenharmony_ci } 250462306a36Sopenharmony_ci} 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci/*** WSFR() - write to the "special function register" (SFR) ***/ 250762306a36Sopenharmony_cistatic void WSFR(struct cirrusfb_info *cinfo, unsigned char val) 250862306a36Sopenharmony_ci{ 250962306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 251062306a36Sopenharmony_ci assert(cinfo->regbase != NULL); 251162306a36Sopenharmony_ci cinfo->SFR = val; 251262306a36Sopenharmony_ci z_writeb(val, cinfo->regbase + 0x8000); 251362306a36Sopenharmony_ci#endif 251462306a36Sopenharmony_ci} 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci/* The Picasso has a second register for switching the monitor bit */ 251762306a36Sopenharmony_cistatic void WSFR2(struct cirrusfb_info *cinfo, unsigned char val) 251862306a36Sopenharmony_ci{ 251962306a36Sopenharmony_ci#ifdef CONFIG_ZORRO 252062306a36Sopenharmony_ci /* writing an arbitrary value to this one causes the monitor switcher */ 252162306a36Sopenharmony_ci /* to flip to Amiga display */ 252262306a36Sopenharmony_ci assert(cinfo->regbase != NULL); 252362306a36Sopenharmony_ci cinfo->SFR = val; 252462306a36Sopenharmony_ci z_writeb(val, cinfo->regbase + 0x9000); 252562306a36Sopenharmony_ci#endif 252662306a36Sopenharmony_ci} 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci/*** WClut - set CLUT entry (range: 0..63) ***/ 252962306a36Sopenharmony_cistatic void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red, 253062306a36Sopenharmony_ci unsigned char green, unsigned char blue) 253162306a36Sopenharmony_ci{ 253262306a36Sopenharmony_ci unsigned int data = VGA_PEL_D; 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci /* address write mode register is not translated.. */ 253562306a36Sopenharmony_ci vga_w(cinfo->regbase, VGA_PEL_IW, regnum); 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 253862306a36Sopenharmony_ci cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 || 253962306a36Sopenharmony_ci cinfo->btype == BT_SD64 || is_laguna(cinfo)) { 254062306a36Sopenharmony_ci /* but DAC data register IS, at least for Picasso II */ 254162306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) 254262306a36Sopenharmony_ci data += 0xfff; 254362306a36Sopenharmony_ci vga_w(cinfo->regbase, data, red); 254462306a36Sopenharmony_ci vga_w(cinfo->regbase, data, green); 254562306a36Sopenharmony_ci vga_w(cinfo->regbase, data, blue); 254662306a36Sopenharmony_ci } else { 254762306a36Sopenharmony_ci vga_w(cinfo->regbase, data, blue); 254862306a36Sopenharmony_ci vga_w(cinfo->regbase, data, green); 254962306a36Sopenharmony_ci vga_w(cinfo->regbase, data, red); 255062306a36Sopenharmony_ci } 255162306a36Sopenharmony_ci} 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci#if 0 255462306a36Sopenharmony_ci/*** RClut - read CLUT entry (range 0..63) ***/ 255562306a36Sopenharmony_cistatic void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red, 255662306a36Sopenharmony_ci unsigned char *green, unsigned char *blue) 255762306a36Sopenharmony_ci{ 255862306a36Sopenharmony_ci unsigned int data = VGA_PEL_D; 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci vga_w(cinfo->regbase, VGA_PEL_IR, regnum); 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 256362306a36Sopenharmony_ci cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) { 256462306a36Sopenharmony_ci if (cinfo->btype == BT_PICASSO) 256562306a36Sopenharmony_ci data += 0xfff; 256662306a36Sopenharmony_ci *red = vga_r(cinfo->regbase, data); 256762306a36Sopenharmony_ci *green = vga_r(cinfo->regbase, data); 256862306a36Sopenharmony_ci *blue = vga_r(cinfo->regbase, data); 256962306a36Sopenharmony_ci } else { 257062306a36Sopenharmony_ci *blue = vga_r(cinfo->regbase, data); 257162306a36Sopenharmony_ci *green = vga_r(cinfo->regbase, data); 257262306a36Sopenharmony_ci *red = vga_r(cinfo->regbase, data); 257362306a36Sopenharmony_ci } 257462306a36Sopenharmony_ci} 257562306a36Sopenharmony_ci#endif 257662306a36Sopenharmony_ci 257762306a36Sopenharmony_ci/******************************************************************* 257862306a36Sopenharmony_ci cirrusfb_WaitBLT() 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_ci Wait for the BitBLT engine to complete a possible earlier job 258162306a36Sopenharmony_ci*********************************************************************/ 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci/* FIXME: use interrupts instead */ 258462306a36Sopenharmony_cistatic void cirrusfb_WaitBLT(u8 __iomem *regbase) 258562306a36Sopenharmony_ci{ 258662306a36Sopenharmony_ci while (vga_rgfx(regbase, CL_GR31) & 0x08) 258762306a36Sopenharmony_ci cpu_relax(); 258862306a36Sopenharmony_ci} 258962306a36Sopenharmony_ci 259062306a36Sopenharmony_ci/******************************************************************* 259162306a36Sopenharmony_ci cirrusfb_BitBLT() 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci perform accelerated "scrolling" 259462306a36Sopenharmony_ci********************************************************************/ 259562306a36Sopenharmony_ci 259662306a36Sopenharmony_cistatic void cirrusfb_set_blitter(u8 __iomem *regbase, 259762306a36Sopenharmony_ci u_short nwidth, u_short nheight, 259862306a36Sopenharmony_ci u_long nsrc, u_long ndest, 259962306a36Sopenharmony_ci u_short bltmode, u_short line_length) 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_ci{ 260262306a36Sopenharmony_ci /* pitch: set to line_length */ 260362306a36Sopenharmony_ci /* dest pitch low */ 260462306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR24, line_length & 0xff); 260562306a36Sopenharmony_ci /* dest pitch hi */ 260662306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR25, line_length >> 8); 260762306a36Sopenharmony_ci /* source pitch low */ 260862306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR26, line_length & 0xff); 260962306a36Sopenharmony_ci /* source pitch hi */ 261062306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR27, line_length >> 8); 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci /* BLT width: actual number of pixels - 1 */ 261362306a36Sopenharmony_ci /* BLT width low */ 261462306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR20, nwidth & 0xff); 261562306a36Sopenharmony_ci /* BLT width hi */ 261662306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR21, nwidth >> 8); 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci /* BLT height: actual number of lines -1 */ 261962306a36Sopenharmony_ci /* BLT height low */ 262062306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR22, nheight & 0xff); 262162306a36Sopenharmony_ci /* BLT width hi */ 262262306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR23, nheight >> 8); 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci /* BLT destination */ 262562306a36Sopenharmony_ci /* BLT dest low */ 262662306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff)); 262762306a36Sopenharmony_ci /* BLT dest mid */ 262862306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8)); 262962306a36Sopenharmony_ci /* BLT dest hi */ 263062306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16)); 263162306a36Sopenharmony_ci 263262306a36Sopenharmony_ci /* BLT source */ 263362306a36Sopenharmony_ci /* BLT src low */ 263462306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff)); 263562306a36Sopenharmony_ci /* BLT src mid */ 263662306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8)); 263762306a36Sopenharmony_ci /* BLT src hi */ 263862306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16)); 263962306a36Sopenharmony_ci 264062306a36Sopenharmony_ci /* BLT mode */ 264162306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */ 264262306a36Sopenharmony_ci 264362306a36Sopenharmony_ci /* BLT ROP: SrcCopy */ 264462306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ 264562306a36Sopenharmony_ci 264662306a36Sopenharmony_ci /* and finally: GO! */ 264762306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ 264862306a36Sopenharmony_ci} 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci/******************************************************************* 265162306a36Sopenharmony_ci cirrusfb_BitBLT() 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci perform accelerated "scrolling" 265462306a36Sopenharmony_ci********************************************************************/ 265562306a36Sopenharmony_ci 265662306a36Sopenharmony_cistatic void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, 265762306a36Sopenharmony_ci u_short curx, u_short cury, 265862306a36Sopenharmony_ci u_short destx, u_short desty, 265962306a36Sopenharmony_ci u_short width, u_short height, 266062306a36Sopenharmony_ci u_short line_length) 266162306a36Sopenharmony_ci{ 266262306a36Sopenharmony_ci u_short nwidth = width - 1; 266362306a36Sopenharmony_ci u_short nheight = height - 1; 266462306a36Sopenharmony_ci u_long nsrc, ndest; 266562306a36Sopenharmony_ci u_char bltmode; 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci bltmode = 0x00; 266862306a36Sopenharmony_ci /* if source adr < dest addr, do the Blt backwards */ 266962306a36Sopenharmony_ci if (cury <= desty) { 267062306a36Sopenharmony_ci if (cury == desty) { 267162306a36Sopenharmony_ci /* if src and dest are on the same line, check x */ 267262306a36Sopenharmony_ci if (curx < destx) 267362306a36Sopenharmony_ci bltmode |= 0x01; 267462306a36Sopenharmony_ci } else 267562306a36Sopenharmony_ci bltmode |= 0x01; 267662306a36Sopenharmony_ci } 267762306a36Sopenharmony_ci /* standard case: forward blitting */ 267862306a36Sopenharmony_ci nsrc = (cury * line_length) + curx; 267962306a36Sopenharmony_ci ndest = (desty * line_length) + destx; 268062306a36Sopenharmony_ci if (bltmode) { 268162306a36Sopenharmony_ci /* this means start addresses are at the end, 268262306a36Sopenharmony_ci * counting backwards 268362306a36Sopenharmony_ci */ 268462306a36Sopenharmony_ci nsrc += nheight * line_length + nwidth; 268562306a36Sopenharmony_ci ndest += nheight * line_length + nwidth; 268662306a36Sopenharmony_ci } 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci cirrusfb_WaitBLT(regbase); 268962306a36Sopenharmony_ci 269062306a36Sopenharmony_ci cirrusfb_set_blitter(regbase, nwidth, nheight, 269162306a36Sopenharmony_ci nsrc, ndest, bltmode, line_length); 269262306a36Sopenharmony_ci} 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci/******************************************************************* 269562306a36Sopenharmony_ci cirrusfb_RectFill() 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci perform accelerated rectangle fill 269862306a36Sopenharmony_ci********************************************************************/ 269962306a36Sopenharmony_ci 270062306a36Sopenharmony_cistatic void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 270162306a36Sopenharmony_ci u_short x, u_short y, u_short width, u_short height, 270262306a36Sopenharmony_ci u32 fg_color, u32 bg_color, u_short line_length, 270362306a36Sopenharmony_ci u_char blitmode) 270462306a36Sopenharmony_ci{ 270562306a36Sopenharmony_ci u_long ndest = (y * line_length) + x; 270662306a36Sopenharmony_ci u_char op; 270762306a36Sopenharmony_ci 270862306a36Sopenharmony_ci cirrusfb_WaitBLT(regbase); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci /* This is a ColorExpand Blt, using the */ 271162306a36Sopenharmony_ci /* same color for foreground and background */ 271262306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color); 271362306a36Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color); 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci op = 0x80; 271662306a36Sopenharmony_ci if (bits_per_pixel >= 16) { 271762306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR10, bg_color >> 8); 271862306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR11, fg_color >> 8); 271962306a36Sopenharmony_ci op = 0x90; 272062306a36Sopenharmony_ci } 272162306a36Sopenharmony_ci if (bits_per_pixel >= 24) { 272262306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR12, bg_color >> 16); 272362306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR13, fg_color >> 16); 272462306a36Sopenharmony_ci op = 0xa0; 272562306a36Sopenharmony_ci } 272662306a36Sopenharmony_ci if (bits_per_pixel == 32) { 272762306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR14, bg_color >> 24); 272862306a36Sopenharmony_ci vga_wgfx(regbase, CL_GR15, fg_color >> 24); 272962306a36Sopenharmony_ci op = 0xb0; 273062306a36Sopenharmony_ci } 273162306a36Sopenharmony_ci cirrusfb_set_blitter(regbase, width - 1, height - 1, 273262306a36Sopenharmony_ci 0, ndest, op | blitmode, line_length); 273362306a36Sopenharmony_ci} 273462306a36Sopenharmony_ci 273562306a36Sopenharmony_ci/************************************************************************** 273662306a36Sopenharmony_ci * bestclock() - determine closest possible clock lower(?) than the 273762306a36Sopenharmony_ci * desired pixel clock 273862306a36Sopenharmony_ci **************************************************************************/ 273962306a36Sopenharmony_cistatic void bestclock(long freq, int *nom, int *den, int *div) 274062306a36Sopenharmony_ci{ 274162306a36Sopenharmony_ci int n, d; 274262306a36Sopenharmony_ci long h, diff; 274362306a36Sopenharmony_ci 274462306a36Sopenharmony_ci assert(nom != NULL); 274562306a36Sopenharmony_ci assert(den != NULL); 274662306a36Sopenharmony_ci assert(div != NULL); 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci *nom = 0; 274962306a36Sopenharmony_ci *den = 0; 275062306a36Sopenharmony_ci *div = 0; 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci if (freq < 8000) 275362306a36Sopenharmony_ci freq = 8000; 275462306a36Sopenharmony_ci 275562306a36Sopenharmony_ci diff = freq; 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci for (n = 32; n < 128; n++) { 275862306a36Sopenharmony_ci int s = 0; 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci d = (14318 * n) / freq; 276162306a36Sopenharmony_ci if ((d >= 7) && (d <= 63)) { 276262306a36Sopenharmony_ci int temp = d; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci if (temp > 31) { 276562306a36Sopenharmony_ci s = 1; 276662306a36Sopenharmony_ci temp >>= 1; 276762306a36Sopenharmony_ci } 276862306a36Sopenharmony_ci h = ((14318 * n) / temp) >> s; 276962306a36Sopenharmony_ci h = h > freq ? h - freq : freq - h; 277062306a36Sopenharmony_ci if (h < diff) { 277162306a36Sopenharmony_ci diff = h; 277262306a36Sopenharmony_ci *nom = n; 277362306a36Sopenharmony_ci *den = temp; 277462306a36Sopenharmony_ci *div = s; 277562306a36Sopenharmony_ci } 277662306a36Sopenharmony_ci } 277762306a36Sopenharmony_ci d++; 277862306a36Sopenharmony_ci if ((d >= 7) && (d <= 63)) { 277962306a36Sopenharmony_ci if (d > 31) { 278062306a36Sopenharmony_ci s = 1; 278162306a36Sopenharmony_ci d >>= 1; 278262306a36Sopenharmony_ci } 278362306a36Sopenharmony_ci h = ((14318 * n) / d) >> s; 278462306a36Sopenharmony_ci h = h > freq ? h - freq : freq - h; 278562306a36Sopenharmony_ci if (h < diff) { 278662306a36Sopenharmony_ci diff = h; 278762306a36Sopenharmony_ci *nom = n; 278862306a36Sopenharmony_ci *den = d; 278962306a36Sopenharmony_ci *div = s; 279062306a36Sopenharmony_ci } 279162306a36Sopenharmony_ci } 279262306a36Sopenharmony_ci } 279362306a36Sopenharmony_ci} 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci/* ------------------------------------------------------------------------- 279662306a36Sopenharmony_ci * 279762306a36Sopenharmony_ci * debugging functions 279862306a36Sopenharmony_ci * 279962306a36Sopenharmony_ci * ------------------------------------------------------------------------- 280062306a36Sopenharmony_ci */ 280162306a36Sopenharmony_ci 280262306a36Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci/* 280562306a36Sopenharmony_ci * cirrusfb_dbg_print_regs 280662306a36Sopenharmony_ci * @regbase: If using newmmio, the newmmio base address, otherwise %NULL 280762306a36Sopenharmony_ci * @reg_class: type of registers to read: %CRT, or %SEQ 280862306a36Sopenharmony_ci * 280962306a36Sopenharmony_ci * DESCRIPTION: 281062306a36Sopenharmony_ci * Dumps the given list of VGA CRTC registers. If @base is %NULL, 281162306a36Sopenharmony_ci * old-style I/O ports are queried for information, otherwise MMIO is 281262306a36Sopenharmony_ci * used at the given @base address to query the information. 281362306a36Sopenharmony_ci */ 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_cistatic void cirrusfb_dbg_print_regs(struct fb_info *info, 281662306a36Sopenharmony_ci caddr_t regbase, 281762306a36Sopenharmony_ci enum cirrusfb_dbg_reg_class reg_class, ...) 281862306a36Sopenharmony_ci{ 281962306a36Sopenharmony_ci va_list list; 282062306a36Sopenharmony_ci unsigned char val = 0; 282162306a36Sopenharmony_ci unsigned reg; 282262306a36Sopenharmony_ci char *name; 282362306a36Sopenharmony_ci 282462306a36Sopenharmony_ci va_start(list, reg_class); 282562306a36Sopenharmony_ci 282662306a36Sopenharmony_ci name = va_arg(list, char *); 282762306a36Sopenharmony_ci while (name != NULL) { 282862306a36Sopenharmony_ci reg = va_arg(list, int); 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci switch (reg_class) { 283162306a36Sopenharmony_ci case CRT: 283262306a36Sopenharmony_ci val = vga_rcrt(regbase, (unsigned char) reg); 283362306a36Sopenharmony_ci break; 283462306a36Sopenharmony_ci case SEQ: 283562306a36Sopenharmony_ci val = vga_rseq(regbase, (unsigned char) reg); 283662306a36Sopenharmony_ci break; 283762306a36Sopenharmony_ci default: 283862306a36Sopenharmony_ci /* should never occur */ 283962306a36Sopenharmony_ci assert(false); 284062306a36Sopenharmony_ci break; 284162306a36Sopenharmony_ci } 284262306a36Sopenharmony_ci 284362306a36Sopenharmony_ci dev_dbg(info->device, "%8s = 0x%02X\n", name, val); 284462306a36Sopenharmony_ci 284562306a36Sopenharmony_ci name = va_arg(list, char *); 284662306a36Sopenharmony_ci } 284762306a36Sopenharmony_ci 284862306a36Sopenharmony_ci va_end(list); 284962306a36Sopenharmony_ci} 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci/* 285262306a36Sopenharmony_ci * cirrusfb_dbg_reg_dump 285362306a36Sopenharmony_ci * @base: If using newmmio, the newmmio base address, otherwise %NULL 285462306a36Sopenharmony_ci * 285562306a36Sopenharmony_ci * DESCRIPTION: 285662306a36Sopenharmony_ci * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL, 285762306a36Sopenharmony_ci * old-style I/O ports are queried for information, otherwise MMIO is 285862306a36Sopenharmony_ci * used at the given @base address to query the information. 285962306a36Sopenharmony_ci */ 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_cistatic void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase) 286262306a36Sopenharmony_ci{ 286362306a36Sopenharmony_ci dev_dbg(info->device, "VGA CRTC register dump:\n"); 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_ci cirrusfb_dbg_print_regs(info, regbase, CRT, 286662306a36Sopenharmony_ci "CR00", 0x00, 286762306a36Sopenharmony_ci "CR01", 0x01, 286862306a36Sopenharmony_ci "CR02", 0x02, 286962306a36Sopenharmony_ci "CR03", 0x03, 287062306a36Sopenharmony_ci "CR04", 0x04, 287162306a36Sopenharmony_ci "CR05", 0x05, 287262306a36Sopenharmony_ci "CR06", 0x06, 287362306a36Sopenharmony_ci "CR07", 0x07, 287462306a36Sopenharmony_ci "CR08", 0x08, 287562306a36Sopenharmony_ci "CR09", 0x09, 287662306a36Sopenharmony_ci "CR0A", 0x0A, 287762306a36Sopenharmony_ci "CR0B", 0x0B, 287862306a36Sopenharmony_ci "CR0C", 0x0C, 287962306a36Sopenharmony_ci "CR0D", 0x0D, 288062306a36Sopenharmony_ci "CR0E", 0x0E, 288162306a36Sopenharmony_ci "CR0F", 0x0F, 288262306a36Sopenharmony_ci "CR10", 0x10, 288362306a36Sopenharmony_ci "CR11", 0x11, 288462306a36Sopenharmony_ci "CR12", 0x12, 288562306a36Sopenharmony_ci "CR13", 0x13, 288662306a36Sopenharmony_ci "CR14", 0x14, 288762306a36Sopenharmony_ci "CR15", 0x15, 288862306a36Sopenharmony_ci "CR16", 0x16, 288962306a36Sopenharmony_ci "CR17", 0x17, 289062306a36Sopenharmony_ci "CR18", 0x18, 289162306a36Sopenharmony_ci "CR22", 0x22, 289262306a36Sopenharmony_ci "CR24", 0x24, 289362306a36Sopenharmony_ci "CR26", 0x26, 289462306a36Sopenharmony_ci "CR2D", 0x2D, 289562306a36Sopenharmony_ci "CR2E", 0x2E, 289662306a36Sopenharmony_ci "CR2F", 0x2F, 289762306a36Sopenharmony_ci "CR30", 0x30, 289862306a36Sopenharmony_ci "CR31", 0x31, 289962306a36Sopenharmony_ci "CR32", 0x32, 290062306a36Sopenharmony_ci "CR33", 0x33, 290162306a36Sopenharmony_ci "CR34", 0x34, 290262306a36Sopenharmony_ci "CR35", 0x35, 290362306a36Sopenharmony_ci "CR36", 0x36, 290462306a36Sopenharmony_ci "CR37", 0x37, 290562306a36Sopenharmony_ci "CR38", 0x38, 290662306a36Sopenharmony_ci "CR39", 0x39, 290762306a36Sopenharmony_ci "CR3A", 0x3A, 290862306a36Sopenharmony_ci "CR3B", 0x3B, 290962306a36Sopenharmony_ci "CR3C", 0x3C, 291062306a36Sopenharmony_ci "CR3D", 0x3D, 291162306a36Sopenharmony_ci "CR3E", 0x3E, 291262306a36Sopenharmony_ci "CR3F", 0x3F, 291362306a36Sopenharmony_ci NULL); 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_ci dev_dbg(info->device, "\n"); 291662306a36Sopenharmony_ci 291762306a36Sopenharmony_ci dev_dbg(info->device, "VGA SEQ register dump:\n"); 291862306a36Sopenharmony_ci 291962306a36Sopenharmony_ci cirrusfb_dbg_print_regs(info, regbase, SEQ, 292062306a36Sopenharmony_ci "SR00", 0x00, 292162306a36Sopenharmony_ci "SR01", 0x01, 292262306a36Sopenharmony_ci "SR02", 0x02, 292362306a36Sopenharmony_ci "SR03", 0x03, 292462306a36Sopenharmony_ci "SR04", 0x04, 292562306a36Sopenharmony_ci "SR08", 0x08, 292662306a36Sopenharmony_ci "SR09", 0x09, 292762306a36Sopenharmony_ci "SR0A", 0x0A, 292862306a36Sopenharmony_ci "SR0B", 0x0B, 292962306a36Sopenharmony_ci "SR0D", 0x0D, 293062306a36Sopenharmony_ci "SR10", 0x10, 293162306a36Sopenharmony_ci "SR11", 0x11, 293262306a36Sopenharmony_ci "SR12", 0x12, 293362306a36Sopenharmony_ci "SR13", 0x13, 293462306a36Sopenharmony_ci "SR14", 0x14, 293562306a36Sopenharmony_ci "SR15", 0x15, 293662306a36Sopenharmony_ci "SR16", 0x16, 293762306a36Sopenharmony_ci "SR17", 0x17, 293862306a36Sopenharmony_ci "SR18", 0x18, 293962306a36Sopenharmony_ci "SR19", 0x19, 294062306a36Sopenharmony_ci "SR1A", 0x1A, 294162306a36Sopenharmony_ci "SR1B", 0x1B, 294262306a36Sopenharmony_ci "SR1C", 0x1C, 294362306a36Sopenharmony_ci "SR1D", 0x1D, 294462306a36Sopenharmony_ci "SR1E", 0x1E, 294562306a36Sopenharmony_ci "SR1F", 0x1F, 294662306a36Sopenharmony_ci NULL); 294762306a36Sopenharmony_ci 294862306a36Sopenharmony_ci dev_dbg(info->device, "\n"); 294962306a36Sopenharmony_ci} 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 295262306a36Sopenharmony_ci 2953