^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Contributors (thanks, all!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * David Eger:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Overhaul for Linux 2.6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Jeff Rugen:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Major contributions; Motorola PowerStack (PPC and PCI) support,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Geert Uytterhoeven:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * Excellent code review.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * Lars Hecking:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Amiga updates and testing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * Original cirrusfb author: Frank Neumann
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Based on retz3fb.c and cirrusfb.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Copyright (C) 1997 Jes Sorensen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * Copyright (C) 1996 Frank Neumann
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ***************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Format this code with GNU indent '-kr -i8 -pcs' options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/zorro.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #ifdef CONFIG_AMIGA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <asm/amigahw.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <video/cirrus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /*****************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * debugging and utility macros
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* disable runtime assertions? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* #define CIRRUSFB_NDEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* debugging assertions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #ifndef CIRRUSFB_NDEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define assert(expr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!(expr)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) printk("Assertion failed! %s,%s,%s,line=%d\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #expr, __FILE__, __func__, __LINE__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define assert(expr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define MB_ (1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /*****************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * chipset information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* board types */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) enum cirrus_board {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) BT_NONE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) BT_SD64, /* GD5434 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) BT_PICCOLO, /* GD5426 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) BT_PICASSO, /* GD5426 or GD5428 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) BT_SPECTRUM, /* GD5426 or GD5428 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) BT_PICASSO4, /* GD5446 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) BT_ALPINE, /* GD543x/4x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) BT_GD5480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) BT_LAGUNA, /* GD5462/64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) BT_LAGUNAB, /* GD5465 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * per-board-type information, used for enumerating and abstracting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * chip-specific information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * NOTE: MUST be in the same order as enum cirrus_board in order to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * use direct indexing on this array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * NOTE: '__initdata' cannot be used as some of this info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * is required at runtime. Maybe separate into an init-only and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * a run-time table?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct cirrusfb_board_info_rec {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) char *name; /* ASCII name of chipset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) long maxclock[5]; /* maximum video clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) bool init_sr07 : 1; /* init SR07 during init_vgachip() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) bool init_sr1f : 1; /* write SR1F during init_vgachip() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* construct bit 19 of screen start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) bool scrn_start_bit19 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* initial SR07 value, then for each mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) unsigned char sr07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) unsigned char sr07_1bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) unsigned char sr07_1bpp_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) unsigned char sr07_8bpp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned char sr07_8bpp_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned char sr1f; /* SR1F VGA initial register value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } cirrusfb_board_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) [BT_SD64] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .name = "CL SD64",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /* guess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* the SD64/P4 have a higher max. videoclock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 135100, 135100, 85500, 85500, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .sr07 = 0xF0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .sr07_1bpp = 0xF0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .sr07_1bpp_mux = 0xF6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .sr07_8bpp = 0xF1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .sr07_8bpp_mux = 0xF7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .sr1f = 0x1E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [BT_PICCOLO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .name = "CL Piccolo",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* guess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 90000, 90000, 90000, 90000, 90000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .scrn_start_bit19 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .sr07 = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .sr07_1bpp = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .sr07_8bpp = 0x81,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .sr1f = 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) [BT_PICASSO] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .name = "CL Picasso",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* guess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 90000, 90000, 90000, 90000, 90000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .scrn_start_bit19 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .sr07 = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .sr07_1bpp = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .sr07_8bpp = 0x21,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .sr1f = 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) [BT_SPECTRUM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .name = "CL Spectrum",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* guess */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 90000, 90000, 90000, 90000, 90000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .scrn_start_bit19 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) .sr07 = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) .sr07_1bpp = 0x80,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) .sr07_8bpp = 0x81,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) .sr1f = 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) [BT_PICASSO4] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .name = "CL Picasso4",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 135100, 135100, 85500, 85500, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .init_sr1f = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .sr07 = 0xA0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .sr07_1bpp = 0xA0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .sr07_1bpp_mux = 0xA6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .sr07_8bpp = 0xA1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .sr07_8bpp_mux = 0xA7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .sr1f = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) [BT_ALPINE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .name = "CL Alpine",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /* for the GD5430. GD5446 can do more... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 85500, 85500, 50000, 28500, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .sr07 = 0xA0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .sr07_1bpp = 0xA0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .sr07_1bpp_mux = 0xA6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) .sr07_8bpp = 0xA1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .sr07_8bpp_mux = 0xA7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .sr1f = 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) [BT_GD5480] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .name = "CL GD5480",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 135100, 200000, 200000, 135100, 135100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .init_sr07 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .init_sr1f = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .sr07 = 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .sr07_1bpp = 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .sr07_8bpp = 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .sr1f = 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) [BT_LAGUNA] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .name = "CL Laguna",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* taken from X11 code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 170000, 170000, 170000, 170000, 135100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .init_sr07 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .init_sr1f = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) [BT_LAGUNAB] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .name = "CL Laguna AGP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .maxclock = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* taken from X11 code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 170000, 250000, 170000, 170000, 135100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) .init_sr07 = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .init_sr1f = false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) .scrn_start_bit19 = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) #define CHIP(id, btype) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static struct pci_device_id cirrusfb_pci_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #undef CHIP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct zorrocl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) enum cirrus_board type; /* Board type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) u32 regoffset; /* Offset of registers in first Zorro device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) u32 ramsize; /* Size of video RAM in first Zorro device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /* If zero, use autoprobe on RAM device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u32 ramoffset; /* Offset of video RAM in first Zorro device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) zorro_id ramid; /* Zorro ID of RAM device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) zorro_id ramid2; /* Zorro ID of optional second RAM device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static const struct zorrocl zcl_sd64 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .type = BT_SD64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static const struct zorrocl zcl_piccolo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .type = BT_PICCOLO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) static const struct zorrocl zcl_picasso = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .type = BT_PICASSO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) static const struct zorrocl zcl_spectrum = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .type = BT_SPECTRUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static const struct zorrocl zcl_picasso4_z3 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .type = BT_PICASSO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .regoffset = 0x00600000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .ramsize = 4 * MB_,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static const struct zorrocl zcl_picasso4_z2 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .type = BT_PICASSO4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) .regoffset = 0x10000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static const struct zorro_device_id cirrusfb_zorro_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .id = ZORRO_PROD_HELFRICH_SD64_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) .driver_data = (unsigned long)&zcl_sd64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) .driver_data = (unsigned long)&zcl_piccolo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .driver_data = (unsigned long)&zcl_picasso,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .driver_data = (unsigned long)&zcl_spectrum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .driver_data = (unsigned long)&zcl_picasso4_z3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .driver_data = (unsigned long)&zcl_picasso4_z2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) { 0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) #endif /* CONFIG_ZORRO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) #ifdef CIRRUSFB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) enum cirrusfb_dbg_reg_class {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) CRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) SEQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) #endif /* CIRRUSFB_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* info about board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct cirrusfb_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u8 __iomem *regbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) u8 __iomem *laguna_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) enum cirrus_board btype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) unsigned char SFR; /* Shadow of special function register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) int multiplexing;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int doubleVCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int blank_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) u32 pseudo_palette[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) void (*unmap)(struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static bool noaccel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static char *mode_option = "640x480@60";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /**** BEGIN PROTOTYPES ******************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /*--- Interface used by the world ------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /*--- Internal routines ----------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static void init_vgachip(struct fb_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) static void switch_monitor(struct cirrusfb_info *cinfo, int on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static void WGen(const struct cirrusfb_info *cinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int regnum, unsigned char val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) static void AttrOn(const struct cirrusfb_info *cinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static void WSFR(struct cirrusfb_info *cinfo, unsigned char val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) unsigned char red, unsigned char green, unsigned char blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) unsigned char *red, unsigned char *green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) unsigned char *blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void cirrusfb_WaitBLT(u8 __iomem *regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) u_short curx, u_short cury,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) u_short destx, u_short desty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) u_short width, u_short height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) u_short line_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u_short x, u_short y,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u_short width, u_short height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u32 fg_color, u32 bg_color,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) u_short line_length, u_char blitmode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static void bestclock(long freq, int *nom, int *den, int *div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #ifdef CIRRUSFB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static void cirrusfb_dbg_print_regs(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) caddr_t regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) enum cirrusfb_dbg_reg_class reg_class, ...);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #endif /* CIRRUSFB_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*** END PROTOTYPES ********************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) /*****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /*** BEGIN Interface Used by the World ***************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static inline int is_laguna(const struct cirrusfb_info *cinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int opencount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /*--- Open /dev/fbx ---------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) static int cirrusfb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (opencount++ == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) switch_monitor(info->par, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /*--- Close /dev/fbx --------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) static int cirrusfb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (--opencount == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) switch_monitor(info->par, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /**** END Interface used by the World *************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /**** BEGIN Hardware specific Routines **************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /* Check if the MCLK is not a better clock source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) static int cirrusfb_check_mclk(struct fb_info *info, long freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* Read MCLK value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) mclk = (14318 * mclk) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* Determine if we should use MCLK instead of VCLK, and if so, what we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * should divide it by to get VCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (abs(freq - mclk) < 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) dev_dbg(info->device, "Using VCLK = MCLK\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) } else if (abs(freq - (mclk / 2)) < 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dev_dbg(info->device, "Using VCLK = MCLK/2\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) static int cirrusfb_check_pixclock(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) long freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) long maxclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) unsigned maxclockidx = var->bits_per_pixel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* convert from ps to kHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) freq = PICOS2KHZ(var->pixclock ? : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) cinfo->multiplexing = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) /* If the frequency is greater than we can support, we might be able
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) * to use multiplexing for the video mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (freq > maxclock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) var->pixclock = KHZ2PICOS(maxclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) while ((freq = PICOS2KHZ(var->pixclock)) > maxclock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) var->pixclock++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * Additional constraint: 8bpp uses DAC clock doubling to allow maximum
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * pixel clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (var->bits_per_pixel == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (freq > 85500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) cinfo->multiplexing = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (freq > 135100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) cinfo->multiplexing = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* If we have a 1MB 5434, we need to put ourselves in a mode where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * the VCLK is double the pixel clock. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cinfo->doubleVCLK = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) var->bits_per_pixel == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) cinfo->doubleVCLK = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static int cirrusfb_check_var(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) int yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /* memory size in pixels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) var->red.length = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) var->green = var->red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) var->blue = var->red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) var->green = var->red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) var->blue = var->red;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) var->green.length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) dev_dbg(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) "Unsupported bpp size: %d\n", var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (var->xres_virtual < var->xres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /* use highest possible virtual resolution */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (var->yres_virtual == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) var->yres_virtual = pixels / var->xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) dev_info(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) "virtual resolution set to maximum of %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) var->xres_virtual, var->yres_virtual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (var->yres_virtual < var->yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) var->yres_virtual = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (var->xres_virtual * var->yres_virtual > pixels) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) dev_err(info->device, "mode %dx%dx%d rejected... "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) "virtual resolution too high to fit into video memory!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) var->xres_virtual, var->yres_virtual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* truncate xoffset and yoffset to maximum if too high */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (var->xoffset > var->xres_virtual - var->xres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) var->xoffset = var->xres_virtual - var->xres - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (var->yoffset > var->yres_virtual - var->yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) var->yoffset = var->yres_virtual - var->yres - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) var->red.msb_right =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) var->green.msb_right =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) var->blue.msb_right =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) var->transp.offset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) var->transp.length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) var->transp.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) yres = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (var->vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) yres *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) else if (var->vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) yres = (yres + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (yres >= 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) dev_err(info->device, "ERROR: VerticalTotal >= 1280; "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) "special treatment required! (TODO)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (cirrusfb_check_pixclock(var, info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!is_laguna(cinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) var->accel_flags = FB_ACCELF_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) unsigned char old1f, old1e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) assert(cinfo != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_dbg(info->device, "Set %s as pixclock source.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) (div == 2) ? "MCLK/2" : "MCLK");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) old1f |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (div == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) old1e |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) vga_wseq(cinfo->regbase, CL_SEQR1E, old1e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) vga_wseq(cinfo->regbase, CL_SEQR1F, old1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /*************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) cirrusfb_set_par_foo()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) actually writes the values for a new video mode into the hardware,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static int cirrusfb_set_par_foo(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct fb_var_screeninfo *var = &info->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) u8 __iomem *regbase = cinfo->regbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) unsigned char tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) int pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) const struct cirrusfb_board_info_rec *bi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) int hdispend, hsyncstart, hsyncend, htotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) int yres, vdispend, vsyncstart, vsyncend, vtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) long freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) int nom, den, div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) unsigned int control = 0, format = 0, threshold = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev_dbg(info->device, "Requested mode: %dx%dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) var->xres, var->yres, var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) info->fix.line_length = var->xres_virtual / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) info->fix.visual = FB_VISUAL_MONO10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) info->fix.line_length = var->xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) info->fix.line_length = var->xres_virtual *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) var->bits_per_pixel >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) init_vgachip(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) bi = &cirrusfb_board_info[cinfo->btype];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) hsyncstart = var->xres + var->right_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) hsyncend = hsyncstart + var->hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) htotal = (hsyncend + var->left_margin) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) hdispend = var->xres / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) hsyncstart = hsyncstart / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) hsyncend = hsyncend / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) vdispend = var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) vsyncstart = vdispend + var->lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) vsyncend = vsyncstart + var->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) vtotal = vsyncend + var->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (var->vmode & FB_VMODE_DOUBLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) vdispend *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) vsyncstart *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) vsyncend *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) vtotal *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) } else if (var->vmode & FB_VMODE_INTERLACED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) vdispend = (vdispend + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) vsyncstart = (vsyncstart + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) vsyncend = (vsyncend + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) vtotal = (vtotal + 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) yres = vdispend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (yres >= 1024) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) vtotal /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) vsyncstart /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) vsyncend /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) vdispend /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) vdispend -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) vsyncstart -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) vsyncend -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) vtotal -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (cinfo->multiplexing) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) htotal /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) hsyncstart /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) hsyncend /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) hdispend /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) htotal -= 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) hdispend -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) hsyncstart += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) hsyncend += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /* unlock register VGA_CRTC_H_TOTAL..CRT7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* if debugging is enabled, all parameters get output before writing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) dev_dbg(info->device, "CRT0: %d\n", htotal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) dev_dbg(info->device, "CRT1: %d\n", hdispend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) dev_dbg(info->device, "CRT2: %d\n", var->xres / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) /* + 128: Compatible read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) vga_wcrt(regbase, VGA_CRTC_H_BLANK_END,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 128 + ((htotal + 5) % 32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) dev_dbg(info->device, "CRT4: %d\n", hsyncstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) tmp = hsyncend % 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if ((htotal + 5) & 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) tmp += 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) dev_dbg(info->device, "CRT5: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) tmp = 16; /* LineCompare bit #9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (vtotal & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) tmp |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (vdispend & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) tmp |= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (vsyncstart & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) tmp |= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if ((vdispend + 1) & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) tmp |= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (vtotal & 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) tmp |= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (vdispend & 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) tmp |= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (vsyncstart & 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) tmp |= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) dev_dbg(info->device, "CRT7: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) tmp = 0x40; /* LineCompare bit #8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if ((vdispend + 1) & 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) tmp |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (var->vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) tmp |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) dev_dbg(info->device, "CRT9: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) dev_dbg(info->device, "CRT18: 0xff\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (var->vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) tmp |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if ((htotal + 5) & 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) tmp |= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) if ((htotal + 5) & 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) tmp |= 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (vtotal & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) tmp |= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (vtotal & 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) tmp |= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) dev_dbg(info->device, "CRT1a: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) vga_wcrt(regbase, CL_CRT1A, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) freq = PICOS2KHZ(var->pixclock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (var->bits_per_pixel == 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) freq *= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (cinfo->multiplexing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) freq /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (cinfo->doubleVCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) freq *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) bestclock(freq, &nom, &den, &div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) freq, nom, den, div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* set VCLK0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* hardware RefClock: 14.31818 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* formula: VClk = (OSC * N) / (D * (1+P)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) cinfo->btype == BT_SD64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) /* if freq is close to mclk or mclk/2 select mclk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * as clock source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) int divMCLK = cirrusfb_check_mclk(info, freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (divMCLK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) nom = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) cirrusfb_set_mclk_as_source(info, divMCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) if (is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) unsigned short tile_control;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (cinfo->btype == BT_LAGUNAB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) tile_control &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) control = fb_readw(cinfo->laguna_mmio + 0x402);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) threshold = fb_readw(cinfo->laguna_mmio + 0xea);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) control &= ~0x6800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) format = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) threshold &= 0xffc0 & 0x3fbf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (nom) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) tmp = den << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (div != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) tmp |= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) if ((cinfo->btype == BT_SD64) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) (cinfo->btype == BT_ALPINE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) (cinfo->btype == BT_GD5480))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) tmp |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* Laguna chipset has reversed clock registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) vga_wseq(regbase, CL_SEQRE, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) vga_wseq(regbase, CL_SEQR1E, nom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) vga_wseq(regbase, CL_SEQRE, nom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) vga_wseq(regbase, CL_SEQR1E, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) if (yres >= 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* 1280x1024 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * address wrap, no compat. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) /* don't know if it would hurt to also program this if no interlaced */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* mode is used, but I feel better this way.. :-) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (var->vmode & FB_VMODE_INTERLACED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) /* adjust horizontal/vertical sync type (low/high), use VCLK3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) /* enable display memory & CRTC I/O address for color mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) tmp = 0x03 | 0xc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (var->sync & FB_SYNC_HOR_HIGH_ACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) tmp |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if (var->sync & FB_SYNC_VERT_HIGH_ACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) tmp |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) WGen(cinfo, VGA_MIS_W, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /* text cursor on and start line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) /* text cursor end line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /******************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) * 1 bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* programming for different color depths */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (var->bits_per_pixel == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) dev_dbg(info->device, "preparing for 1 bit deep display\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* SR07 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) cinfo->multiplexing ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) bi->sr07_1bpp_mux : bi->sr07_1bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) vga_rseq(regbase, CL_SEQR7) & ~0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) dev_warn(info->device, "unknown Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /* Extended Sequencer Mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* evtl d0 bei 1 bit? avoid FIFO underruns..? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /* ## vorher d0 avoid FIFO underruns..? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) vga_wseq(regbase, CL_SEQRF, 0xd0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) dev_warn(info->device, "unknown Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) /* pixel mask: pass-through for first plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) WGen(cinfo, VGA_PEL_MSK, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (cinfo->multiplexing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* hidden dac reg: 1280x1024 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) WHDR(cinfo, 0x4a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /* hidden dac: nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) WHDR(cinfo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /* memory mode: odd/even, ext. memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) /* plane mask: only write to first plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) /******************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * 8 bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) else if (var->bits_per_pixel == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) dev_dbg(info->device, "preparing for 8 bit deep display\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) cinfo->multiplexing ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) bi->sr07_8bpp_mux : bi->sr07_8bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) vga_rseq(regbase, CL_SEQR7) | 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) threshold |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) dev_warn(info->device, "unknown Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) /* Fast Page-Mode writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /* ### INCOMPLETE!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) vga_wseq(regbase, CL_SEQRF, 0xb8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /* do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) dev_warn(info->device, "unknown board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) /* mode register: 256 color mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) vga_wgfx(regbase, VGA_GFX_MODE, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (cinfo->multiplexing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) /* hidden dac reg: 1280x1024 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) WHDR(cinfo, 0x4a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) /* hidden dac: nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) WHDR(cinfo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /******************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * 16 bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) else if (var->bits_per_pixel == 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) dev_dbg(info->device, "preparing for 16 bit deep display\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) vga_wseq(regbase, CL_SEQR7, 0x87);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) /* Fast Page-Mode writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) vga_wseq(regbase, CL_SEQR7, 0x27);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* Fast Page-Mode writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* Extended Sequencer Mode: 256c col. mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) cinfo->doubleVCLK ? 0xa3 : 0xa7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) vga_wseq(regbase, CL_SEQR7, 0x17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) /* We already set SRF and SR1F */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) vga_rseq(regbase, CL_SEQR7) & ~0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) control |= 0x2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) format |= 0x1400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) threshold |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) dev_warn(info->device, "unknown Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /* mode register: 256 color mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) vga_wgfx(regbase, VGA_GFX_MODE, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) #elif defined(CONFIG_ZORRO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) /******************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) * 24 bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) else if (var->bits_per_pixel == 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) dev_dbg(info->device, "preparing for 24 bit deep display\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) vga_wseq(regbase, CL_SEQR7, 0x85);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /* Fast Page-Mode writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) vga_wseq(regbase, CL_SEQR7, 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) /* Fast Page-Mode writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) vga_wseq(regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* Extended Sequencer Mode: 256c col. mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) vga_wseq(regbase, CL_SEQR7, 0xa5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) vga_wseq(regbase, CL_SEQR7, 0x15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* We already set SRF and SR1F */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) vga_wseq(regbase, CL_SEQR7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) vga_rseq(regbase, CL_SEQR7) & ~0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) control |= 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) format |= 0x2400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) threshold |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) dev_warn(info->device, "unknown Board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /* mode register: 256 color mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) vga_wgfx(regbase, VGA_GFX_MODE, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /* hidden dac reg: 8-8-8 mode (24 or 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) WHDR(cinfo, 0xc5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /******************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * unknown/unsupported bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) dev_err(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) "What's this? requested color depth == %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) pitch = info->fix.line_length >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) tmp = 0x22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if (pitch & 0x100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) tmp |= 0x10; /* offset overflow bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* screen start addr #16-18, fastpagemode cycles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) vga_wcrt(regbase, CL_CRT1B, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) /* screen start address bit 19 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) tmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if ((htotal + 5) & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) tmp |= 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) if (hdispend & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) tmp |= 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (hsyncstart & 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) tmp |= 48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) if (vtotal & 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) tmp |= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (vdispend & 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) tmp |= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (vsyncstart & 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) tmp |= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) vga_wcrt(regbase, CL_CRT1E, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) dev_dbg(info->device, "CRT1e: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) /* pixel panning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) vga_wattr(regbase, CL_AR33, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /* [ EGS: SetOffset(); ] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) AttrOn(cinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if (is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) /* no tiles */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) fb_writew(format, cinfo->laguna_mmio + 0xc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) fb_writew(threshold, cinfo->laguna_mmio + 0xea);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) /* finally, turn on everything - turn off "FullBandwidth" bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /* also, set "DotClock%2" bit where requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) tmp = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (var->vmode & FB_VMODE_CLOCK_HALVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) tmp |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) dev_dbg(info->device, "CL_SEQR1: %d\n", tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) #ifdef CIRRUSFB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) cirrusfb_dbg_reg_dump(info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) /* for some reason incomprehensible to me, cirrusfb requires that you write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * the registers twice for the settings to take..grr. -dte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) static int cirrusfb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) cirrusfb_set_par_foo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) return cirrusfb_set_par_foo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) unsigned blue, unsigned transp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) if (regno > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) red >>= (16 - info->var.red.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) green >>= (16 - info->var.green.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) blue >>= (16 - info->var.blue.length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (regno >= 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) v = (red << info->var.red.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) (green << info->var.green.offset) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) (blue << info->var.blue.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) cinfo->pseudo_palette[regno] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (info->var.bits_per_pixel == 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) /*************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) cirrusfb_pan_display()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) performs display panning - provided hardware permits this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) static int cirrusfb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) int xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) unsigned long base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) unsigned char tmp, xpix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) /* no range checks for xoffset and yoffset, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) /* as fb_pan_display has already done this */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (var->vmode & FB_VMODE_YWRAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) xoffset = var->xoffset * info->var.bits_per_pixel / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) base = var->yoffset * info->fix.line_length + xoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) if (info->var.bits_per_pixel == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) /* base is already correct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) xpix = (unsigned char) (var->xoffset % 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) base /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) xpix = (unsigned char) ((xoffset % 4) * 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (!is_laguna(cinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) cirrusfb_WaitBLT(cinfo->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) /* lower 8 + 8 bits of screen start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) /* 0xf2 is %11110010, exclude tmp bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /* construct bits 16, 17 and 18 of screen start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (base & 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) tmp |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) if (base & 0x20000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) tmp |= 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (base & 0x40000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) tmp |= 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) vga_wcrt(cinfo->regbase, CL_CRT1B, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* construct bit 19 of screen start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) tmp = vga_rcrt(cinfo->regbase, CL_CRT1D);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (is_laguna(cinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) tmp = (tmp & ~0x18) | ((base >> 16) & 0x18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) tmp = (tmp & ~0x80) | ((base >> 12) & 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) vga_wcrt(cinfo->regbase, CL_CRT1D, tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) /* write pixel panning value to AR33; this does not quite work in 8bpp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * ### Piccolo..? Will this work?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (info->var.bits_per_pixel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) vga_wattr(cinfo->regbase, CL_AR33, xpix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) static int cirrusfb_blank(int blank_mode, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * Blank the screen if blank_mode != 0, else unblank. If blank == NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * then the caller blanks by setting the CLUT (Color Look Up Table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * failed due to e.g. a video mode which doesn't support it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * Implements VESA suspend and powerdown modes on hardware that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) * supports disabling hsync/vsync:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * blank_mode == 2: suspend vsync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * blank_mode == 3: suspend hsync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * blank_mode == 4: powerdown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) int current_mode = cinfo->blank_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) if (info->state != FBINFO_STATE_RUNNING ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) current_mode == blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) dev_dbg(info->device, "EXIT, returning 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) /* Undo current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (current_mode == FB_BLANK_NORMAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) current_mode == FB_BLANK_UNBLANK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* clear "FullBandwidth" bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) /* set "FullBandwidth" bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) val = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) switch (blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) case FB_BLANK_UNBLANK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) case FB_BLANK_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) val = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case FB_BLANK_VSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) val = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) case FB_BLANK_HSYNC_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) val = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) case FB_BLANK_POWERDOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) val = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) dev_dbg(info->device, "EXIT, returning 1\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) vga_wgfx(cinfo->regbase, CL_GRE, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) cinfo->blank_mode = blank_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) dev_dbg(info->device, "EXIT, returning 0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) /* Let fbcon do a soft blank for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /**** END Hardware specific Routines **************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) /**** BEGIN Internal Routines ***********************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) static void init_vgachip(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) const struct cirrusfb_board_info_rec *bi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) assert(cinfo != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) bi = &cirrusfb_board_info[cinfo->btype];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) /* reset board globally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) WSFR(cinfo, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) WSFR(cinfo, 0x51);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) case BT_PICASSO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) WSFR2(cinfo, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) WSFR(cinfo, 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) WSFR(cinfo, 0x4f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) udelay(500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) case BT_PICASSO4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) /* disable flickerfixer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) vga_wcrt(cinfo->regbase, CL_CRT51, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) mdelay(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) /* from Klaus' NetBSD driver: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) vga_wgfx(cinfo->regbase, CL_GR2F, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) /* put blitter into 542x compat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) vga_wgfx(cinfo->regbase, CL_GR33, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) /* Nothing to do to reset the board. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) dev_err(info->device, "Warning: Unknown board type\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) /* make sure RAM size set by this point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) assert(info->screen_size > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) /* the P4 is not fully initialized here; I rely on it having been */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) /* inited under AmigaOS already, which seems to work just fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) /* (Klaus advised to do it this way) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) if (cinfo->btype != BT_PICASSO4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) WGen(cinfo, CL_POS102, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) if (cinfo->btype != BT_SD64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) WGen(cinfo, CL_VSSM2, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) /* reset sequencer logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) /* FullBandwidth (video off) and 8/9 dot clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /* "magic cookie" - doesn't make any sense to me.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /* unlock all extension registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) case BT_GD5480:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) vga_wseq(cinfo->regbase, CL_SEQRF, 0x98);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) case BT_ALPINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) case BT_LAGUNA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) case BT_LAGUNAB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /* plane mask: nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) /* character map select: doesn't even matter in gx mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) /* memory mode: chain4, ext. memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) /* controller-internal base address of video memory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (bi->init_sr07)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) /* EEPROM control: shouldn't be necessary to write to this at all.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) /* graphics cursor X position (incomplete; position gives rem. 3 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) vga_wseq(cinfo->regbase, CL_SEQR10, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) /* graphics cursor Y position (..."... ) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) vga_wseq(cinfo->regbase, CL_SEQR11, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) /* graphics cursor attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) vga_wseq(cinfo->regbase, CL_SEQR12, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) /* graphics cursor pattern address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) /* writing these on a P4 might give problems.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) if (cinfo->btype != BT_PICASSO4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) /* configuration readback and ext. color */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) vga_wseq(cinfo->regbase, CL_SEQR17, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) /* signature generator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) /* Screen A preset row scan: none */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) /* Text cursor start: disable text cursor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) /* Text cursor end: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) /* text cursor location high: 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) /* text cursor location low: 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) /* Underline Row scanline: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) /* ### add 0x40 for text modes with > 30 MHz pixclock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) /* ext. display controls: ext.adr. wrap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) /* Set/Reset registers: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) /* Set/Reset enable: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /* Color Compare: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) /* Data Rotate: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) /* Read Map Select: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) /* Miscellaneous: memory map base address, graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) /* Color Don't care: involve all planes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) /* Bit Mask: no mask at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) is_laguna(cinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) /* (5434 can't have bit 3 set for bitblt) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) vga_wgfx(cinfo->regbase, CL_GRB, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) /* Graphics controller mode extensions: finer granularity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * 8byte data latches
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) vga_wgfx(cinfo->regbase, CL_GRB, 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) /* Background color byte 1: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) /* Attribute Controller palette registers: "identity mapping" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) /* Attribute Controller mode: graphics mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) /* Overscan color reg.: reg. 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) /* Color Plane enable: Enable all 4 planes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) /* Color Select: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) /* BLT Start/status: Blitter reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) vga_wgfx(cinfo->regbase, CL_GR31, 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* - " - : "end-of-reset" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) vga_wgfx(cinfo->regbase, CL_GR31, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) /* misc... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) WHDR(cinfo, 0); /* Hidden DAC register: - */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) static void switch_monitor(struct cirrusfb_info *cinfo, int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) #ifdef CONFIG_ZORRO /* only works on Zorro boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) static int IsOn = 0; /* XXX not ok for multiple boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (cinfo->btype == BT_PICASSO4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) return; /* nothing to switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (cinfo->btype == BT_ALPINE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) return; /* nothing to switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (cinfo->btype == BT_GD5480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) return; /* nothing to switch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (cinfo->btype == BT_PICASSO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) if ((on && !IsOn) || (!on && IsOn))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) WSFR(cinfo, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) WSFR(cinfo, cinfo->SFR | 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) WSFR(cinfo, cinfo->SFR | 0x28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) WSFR(cinfo, 0x6f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) default: /* do nothing */ break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) switch (cinfo->btype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) case BT_SD64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) WSFR(cinfo, cinfo->SFR & 0xde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) case BT_PICCOLO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) WSFR(cinfo, cinfo->SFR & 0xd7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) case BT_SPECTRUM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) WSFR(cinfo, 0x4f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) default: /* do nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) #endif /* CONFIG_ZORRO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) /******************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /* Linux 2.6-style accelerated functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) /******************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) static int cirrusfb_sync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) if (!is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) static void cirrusfb_fillrect(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) const struct fb_fillrect *region)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) struct fb_fillrect modded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) int vxres, vyres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) int m = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) cinfo->pseudo_palette[region->color] : region->color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) if (info->state != FBINFO_STATE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) if (info->flags & FBINFO_HWACCEL_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) cfb_fillrect(info, region);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) vxres = info->var.xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) vyres = info->var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) memcpy(&modded, region, sizeof(struct fb_fillrect));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) if (!modded.width || !modded.height ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) modded.dx >= vxres || modded.dy >= vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) if (modded.dx + modded.width > vxres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) modded.width = vxres - modded.dx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (modded.dy + modded.height > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) modded.height = vyres - modded.dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) cirrusfb_RectFill(cinfo->regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) info->var.bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) (region->dx * m) / 8, region->dy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) (region->width * m) / 8, region->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) color, color,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) info->fix.line_length, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) static void cirrusfb_copyarea(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) struct fb_copyarea modded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) u32 vxres, vyres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) int m = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (info->state != FBINFO_STATE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) if (info->flags & FBINFO_HWACCEL_DISABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) cfb_copyarea(info, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) vxres = info->var.xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) vyres = info->var.yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) memcpy(&modded, area, sizeof(struct fb_copyarea));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) if (!modded.width || !modded.height ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) modded.sx >= vxres || modded.sy >= vyres ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) modded.dx >= vxres || modded.dy >= vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (modded.sx + modded.width > vxres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) modded.width = vxres - modded.sx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) if (modded.dx + modded.width > vxres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) modded.width = vxres - modded.dx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) if (modded.sy + modded.height > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) modded.height = vyres - modded.sy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (modded.dy + modded.height > vyres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) modded.height = vyres - modded.dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) (area->sx * m) / 8, area->sy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) (area->dx * m) / 8, area->dy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) (area->width * m) / 8, area->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) info->fix.line_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) static void cirrusfb_imageblit(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (info->state != FBINFO_STATE_RUNNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) /* Alpine/SD64 does not work at 24bpp ??? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) op == 0xc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) unsigned size = ((image->width + 7) >> 3) * image->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) int m = info->var.bits_per_pixel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) u32 fg, bg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) if (info->var.bits_per_pixel == 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) fg = image->fg_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) bg = image->bg_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) fg = ((u32 *)(info->pseudo_palette))[image->fg_color];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) bg = ((u32 *)(info->pseudo_palette))[image->bg_color];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) if (info->var.bits_per_pixel == 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) /* clear background first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) cirrusfb_RectFill(cinfo->regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) info->var.bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) (image->dx * m) / 8, image->dy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) (image->width * m) / 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) image->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) bg, bg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) info->fix.line_length, 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) cirrusfb_RectFill(cinfo->regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) info->var.bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) (image->dx * m) / 8, image->dy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) (image->width * m) / 8, image->height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) fg, bg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) info->fix.line_length, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) memcpy(info->screen_base, image->data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) static int release_io_ports;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) * based on the DRAM bandwidth bit and DRAM bank switching bit. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) * seem to have. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) static unsigned int cirrusfb_get_memsize(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) u8 __iomem *regbase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) unsigned long mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) if (is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) unsigned char SR14 = vga_rseq(regbase, CL_SEQR14);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) mem = ((SR14 & 7) + 1) << 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) unsigned char SRF = vga_rseq(regbase, CL_SEQRF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) switch ((SRF & 0x18)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) case 0x08:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) mem = 512 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) mem = 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) /* 64-bit DRAM data bus width; assume 2MB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) * Also indicates 2MB memory on the 5430.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) case 0x18:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) mem = 2048 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) dev_warn(info->device, "Unknown memory size!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) mem = 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) /* If DRAM bank switching is enabled, there must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) * twice as much memory installed. (4MB on the 5434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) mem *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) return mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) static void get_pci_addrs(const struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) unsigned long *display, unsigned long *registers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) assert(pdev != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) assert(display != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) assert(registers != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) *display = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) *registers = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) /* This is a best-guess for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) *display = pci_resource_start(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) *registers = pci_resource_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) *display = pci_resource_start(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) *registers = pci_resource_start(pdev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) assert(*display != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) static void cirrusfb_pci_unmap(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) struct pci_dev *pdev = to_pci_dev(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) if (cinfo->laguna_mmio == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) iounmap(cinfo->laguna_mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) #if 0 /* if system didn't claim this region, we would... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) release_mem_region(0xA0000, 65535);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if (release_io_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) release_region(0x3C0, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) static void cirrusfb_zorro_unmap(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) struct zorro_dev *zdev = to_zorro_dev(info->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) if (info->fix.smem_start > 16 * MB_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (info->fix.mmio_start > 16 * MB_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) iounmap(cinfo->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) zorro_release_device(zdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) #endif /* CONFIG_ZORRO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) /* function table of the above functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) static const struct fb_ops cirrusfb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) .fb_open = cirrusfb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) .fb_release = cirrusfb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) .fb_setcolreg = cirrusfb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) .fb_check_var = cirrusfb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) .fb_set_par = cirrusfb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) .fb_pan_display = cirrusfb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) .fb_blank = cirrusfb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) .fb_fillrect = cirrusfb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) .fb_copyarea = cirrusfb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) .fb_sync = cirrusfb_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) .fb_imageblit = cirrusfb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) static int cirrusfb_set_fbinfo(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) struct fb_var_screeninfo *var = &info->var;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) info->pseudo_palette = cinfo->pseudo_palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) info->flags = FBINFO_DEFAULT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) | FBINFO_HWACCEL_XPAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) | FBINFO_HWACCEL_YPAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) | FBINFO_HWACCEL_FILLRECT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) | FBINFO_HWACCEL_IMAGEBLIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) | FBINFO_HWACCEL_COPYAREA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (noaccel || is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) info->flags |= FBINFO_HWACCEL_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) info->fix.accel = FB_ACCEL_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) info->fix.accel = FB_ACCEL_CIRRUS_ALPINE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) info->fbops = &cirrusfb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (cinfo->btype == BT_GD5480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) if (var->bits_per_pixel == 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) info->screen_base += 1 * MB_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) if (var->bits_per_pixel == 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) info->screen_base += 2 * MB_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) /* Fill fix common fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) sizeof(info->fix.id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) /* monochrome: only 1 memory plane */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) /* 8 bit and above: Use whole memory area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) info->fix.smem_len = info->screen_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (var->bits_per_pixel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) info->fix.smem_len /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) info->fix.type_aux = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) info->fix.xpanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) info->fix.ypanstep = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) info->fix.ywrapstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) /* FIXME: map region at 0xB8000 if available, fill in here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) info->fix.mmio_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) static int cirrusfb_register(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) /* sanity checks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) assert(cinfo->btype != BT_NONE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) /* set all the vital stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) cirrusfb_set_fbinfo(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if (!err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) dev_dbg(info->device, "wrong initial video mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) goto err_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) info->var.activate = FB_ACTIVATE_NOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) err = cirrusfb_check_var(&info->var, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) /* should never happen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) dev_dbg(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) "choking on default var... umm, no good.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) goto err_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) dev_err(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) "could not register fb device; err = %d!\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) goto err_dealloc_cmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) err_dealloc_cmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) static void cirrusfb_cleanup(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) struct cirrusfb_info *cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) switch_monitor(cinfo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) dev_dbg(info->device, "Framebuffer unregistered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) cinfo->unmap(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) static int cirrusfb_pci_register(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) struct cirrusfb_info *cinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) unsigned long board_addr, board_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) ret = pci_enable_device(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) if (!info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) cinfo->btype = (enum cirrus_board) ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) dev_dbg(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) (unsigned long long)pdev->resource[0].start, cinfo->btype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) dev_dbg(info->device, " base address 1 is 0x%Lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) (unsigned long long)pdev->resource[1].start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) dev_dbg(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) "Attempt to get PCI info for Cirrus Graphics Card\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) /* FIXME: this forces VGA. alternatives? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) cinfo->regbase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) board_addr, info->fix.mmio_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) board_size = (cinfo->btype == BT_GD5480) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) ret = pci_request_regions(pdev, "cirrusfb");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) board_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) #if 0 /* if the system didn't claim this region, we would... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) 0xA0000L);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) goto err_release_regions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (request_region(0x3C0, 32, "cirrusfb"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) release_io_ports = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) info->screen_base = ioremap(board_addr, board_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) goto err_release_legacy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) info->fix.smem_start = board_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) info->screen_size = board_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) cinfo->unmap = cirrusfb_pci_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) dev_info(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) info->screen_size >> 10, board_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) pci_set_drvdata(pdev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) ret = cirrusfb_register(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) err_release_legacy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) if (release_io_ports)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) release_region(0x3C0, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) release_mem_region(0xA0000, 65535);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) err_release_regions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) pci_release_regions(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) err_release_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) if (cinfo->laguna_mmio != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) iounmap(cinfo->laguna_mmio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) static void cirrusfb_pci_unregister(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) struct fb_info *info = pci_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) cirrusfb_cleanup(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) static struct pci_driver cirrusfb_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) .name = "cirrusfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) .id_table = cirrusfb_pci_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) .probe = cirrusfb_pci_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) .remove = cirrusfb_pci_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) .suspend = cirrusfb_pci_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) .resume = cirrusfb_pci_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) #endif /* CONFIG_PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) static int cirrusfb_zorro_register(struct zorro_dev *z,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) const struct zorro_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) const struct zorrocl *zcl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) enum cirrus_board btype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) unsigned long regbase, ramsize, rambase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) struct cirrusfb_info *cinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) zcl = (const struct zorrocl *)ent->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) btype = zcl->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) regbase = zorro_resource_start(z) + zcl->regoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) ramsize = zcl->ramsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) if (ramsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) rambase = zorro_resource_start(z) + zcl->ramoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) if (zorro_resource_len(z) == 64 * MB_) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) /* Quirk for 64 MiB Picasso IV */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) rambase += zcl->ramoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) if (!ram || !zorro_resource_len(ram)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) dev_err(info->device, "No video RAM found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) error = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) rambase = zorro_resource_start(ram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) ramsize = zorro_resource_len(ram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) if (zcl->ramid2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) (ram = zorro_find_device(zcl->ramid2, NULL))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) if (zorro_resource_start(ram) != rambase + ramsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) dev_warn(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) "Skipping non-contiguous RAM at %pR\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) &ram->resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) ramsize += zorro_resource_len(ram);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) dev_info(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) rambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) if (!zorro_request_device(z, "cirrusfb")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) error = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) goto err_release_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) cinfo = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) cinfo->btype = btype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) info->fix.mmio_start = regbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) : ZTWO_VADDR(regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) if (!cinfo->regbase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) dev_err(info->device, "Cannot map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) goto err_release_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) info->fix.smem_start = rambase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) info->screen_size = ramsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) : ZTWO_VADDR(rambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) dev_err(info->device, "Cannot map video RAM\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) error = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) goto err_unmap_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) cinfo->unmap = cirrusfb_zorro_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) dev_info(info->device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) ramsize / MB_, rambase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) /* MCLK select etc. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) if (cirrusfb_board_info[btype].init_sr1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) vga_wseq(cinfo->regbase, CL_SEQR1F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) cirrusfb_board_info[btype].sr1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) error = cirrusfb_register(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) dev_err(info->device, "Failed to register device, error %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) goto err_unmap_ram;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) zorro_set_drvdata(z, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) err_unmap_ram:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) if (rambase > 16 * MB_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) err_unmap_reg:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) if (regbase > 16 * MB_)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) iounmap(cinfo->regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) err_release_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) zorro_release_device(z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) err_release_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) void cirrusfb_zorro_unregister(struct zorro_dev *z)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) struct fb_info *info = zorro_get_drvdata(z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) cirrusfb_cleanup(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) zorro_set_drvdata(z, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) static struct zorro_driver cirrusfb_zorro_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) .name = "cirrusfb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) .id_table = cirrusfb_zorro_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) .probe = cirrusfb_zorro_register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) .remove = cirrusfb_zorro_unregister,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323) #endif /* CONFIG_ZORRO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326) static int __init cirrusfb_setup(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) char *this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) while ((this_opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) if (!*this_opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) if (!strcmp(this_opt, "noaccel"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) noaccel = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339) else if (!strncmp(this_opt, "mode:", 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) mode_option = this_opt + 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) mode_option = this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) * Modularization
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353) MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356) static int __init cirrusfb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363) if (fb_get_options("cirrusfb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) cirrusfb_setup(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) error |= zorro_register_driver(&cirrusfb_zorro_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) error |= pci_register_driver(&cirrusfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) static void __exit cirrusfb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) #ifdef CONFIG_PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380) pci_unregister_driver(&cirrusfb_pci_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) zorro_unregister_driver(&cirrusfb_zorro_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387) module_init(cirrusfb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) module_param(mode_option, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) module_param(noaccel, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392) MODULE_PARM_DESC(noaccel, "Disable acceleration");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395) module_exit(cirrusfb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) /**********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) /* about the following functions - I have used the same names for the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400) /* functions as Markus Wild did in his Retina driver for NetBSD as */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) /* they just made sense for this purpose. Apart from that, I wrote */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) /* these functions myself. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403) /**********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) /*** WGen() - write into one of the external/general registers ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406) static void WGen(const struct cirrusfb_info *cinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) int regnum, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409) unsigned long regofs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) if (cinfo->btype == BT_PICASSO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412) /* Picasso II specific hack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) regnum == CL_VSSM2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415) if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) regofs = 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) vga_w(cinfo->regbase, regofs + regnum, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) /*** RGen() - read out one of the external/general registers ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) static unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) unsigned long regofs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) if (cinfo->btype == BT_PICASSO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) /* Picasso II specific hack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) regnum == CL_VSSM2) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) regofs = 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) return vga_r(cinfo->regbase, regofs + regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) static void AttrOn(const struct cirrusfb_info *cinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) assert(cinfo != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) /* if we're just in "write value" mode, write back the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) /* same value as before to not modify anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) vga_w(cinfo->regbase, VGA_ATT_IW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) vga_r(cinfo->regbase, VGA_ATT_R));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) /* turn on video bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450) /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) /* dummy write on Reg0 to be on "write index" mode next time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) /*** WHDR() - write into the Hidden DAC register ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) /* as the HDR is the only extension register that requires special treatment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) * (the other extension registers are accessible just like the "ordinary"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460) * registers of their functional group) here is a specialized routine for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) * accessing the HDR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465) unsigned char dummy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) if (is_laguna(cinfo))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) if (cinfo->btype == BT_PICASSO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) /* Klaus' hint for correct access to HDR on some boards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) /* first write 0 to pixel mask (3c6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472) WGen(cinfo, VGA_PEL_MSK, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474) /* next read dummy from pixel address (3c8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) dummy = RGen(cinfo, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) /* now do the usual stuff to access the HDR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480) dummy = RGen(cinfo, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) dummy = RGen(cinfo, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) dummy = RGen(cinfo, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486) dummy = RGen(cinfo, VGA_PEL_MSK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) WGen(cinfo, VGA_PEL_MSK, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) if (cinfo->btype == BT_PICASSO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493) /* now first reset HDR access counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) dummy = RGen(cinfo, VGA_PEL_IW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) /* and at the end, restore the mask value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) /* ## is this mask always 0xff? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499) WGen(cinfo, VGA_PEL_MSK, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) udelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504) /*** WSFR() - write to the "special function register" (SFR) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) static void WSFR(struct cirrusfb_info *cinfo, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) assert(cinfo->regbase != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) cinfo->SFR = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) z_writeb(val, cinfo->regbase + 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) /* The Picasso has a second register for switching the monitor bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) static void WSFR2(struct cirrusfb_info *cinfo, unsigned char val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) #ifdef CONFIG_ZORRO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518) /* writing an arbitrary value to this one causes the monitor switcher */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) /* to flip to Amiga display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) assert(cinfo->regbase != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) cinfo->SFR = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522) z_writeb(val, cinfo->regbase + 0x9000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) /*** WClut - set CLUT entry (range: 0..63) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528) unsigned char green, unsigned char blue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) unsigned int data = VGA_PEL_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) /* address write mode register is not translated.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) vga_w(cinfo->regbase, VGA_PEL_IW, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536) cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) cinfo->btype == BT_SD64 || is_laguna(cinfo)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) /* but DAC data register IS, at least for Picasso II */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) if (cinfo->btype == BT_PICASSO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) data += 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541) vga_w(cinfo->regbase, data, red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) vga_w(cinfo->regbase, data, green);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) vga_w(cinfo->regbase, data, blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) vga_w(cinfo->regbase, data, blue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) vga_w(cinfo->regbase, data, green);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547) vga_w(cinfo->regbase, data, red);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) /*** RClut - read CLUT entry (range 0..63) ***/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) unsigned char *green, unsigned char *blue)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) unsigned int data = VGA_PEL_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558) vga_w(cinfo->regbase, VGA_PEL_IR, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) if (cinfo->btype == BT_PICASSO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) data += 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) *red = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) *green = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) *blue = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568) *blue = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) *green = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) *red = vga_r(cinfo->regbase, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) /*******************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) cirrusfb_WaitBLT()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) Wait for the BitBLT engine to complete a possible earlier job
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) *********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) /* FIXME: use interrupts instead */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) static void cirrusfb_WaitBLT(u8 __iomem *regbase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) while (vga_rgfx(regbase, CL_GR31) & 0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) /*******************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) cirrusfb_BitBLT()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591) perform accelerated "scrolling"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) ********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) static void cirrusfb_set_blitter(u8 __iomem *regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595) u_short nwidth, u_short nheight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) u_long nsrc, u_long ndest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597) u_short bltmode, u_short line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600) /* pitch: set to line_length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) /* dest pitch low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) vga_wgfx(regbase, CL_GR24, line_length & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) /* dest pitch hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) vga_wgfx(regbase, CL_GR25, line_length >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) /* source pitch low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) vga_wgfx(regbase, CL_GR26, line_length & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607) /* source pitch hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) vga_wgfx(regbase, CL_GR27, line_length >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610) /* BLT width: actual number of pixels - 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) /* BLT width low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) vga_wgfx(regbase, CL_GR20, nwidth & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) /* BLT width hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) vga_wgfx(regbase, CL_GR21, nwidth >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) /* BLT height: actual number of lines -1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) /* BLT height low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618) vga_wgfx(regbase, CL_GR22, nheight & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) /* BLT width hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) vga_wgfx(regbase, CL_GR23, nheight >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) /* BLT destination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) /* BLT dest low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) /* BLT dest mid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) /* BLT dest hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) /* BLT source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) /* BLT src low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) /* BLT src mid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) /* BLT src hi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) /* BLT mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) /* BLT ROP: SrcCopy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) /* and finally: GO! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) /*******************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) cirrusfb_BitBLT()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651) perform accelerated "scrolling"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) ********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655) u_short curx, u_short cury,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) u_short destx, u_short desty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) u_short width, u_short height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) u_short line_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660) u_short nwidth = width - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) u_short nheight = height - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) u_long nsrc, ndest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663) u_char bltmode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) bltmode = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) /* if source adr < dest addr, do the Blt backwards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) if (cury <= desty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668) if (cury == desty) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) /* if src and dest are on the same line, check x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) if (curx < destx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) bltmode |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) bltmode |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675) /* standard case: forward blitting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) nsrc = (cury * line_length) + curx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) ndest = (desty * line_length) + destx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678) if (bltmode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) /* this means start addresses are at the end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) * counting backwards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) nsrc += nheight * line_length + nwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) ndest += nheight * line_length + nwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) cirrusfb_WaitBLT(regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) cirrusfb_set_blitter(regbase, nwidth, nheight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) nsrc, ndest, bltmode, line_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692) /*******************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) cirrusfb_RectFill()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) perform accelerated rectangle fill
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) ********************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698) static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) u_short x, u_short y, u_short width, u_short height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) u32 fg_color, u32 bg_color, u_short line_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) u_char blitmode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) u_long ndest = (y * line_length) + x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) u_char op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706) cirrusfb_WaitBLT(regbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) /* This is a ColorExpand Blt, using the */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) /* same color for foreground and background */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) op = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714) if (bits_per_pixel >= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) vga_wgfx(regbase, CL_GR10, bg_color >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716) vga_wgfx(regbase, CL_GR11, fg_color >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) op = 0x90;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) if (bits_per_pixel >= 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) vga_wgfx(regbase, CL_GR12, bg_color >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721) vga_wgfx(regbase, CL_GR13, fg_color >> 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) op = 0xa0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) if (bits_per_pixel == 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) vga_wgfx(regbase, CL_GR14, bg_color >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) vga_wgfx(regbase, CL_GR15, fg_color >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727) op = 0xb0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729) cirrusfb_set_blitter(regbase, width - 1, height - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) 0, ndest, op | blitmode, line_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) /**************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734) * bestclock() - determine closest possible clock lower(?) than the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) * desired pixel clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) **************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) static void bestclock(long freq, int *nom, int *den, int *div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739) int n, d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) long h, diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) assert(nom != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) assert(den != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) assert(div != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) *nom = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) *den = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) *div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) if (freq < 8000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751) freq = 8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) diff = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) for (n = 32; n < 128; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) int s = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) d = (14318 * n) / freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759) if ((d >= 7) && (d <= 63)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) int temp = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) if (temp > 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763) s = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) temp >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) h = ((14318 * n) / temp) >> s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) h = h > freq ? h - freq : freq - h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) if (h < diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) diff = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) *nom = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) *den = temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) *div = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775) d++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if ((d >= 7) && (d <= 63)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) if (d > 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) s = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779) d >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781) h = ((14318 * n) / d) >> s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) h = h > freq ? h - freq : freq - h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) if (h < diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) diff = h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) *nom = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) *den = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) *div = s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) /* -------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) * debugging functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) * -------------------------------------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) #ifdef CIRRUSFB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) * cirrusfb_dbg_print_regs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804) * @base: If using newmmio, the newmmio base address, otherwise %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) * @reg_class: type of registers to read: %CRT, or %SEQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) * DESCRIPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) * Dumps the given list of VGA CRTC registers. If @base is %NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) * old-style I/O ports are queried for information, otherwise MMIO is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) * used at the given @base address to query the information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813) static void cirrusfb_dbg_print_regs(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) caddr_t regbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) enum cirrusfb_dbg_reg_class reg_class, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) va_list list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) unsigned char val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) unsigned reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) va_start(list, reg_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) name = va_arg(list, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) while (name != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826) reg = va_arg(list, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) switch (reg_class) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829) case CRT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) val = vga_rcrt(regbase, (unsigned char) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) case SEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) val = vga_rseq(regbase, (unsigned char) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) /* should never occur */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) assert(false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) dev_dbg(info->device, "%8s = 0x%02X\n", name, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) name = va_arg(list, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) va_end(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) * cirrusfb_dbg_reg_dump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) * @base: If using newmmio, the newmmio base address, otherwise %NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) * DESCRIPTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854) * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) * old-style I/O ports are queried for information, otherwise MMIO is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) * used at the given @base address to query the information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861) dev_dbg(info->device, "VGA CRTC register dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) cirrusfb_dbg_print_regs(info, regbase, CRT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864) "CR00", 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) "CR01", 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) "CR02", 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) "CR03", 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868) "CR04", 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) "CR05", 0x05,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) "CR06", 0x06,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) "CR07", 0x07,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872) "CR08", 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) "CR09", 0x09,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) "CR0A", 0x0A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) "CR0B", 0x0B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) "CR0C", 0x0C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) "CR0D", 0x0D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) "CR0E", 0x0E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) "CR0F", 0x0F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) "CR10", 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881) "CR11", 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) "CR12", 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) "CR13", 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) "CR14", 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) "CR15", 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) "CR16", 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887) "CR17", 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) "CR18", 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) "CR22", 0x22,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) "CR24", 0x24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) "CR26", 0x26,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) "CR2D", 0x2D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) "CR2E", 0x2E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) "CR2F", 0x2F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) "CR30", 0x30,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) "CR31", 0x31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897) "CR32", 0x32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) "CR33", 0x33,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) "CR34", 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900) "CR35", 0x35,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) "CR36", 0x36,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) "CR37", 0x37,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) "CR38", 0x38,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) "CR39", 0x39,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) "CR3A", 0x3A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) "CR3B", 0x3B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) "CR3C", 0x3C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) "CR3D", 0x3D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) "CR3E", 0x3E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) "CR3F", 0x3F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) dev_dbg(info->device, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) dev_dbg(info->device, "VGA SEQ register dump:\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) cirrusfb_dbg_print_regs(info, regbase, SEQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) "SR00", 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) "SR01", 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) "SR02", 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) "SR03", 0x03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) "SR04", 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) "SR08", 0x08,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) "SR09", 0x09,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) "SR0A", 0x0A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) "SR0B", 0x0B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) "SR0D", 0x0D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) "SR10", 0x10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) "SR11", 0x11,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) "SR12", 0x12,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) "SR13", 0x13,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) "SR14", 0x14,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) "SR15", 0x15,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) "SR16", 0x16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) "SR17", 0x17,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) "SR18", 0x18,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) "SR19", 0x19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) "SR1A", 0x1A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) "SR1B", 0x1B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) "SR1C", 0x1C,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) "SR1D", 0x1D,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) "SR1E", 0x1E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943) "SR1F", 0x1F,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) dev_dbg(info->device, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) #endif /* CIRRUSFB_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950)