^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/drivers/video/neofb.c -- NeoMagic Framebuffer Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2001-2002 Denis Oliver Kropp <dok@directfb.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Card specific code is based on XFree86's neomagic driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Framebuffer framework code is based on code of cyber2000fb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This file is subject to the terms and conditions of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Public License. See the file COPYING in the main directory of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * archive for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * 0.4.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * - Cosmetic changes (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * 0.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * - Toshiba Libretto support, allow modes larger than LCD size if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * LCD is disabled, keep BIOS settings if internal/external display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * haven't been enabled explicitly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * (Thomas J. Moore <dark@mama.indstate.edu>)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * 0.3.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * - Porting over to new fbdev api. (jsimmons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * 0.3.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * - got rid of all floating point (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * 0.3.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * - added module license (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * 0.3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * - hardware accelerated clear and move for 2200 and above (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * - maximum allowed dotclock is handled now (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * 0.2.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - correct panning after X usage (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * - added module and kernel parameters (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * - no stretching if external display is enabled (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * 0.2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * - initial version (dok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * TODO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * - ioctl for internal/external switching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * - blanking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * - 32bit depth support, maybe impossible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * - disable pan-on-sync, need specs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * BUGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * - white margin on bootup like with tdfxfb (colormap problem?)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #include <linux/fb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #ifdef CONFIG_TOSHIBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #include <linux/toshiba.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <video/vga.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <video/neomagic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define NEOFB_VERSION "0.4.2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* --------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static bool internal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static bool external;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static bool libretto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static bool nostretch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static bool nopciburst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static char *mode_option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MODULE_AUTHOR("(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) MODULE_DESCRIPTION("FBDev driver for NeoMagic PCI Chips");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) module_param(internal, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) MODULE_PARM_DESC(internal, "Enable output on internal LCD Display.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) module_param(external, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_PARM_DESC(external, "Enable output on external CRT.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) module_param(libretto, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) MODULE_PARM_DESC(libretto, "Force Libretto 100/110 800x480 LCD.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) module_param(nostretch, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) MODULE_PARM_DESC(nostretch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) "Disable stretching of modes smaller than LCD.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) module_param(nopciburst, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) MODULE_PARM_DESC(nopciburst, "Disable PCI burst mode.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) module_param(mode_option, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) MODULE_PARM_DESC(mode_option, "Preferred video mode ('640x480-8@60', etc)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* --------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static biosMode bios8[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {320, 240, 0x40},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {300, 400, 0x42},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {640, 400, 0x20},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {640, 480, 0x21},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {800, 600, 0x23},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {1024, 768, 0x25},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static biosMode bios16[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {320, 200, 0x2e},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {320, 240, 0x41},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {300, 400, 0x43},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {640, 480, 0x31},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {800, 600, 0x34},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {1024, 768, 0x37},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static biosMode bios24[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {640, 480, 0x32},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {800, 600, 0x35},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {1024, 768, 0x38}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* FIXME: guessed values, wrong */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static biosMode bios32[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {640, 480, 0x33},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {800, 600, 0x36},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {1024, 768, 0x39}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static inline void write_le32(int regindex, u32 val, const struct neofb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) writel(val, par->neo2200 + par->cursorOff + regindex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int neoFindMode(int xres, int yres, int depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int xres_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int i, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) biosMode *mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) switch (depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) size = ARRAY_SIZE(bios8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) mode = bios8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) size = ARRAY_SIZE(bios16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) mode = bios16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) size = ARRAY_SIZE(bios24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) mode = bios24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) size = ARRAY_SIZE(bios32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) mode = bios32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) for (i = 0; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (xres <= mode[i].x_res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) xres_s = mode[i].x_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) for (; i < size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (mode[i].x_res != xres_s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return mode[i - 1].mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (yres <= mode[i].y_res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return mode[i].mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return mode[size - 1].mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * neoCalcVCLK --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Determine the closest clock frequency to the one requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define MAX_N 127
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) #define MAX_D 31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #define MAX_F 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static void neoCalcVCLK(const struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) struct neofb_par *par, long freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int n, d, f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) int n_best = 0, d_best = 0, f_best = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) long f_best_diff = 0x7ffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for (f = 0; f <= MAX_F; f++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) for (d = 0; d <= MAX_D; d++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) for (n = 0; n <= MAX_N; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) long f_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) long f_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) f_out = ((14318 * (n + 1)) / (d + 1)) >> f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) f_diff = abs(f_out - freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (f_diff <= f_best_diff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) f_best_diff = f_diff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) n_best = n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) d_best = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) f_best = f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (f_out > freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* NOT_DONE: We are trying the full range of the 2200 clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) We should be able to try n up to 2047 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) par->VCLK3NumeratorLow = n_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) par->VCLK3NumeratorHigh = (f_best << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) par->VCLK3NumeratorLow = n_best | (f_best << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) par->VCLK3Denominator = d_best;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #ifdef NEOFB_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) printk(KERN_DEBUG "neoVCLK: f:%ld NumLow=%d NumHi=%d Den=%d Df=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) freq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) par->VCLK3NumeratorLow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) par->VCLK3NumeratorHigh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) par->VCLK3Denominator, f_best_diff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * vgaHWInit --
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Handle the initialization, etc. of a screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * Return FALSE on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) static int vgaHWInit(const struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct neofb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int hsync_end = var->xres + var->right_margin + var->hsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) int htotal = (hsync_end + var->left_margin) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int vsync_start = var->yres + var->lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int vsync_end = vsync_start + var->vsync_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) int vtotal = vsync_end + var->upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) par->MiscOutReg = 0x23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) par->MiscOutReg |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) par->MiscOutReg |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * Time Sequencer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) par->Sequencer[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) par->Sequencer[1] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) par->Sequencer[2] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) par->Sequencer[3] = 0x00; /* Font select */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) par->Sequencer[4] = 0x0E; /* Misc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * CRTC Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) par->CRTC[0] = htotal - 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) par->CRTC[1] = (var->xres >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) par->CRTC[2] = (var->xres >> 3) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) par->CRTC[4] = ((var->xres + var->right_margin) >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) | (((hsync_end >> 3)) & 0x1F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) par->CRTC[6] = (vtotal - 2) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) | (((var->yres - 1) & 0x100) >> 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) | ((vsync_start & 0x100) >> 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) | (((var->yres - 1) & 0x100) >> 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) | 0x10 | (((vtotal - 2) & 0x200) >> 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) | (((var->yres - 1) & 0x200) >> 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) | ((vsync_start & 0x200) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) par->CRTC[8] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) par->CRTC[9] = (((var->yres - 1) & 0x200) >> 4) | 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (var->vmode & FB_VMODE_DOUBLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) par->CRTC[9] |= 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) par->CRTC[10] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) par->CRTC[11] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) par->CRTC[12] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) par->CRTC[13] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) par->CRTC[14] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) par->CRTC[15] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) par->CRTC[16] = vsync_start & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) par->CRTC[18] = (var->yres - 1) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) par->CRTC[19] = var->xres_virtual >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) par->CRTC[20] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) par->CRTC[21] = (var->yres - 1) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) par->CRTC[22] = (vtotal - 1) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) par->CRTC[23] = 0xC3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) par->CRTC[24] = 0xFF;
^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) * are these unnecessary?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN | KGA_ENABLE_ON_ZERO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * Graphics Display Controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) par->Graphics[0] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) par->Graphics[1] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) par->Graphics[2] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) par->Graphics[3] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) par->Graphics[4] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) par->Graphics[5] = 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) par->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) par->Graphics[7] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) par->Graphics[8] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) par->Attribute[0] = 0x00; /* standard colormap translation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) par->Attribute[1] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) par->Attribute[2] = 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) par->Attribute[3] = 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) par->Attribute[4] = 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) par->Attribute[5] = 0x05;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) par->Attribute[6] = 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) par->Attribute[7] = 0x07;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) par->Attribute[8] = 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) par->Attribute[9] = 0x09;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) par->Attribute[10] = 0x0A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) par->Attribute[11] = 0x0B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) par->Attribute[12] = 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) par->Attribute[13] = 0x0D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) par->Attribute[14] = 0x0E;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) par->Attribute[15] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) par->Attribute[16] = 0x41;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) par->Attribute[17] = 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) par->Attribute[18] = 0x0F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) par->Attribute[19] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) par->Attribute[20] = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void vgaHWLock(struct vgastate *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Protect CRTC[0-7] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) vga_wcrt(state->vgabase, 0x11, vga_rcrt(state->vgabase, 0x11) | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static void vgaHWUnlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Unprotect CRTC[0-7] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) vga_wcrt(NULL, 0x11, vga_rcrt(NULL, 0x11) & ~0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static void neoLock(struct vgastate *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) vga_wgfx(state->vgabase, 0x09, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) vgaHWLock(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void neoUnlock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) vgaHWUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) vga_wgfx(NULL, 0x09, 0x26);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * VGA Palette management
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) static int paletteEnabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static inline void VGAenablePalette(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) vga_r(NULL, VGA_IS1_RC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) vga_w(NULL, VGA_ATT_W, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) paletteEnabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) static inline void VGAdisablePalette(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) vga_r(NULL, VGA_IS1_RC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) vga_w(NULL, VGA_ATT_W, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) paletteEnabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static inline void VGAwATTR(u8 index, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (paletteEnabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) index &= ~0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) index |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) vga_r(NULL, VGA_IS1_RC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) vga_wattr(NULL, index, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) static void vgaHWProtect(int on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) unsigned char tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) tmp = vga_rseq(NULL, 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * Turn off screen and disable sequencer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) vga_wseq(NULL, 0x00, 0x01); /* Synchronous Reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) vga_wseq(NULL, 0x01, tmp | 0x20); /* disable the display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) VGAenablePalette();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Reenable sequencer, then turn on screen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) vga_wseq(NULL, 0x01, tmp & ~0x20); /* reenable display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) vga_wseq(NULL, 0x00, 0x03); /* clear synchronousreset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) VGAdisablePalette();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static void vgaHWRestore(const struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) const struct neofb_par *par)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) vga_w(NULL, VGA_MIS_W, par->MiscOutReg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) for (i = 1; i < 5; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) vga_wseq(NULL, i, par->Sequencer[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) vga_wcrt(NULL, 17, par->CRTC[17] & ~0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) for (i = 0; i < 25; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) vga_wcrt(NULL, i, par->CRTC[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) for (i = 0; i < 9; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) vga_wgfx(NULL, i, par->Graphics[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) VGAenablePalette();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) for (i = 0; i < 21; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) VGAwATTR(i, par->Attribute[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) VGAdisablePalette();
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) /* -------------------- Hardware specific routines ------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Hardware Acceleration for Neo2200+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static inline int neo2200_sync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) while (readl(&par->neo2200->bltStat) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static inline void neo2200_wait_fifo(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int requested_fifo_space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) // ndev->neo.waitfifo_calls++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) // ndev->neo.waitfifo_sum += requested_fifo_space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* FIXME: does not work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (neo_fifo_space < requested_fifo_space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) neo_fifo_waitcycles++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) neo_fifo_space = (neo2200->bltStat >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (neo_fifo_space >= requested_fifo_space)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) neo_fifo_cache_hits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) neo_fifo_space -= requested_fifo_space;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) neo2200_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) static inline void neo2200_accel_init(struct fb_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct fb_var_screeninfo *var)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) Neo2200 __iomem *neo2200 = par->neo2200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) u32 bltMod, pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) neo2200_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) bltMod = NEO_MODE1_DEPTH8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) pitch = var->xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) bltMod = NEO_MODE1_DEPTH16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) pitch = var->xres_virtual * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) bltMod = NEO_MODE1_DEPTH24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) pitch = var->xres_virtual * 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) writel(bltMod << 16, &neo2200->bltStat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) writel((pitch << 16) | pitch, &neo2200->pitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* --------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) neofb_open(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!par->ref_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) memset(&par->state, 0, sizeof(struct vgastate));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) save_vga(&par->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) par->ref_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) neofb_release(struct fb_info *info, int user)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (!par->ref_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (par->ref_count == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) restore_vga(&par->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) par->ref_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int memlen, vramlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int mode_ok = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) DBG("neofb_check_var");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (PICOS2KHZ(var->pixclock) > par->maxClock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* Is the mode larger than the LCD panel? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (par->internal_display &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) ((var->xres > par->NeoPanelWidth) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) (var->yres > par->NeoPanelHeight))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) var->xres, var->yres, par->NeoPanelWidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) par->NeoPanelHeight);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Is the mode one of the acceptable sizes? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (!par->internal_display)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) mode_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) switch (var->xres) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) case 1280:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (var->yres == 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) mode_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case 1024:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (var->yres == 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) mode_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) case 800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (var->yres == (par->libretto ? 480 : 600))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) mode_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) case 640:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (var->yres == 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) mode_ok = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (!mode_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) printk(KERN_INFO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) "Mode (%dx%d) won't display properly on LCD\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) var->xres, var->yres);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) var->red.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) var->green.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) var->blue.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) var->transp.msb_right = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) var->transp.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) var->transp.length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) switch (var->bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) case 8: /* PSEUDOCOLOUR, 256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) var->red.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) var->green.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case 16: /* DIRECTCOLOUR, 64k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) var->red.offset = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) var->red.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) var->green.offset = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) var->green.length = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) var->blue.length = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) case 24: /* TRUECOLOUR, 16m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) case 32: /* TRUECOLOUR, 16m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) var->transp.offset = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) var->transp.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) var->red.offset = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) var->red.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) var->green.offset = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) var->green.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) var->blue.offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) var->blue.length = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) printk(KERN_WARNING "neofb: no support for %dbpp\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) vramlen = info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (vramlen > 4 * 1024 * 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) vramlen = 4 * 1024 * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (var->xres_virtual < var->xres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) var->xres_virtual = var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (memlen > vramlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) var->yres_virtual = vramlen * 8 / (var->xres_virtual *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) var->bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) memlen = var->xres_virtual * var->bits_per_pixel *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) var->yres_virtual / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* we must round yres/xres down, we already rounded y/xres_virtual up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if it was possible. We should return -EINVAL, but I disagree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (var->yres_virtual < var->yres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) var->yres = var->yres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (var->xoffset + var->xres > var->xres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) var->xoffset = var->xres_virtual - var->xres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (var->yoffset + var->yres > var->yres_virtual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) var->yoffset = var->yres_virtual - var->yres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) var->nonstd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) var->height = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) var->width = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (var->bits_per_pixel >= 24 || !par->neo2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) var->accel_flags &= ~FB_ACCELF_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static int neofb_set_par(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) unsigned char temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) int i, clock_hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int lcd_stretch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int hoffset, voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int vsync_start, vtotal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) DBG("neofb_set_par");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) neoUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) vgaHWProtect(1); /* Blank the screen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) vsync_start = info->var.yres + info->var.lower_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) vtotal = vsync_start + info->var.vsync_len + info->var.upper_margin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * This will allocate the datastructure and initialize all of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * generic VGA registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (vgaHWInit(&info->var, par))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * The default value assigned by vgaHW.c is 0x41, but this does
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * not work for NeoMagic.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) par->Attribute[16] = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) par->CRTC[0x13] = info->var.xres_virtual >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) par->ExtCRTOffset = info->var.xres_virtual >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) par->ExtColorModeSelect = 0x11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) par->CRTC[0x13] = info->var.xres_virtual >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) par->ExtCRTOffset = info->var.xres_virtual >> 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) par->ExtColorModeSelect = 0x13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) par->CRTC[0x13] = (info->var.xres_virtual * 3) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) par->ExtCRTOffset = (info->var.xres_virtual * 3) >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) par->ExtColorModeSelect = 0x14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) case 32: /* FIXME: guessed values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) par->CRTC[0x13] = info->var.xres_virtual >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) par->ExtCRTOffset = info->var.xres_virtual >> 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) par->ExtColorModeSelect = 0x15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) par->ExtCRTDispAddr = 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* Vertical Extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) | (((info->var.yres - 1) & 0x400) >> 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) | (((vsync_start) & 0x400) >> 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) | (((vsync_start) & 0x400) >> 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) /* Fast write bursts on unless disabled. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (par->pci_burst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) par->SysIfaceCntl1 = 0x30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) par->SysIfaceCntl1 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /* Initialize: by default, we want display config register to be read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) par->PanelDispCntlRegRead = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* Enable any user specified display devices. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) par->PanelDispCntlReg1 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) if (par->internal_display)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) par->PanelDispCntlReg1 |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (par->external_display)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) par->PanelDispCntlReg1 |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* If the user did not specify any display devices, then... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (par->PanelDispCntlReg1 == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /* Default to internal (i.e., LCD) only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* If we are using a fixed mode, then tell the chip we are. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) switch (info->var.xres) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) case 1280:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) par->PanelDispCntlReg1 |= 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) case 1024:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) par->PanelDispCntlReg1 |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) case 800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) par->PanelDispCntlReg1 |= 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) case 640:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* Setup shadow register locking. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) switch (par->PanelDispCntlReg1 & 0x03) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) case 0x01: /* External CRT only mode: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) par->GeneralLockReg = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* We need to program the VCLK for external display only mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) par->ProgramVCLK = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) case 0x02: /* Internal LCD only mode: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) par->GeneralLockReg = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) /* Don't program the VCLK when using the LCD. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) par->ProgramVCLK = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) * If the screen is to be stretched, turn on stretching for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * various modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * OPTION_LCD_STRETCH means stretching should be turned off!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) par->PanelDispCntlReg2 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) par->PanelDispCntlReg3 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) && /* LCD only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) (info->var.xres != par->NeoPanelWidth)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) switch (info->var.xres) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) case 320: /* Needs testing. KEM -- 24 May 98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) case 400: /* Needs testing. KEM -- 24 May 98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) case 640:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) case 800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) case 1024:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) lcd_stretch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) par->PanelDispCntlReg2 |= 0xC6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) lcd_stretch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /* No stretching in these modes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) lcd_stretch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) * If the screen is to be centerd, turn on the centering for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) * various modes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) par->PanelVertCenterReg1 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) par->PanelVertCenterReg2 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) par->PanelVertCenterReg3 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) par->PanelVertCenterReg4 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) par->PanelVertCenterReg5 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) par->PanelHorizCenterReg1 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) par->PanelHorizCenterReg2 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) par->PanelHorizCenterReg3 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) par->PanelHorizCenterReg4 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) par->PanelHorizCenterReg5 = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (par->PanelDispCntlReg1 & 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (info->var.xres == par->NeoPanelWidth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) * No centering required when the requested display width
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) * equals the panel width.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) par->PanelDispCntlReg2 |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) par->PanelDispCntlReg3 |= 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) /* Calculate the horizontal and vertical offsets. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (!lcd_stretch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) hoffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) ((par->NeoPanelWidth -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) info->var.xres) >> 4) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) voffset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) ((par->NeoPanelHeight -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) info->var.yres) >> 1) - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) /* Stretched modes cannot be centered. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) hoffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) voffset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) switch (info->var.xres) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) case 320: /* Needs testing. KEM -- 24 May 98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) par->PanelHorizCenterReg3 = hoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) par->PanelVertCenterReg2 = voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case 400: /* Needs testing. KEM -- 24 May 98 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) par->PanelHorizCenterReg4 = hoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) par->PanelVertCenterReg1 = voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) case 640:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) par->PanelHorizCenterReg1 = hoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) par->PanelVertCenterReg3 = voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case 800:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) par->PanelHorizCenterReg2 = hoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) par->PanelVertCenterReg4 = voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) case 1024:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) par->PanelHorizCenterReg5 = hoffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) par->PanelVertCenterReg5 = voffset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) case 1280:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) /* No centering in these modes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^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) par->biosMode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) neoFindMode(info->var.xres, info->var.yres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) info->var.bits_per_pixel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * Calculate the VCLK that most closely matches the requested dot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) neoCalcVCLK(info, par, PICOS2KHZ(info->var.pixclock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* Since we program the clocks ourselves, always use VCLK3. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) par->MiscOutReg |= 0x0C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /* alread unlocked above */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) /* BOGUS vga_wgfx(NULL, 0x09, 0x26); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) /* don't know what this is, but it's 0 from bootup anyway */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) vga_wgfx(NULL, 0x15, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /* was set to 0x01 by my bios in text and vesa modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) vga_wgfx(NULL, 0x0A, par->GeneralLockReg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * The color mode needs to be set before calling vgaHWRestore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * to ensure the DAC is initialized properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * NOTE: Make sure we don't change bits make sure we don't change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * any reserved bits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) temp = vga_rgfx(NULL, 0x90);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) temp &= 0xF0; /* Save bits 7:4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) temp |= (par->ExtColorModeSelect & ~0xF0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) temp &= 0x70; /* Save bits 6:4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) temp |= (par->ExtColorModeSelect & ~0x70);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) vga_wgfx(NULL, 0x90, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * In some rare cases a lockup might occur if we don't delay
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * here. (Reported by Miles Lane)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) //mdelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * Disable horizontal and vertical graphics and text expansions so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * that vgaHWRestore works properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) temp = vga_rgfx(NULL, 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) temp &= 0x39;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) vga_wgfx(NULL, 0x25, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) * Sleep for 200ms to make sure that the two operations above have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * had time to take effect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) mdelay(200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * This function handles restoring the generic VGA registers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) vgaHWRestore(info, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* linear colormap for non palettized modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* PseudoColor, 256 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) /* TrueColor, 64k */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) for (i = 0; i < 64; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) outb(i, 0x3c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) outb(i << 1, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) outb(i, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) outb(i << 1, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) /* TrueColor, 16m */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) info->fix.visual = FB_VISUAL_TRUECOLOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) for (i = 0; i < 256; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) outb(i, 0x3c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) outb(i, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) outb(i, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) outb(i, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) vga_wgfx(NULL, 0x0E, par->ExtCRTDispAddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) vga_wgfx(NULL, 0x0F, par->ExtCRTOffset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) temp = vga_rgfx(NULL, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) temp &= 0x0F; /* Save bits 3:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) temp |= (par->SysIfaceCntl1 & ~0x0F); /* VESA Bios sets bit 1! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) vga_wgfx(NULL, 0x10, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) vga_wgfx(NULL, 0x11, par->SysIfaceCntl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) vga_wgfx(NULL, 0x15, 0 /*par->SingleAddrPage */ );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) vga_wgfx(NULL, 0x16, 0 /*par->DualAddrPage */ );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) temp = vga_rgfx(NULL, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) temp &= 0xFC; /* Save bits 7:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) temp |= (par->PanelDispCntlReg1 & ~0xFC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) temp &= 0xDC; /* Save bits 7:6,4:2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) temp |= (par->PanelDispCntlReg1 & ~0xDC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) temp &= 0x98; /* Save bits 7,4:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) temp |= (par->PanelDispCntlReg1 & ~0x98);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) vga_wgfx(NULL, 0x20, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) temp = vga_rgfx(NULL, 0x25);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) temp &= 0x38; /* Save bits 5:3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) temp |= (par->PanelDispCntlReg2 & ~0x38);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) vga_wgfx(NULL, 0x25, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) temp = vga_rgfx(NULL, 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) temp |= (par->PanelDispCntlReg3 & ~0xEF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) vga_wgfx(NULL, 0x30, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) vga_wgfx(NULL, 0x28, par->PanelVertCenterReg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) vga_wgfx(NULL, 0x29, par->PanelVertCenterReg2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) vga_wgfx(NULL, 0x2a, par->PanelVertCenterReg3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (info->fix.accel != FB_ACCEL_NEOMAGIC_NM2070) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) vga_wgfx(NULL, 0x32, par->PanelVertCenterReg4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) vga_wgfx(NULL, 0x33, par->PanelHorizCenterReg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) vga_wgfx(NULL, 0x34, par->PanelHorizCenterReg2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) vga_wgfx(NULL, 0x35, par->PanelHorizCenterReg3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) vga_wgfx(NULL, 0x36, par->PanelHorizCenterReg4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) vga_wgfx(NULL, 0x37, par->PanelVertCenterReg5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) vga_wgfx(NULL, 0x38, par->PanelHorizCenterReg5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) clock_hi = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) /* Program VCLK3 if needed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) if (par->ProgramVCLK && ((vga_rgfx(NULL, 0x9B) != par->VCLK3NumeratorLow)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) || (vga_rgfx(NULL, 0x9F) != par->VCLK3Denominator)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) || (clock_hi && ((vga_rgfx(NULL, 0x8F) & ~0x0f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) != (par->VCLK3NumeratorHigh &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) ~0x0F))))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) vga_wgfx(NULL, 0x9B, par->VCLK3NumeratorLow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (clock_hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) temp = vga_rgfx(NULL, 0x8F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) temp &= 0x0F; /* Save bits 3:0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) temp |= (par->VCLK3NumeratorHigh & ~0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) vga_wgfx(NULL, 0x8F, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) vga_wgfx(NULL, 0x9F, par->VCLK3Denominator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if (par->biosMode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) vga_wcrt(NULL, 0x23, par->biosMode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) vga_wgfx(NULL, 0x93, 0xc0); /* Gives 5x faster framebuffer writes !!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /* Program vertical extension register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (info->fix.accel == FB_ACCEL_NEOMAGIC_NM2200 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2230 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2360 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) info->fix.accel == FB_ACCEL_NEOMAGIC_NM2380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) vga_wcrt(NULL, 0x70, par->VerticalExt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) vgaHWProtect(0); /* Turn on screen */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /* Calling this also locks offset registers required in update_start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) neoLock(&par->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) info->fix.line_length =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) info->var.xres_virtual * (info->var.bits_per_pixel >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) neo2200_accel_init(info, &info->var);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) * Pan or Wrap the Display
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) static int neofb_pan_display(struct fb_var_screeninfo *var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) struct vgastate *state = &par->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) int oldExtCRTDispAddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) int Base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) DBG("neofb_update_start");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) Base = (var->yoffset * info->var.xres_virtual + var->xoffset) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) Base *= (info->var.bits_per_pixel + 7) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) neoUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) * These are the generic starting address registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) vga_wcrt(state->vgabase, 0x0C, (Base & 0x00FF00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) vga_wcrt(state->vgabase, 0x0D, (Base & 0x00FF));
^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) * Make sure we don't clobber some other bits that might already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) * be needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) oldExtCRTDispAddr = vga_rgfx(NULL, 0x0E);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) vga_wgfx(state->vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) neoLock(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) static int neofb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) u_int transp, struct fb_info *fb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) if (regno >= fb->cmap.len || regno > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) if (fb->var.bits_per_pixel <= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) outb(regno, 0x3c8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) outb(red >> 10, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) outb(green >> 10, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) outb(blue >> 10, 0x3c9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) } else if (regno < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) switch (fb->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) ((u32 *) fb->pseudo_palette)[regno] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) ((blue & 0xf800) >> 11);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) ((u32 *) fb->pseudo_palette)[regno] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ((red & 0xff00) << 8) | ((green & 0xff00)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) ((blue & 0xff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) #ifdef NO_32BIT_SUPPORT_YET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) case 32:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) ((u32 *) fb->pseudo_palette)[regno] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) ((green & 0xff00)) | ((blue & 0xff00) >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * (Un)Blank the display.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) static int neofb_blank(int blank_mode, struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) * Blank the screen if blank_mode != 0, else unblank.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * Return 0 if blanking succeeded, != 0 if un-/blanking failed due to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) * e.g. a video mode which doesn't support it. Implements VESA suspend
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) * and powerdown modes for monitors, and backlight control on LCDs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) * blank_mode == 0: unblanked (backlight on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * blank_mode == 1: blank (backlight on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * blank_mode == 2: suspend vsync (backlight off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * blank_mode == 3: suspend hsync (backlight off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * blank_mode == 4: powerdown (backlight off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * wms...Enable VESA DPMS compatible powerdown mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * run "setterm -powersave powerdown" to take advantage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
^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) * Read back the register bits related to display configuration. They might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * have been changed underneath the driver via Fn key stroke.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) neoUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) neoLock(&par->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) /* In case we blank the screen, we want to store the possibly new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) * configuration in the driver. During un-blank, we re-apply this setting,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * since the LCD bit will be cleared in order to switch off the backlight.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (par->PanelDispCntlRegRead) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) par->PanelDispCntlReg1 = tmpdisp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) par->PanelDispCntlRegRead = !blank_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) switch (blank_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) case FB_BLANK_POWERDOWN: /* powerdown - both sync lines down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) lcdflags = 0; /* LCD off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) dpmsflags = NEO_GR01_SUPPRESS_HSYNC |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) NEO_GR01_SUPPRESS_VSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) #ifdef CONFIG_TOSHIBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* Do we still need this ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) /* attempt to turn off backlight on toshiba; also turns off external */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) SMMRegisters regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) regs.eax = 0xff00; /* HCI_SET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) regs.ebx = 0x0002; /* HCI_BACKLIGHT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) regs.ecx = 0x0000; /* HCI_DISABLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) tosh_smm(®s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) case FB_BLANK_HSYNC_SUSPEND: /* hsync off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) lcdflags = 0; /* LCD off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) dpmsflags = NEO_GR01_SUPPRESS_HSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) case FB_BLANK_VSYNC_SUSPEND: /* vsync off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) lcdflags = 0; /* LCD off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) dpmsflags = NEO_GR01_SUPPRESS_VSYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) case FB_BLANK_NORMAL: /* just blank screen (backlight stays on) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) seqflags = VGA_SR01_SCREEN_OFF; /* Disable sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) * During a blank operation with the LID shut, we might store "LCD off"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) * by mistake. Due to timing issues, the BIOS may switch the lights
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * back on, and we turn it back off once we "unblank".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) * So here is an attempt to implement ">=" - if we are in the process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * of unblanking, and the LCD bit is unset in the driver but set in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) * register, we must keep it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) dpmsflags = 0x00; /* no hsync/vsync suppression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) case FB_BLANK_UNBLANK: /* unblank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) seqflags = 0; /* Enable sequencer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) dpmsflags = 0x00; /* no hsync/vsync suppression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) #ifdef CONFIG_TOSHIBA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) /* Do we still need this ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* attempt to re-enable backlight/external on toshiba */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) SMMRegisters regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) regs.eax = 0xff00; /* HCI_SET */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) regs.ebx = 0x0002; /* HCI_BACKLIGHT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) regs.ecx = 0x0001; /* HCI_ENABLE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) tosh_smm(®s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) default: /* Anything else we don't understand; return 1 to tell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * fb_blank we didn't aactually do anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) neoUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) reg = (vga_rseq(NULL, 0x01) & ~0x20) | seqflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) vga_wseq(NULL, 0x01, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) reg = (vga_rgfx(NULL, 0x20) & ~0x02) | lcdflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) vga_wgfx(NULL, 0x20, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) reg = (vga_rgfx(NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) vga_wgfx(NULL, 0x01, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) neoLock(&par->state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) neo2200_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) u_long dst, rop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) dst = rect->dx + rect->dy * info->var.xres_virtual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) rop = rect->rop ? 0x060000 : 0x0c0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) neo2200_wait_fifo(info, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* set blt control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) writel(NEO_BC3_FIFO_EN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) NEO_BC0_SRC_IS_FG | NEO_BC3_SKIP_MAPPING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) // NEO_BC3_DST_XY_ADDR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) // NEO_BC3_SRC_XY_ADDR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) rop, &par->neo2200->bltCntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) writel(rect->color, &par->neo2200->fgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) writel(((u32 *) (info->pseudo_palette))[rect->color],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) &par->neo2200->fgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) writel(dst * ((info->var.bits_per_pixel + 7) >> 3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) &par->neo2200->dstStart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) writel((rect->height << 16) | (rect->width & 0xffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) &par->neo2200->xyExt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) neo2200_copyarea(struct fb_info *info, const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) u32 sx = area->sx, sy = area->sy, dx = area->dx, dy = area->dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) u_long src, dst, bltCntl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) bltCntl = NEO_BC3_FIFO_EN | NEO_BC3_SKIP_MAPPING | 0x0C0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) if ((dy > sy) || ((dy == sy) && (dx > sx))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) /* Start with the lower right corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) sy += (area->height - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) dy += (area->height - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) sx += (area->width - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) dx += (area->width - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) bltCntl |= NEO_BC0_X_DEC | NEO_BC0_DST_Y_DEC | NEO_BC0_SRC_Y_DEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) src = sx * (info->var.bits_per_pixel >> 3) + sy*info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) dst = dx * (info->var.bits_per_pixel >> 3) + dy*info->fix.line_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) neo2200_wait_fifo(info, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) /* set blt control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) writel(bltCntl, &par->neo2200->bltCntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) writel(src, &par->neo2200->srcStart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) writel(dst, &par->neo2200->dstStart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) writel((area->height << 16) | (area->width & 0xffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) &par->neo2200->xyExt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) neo2200_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) int s_pitch = (image->width * image->depth + 7) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) int scan_align = info->pixmap.scan_align - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) int buf_align = info->pixmap.buf_align - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) int bltCntl_flags, d_pitch, data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) // The data is padded for the hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) d_pitch = (s_pitch + scan_align) & ~scan_align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) data_len = ((d_pitch * image->height) + buf_align) & ~buf_align;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) neo2200_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (image->depth == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (info->var.bits_per_pixel == 24 && image->width < 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) /* FIXME. There is a bug with accelerated color-expanded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * transfers in 24 bit mode if the image being transferred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * is less than 16 bits wide. This is due to insufficient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) * padding when writing the image. We need to adjust
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * struct fb_pixmap. Not yet done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) bltCntl_flags = NEO_BC0_SRC_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) } else if (image->depth == info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) bltCntl_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /* We don't currently support hardware acceleration if image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * depth is different from display */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) switch (info->var.bits_per_pixel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) writel(image->fg_color, &par->neo2200->fgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) writel(image->bg_color, &par->neo2200->bgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) writel(((u32 *) (info->pseudo_palette))[image->fg_color],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) &par->neo2200->fgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) writel(((u32 *) (info->pseudo_palette))[image->bg_color],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) &par->neo2200->bgColor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) writel(NEO_BC0_SYS_TO_VID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) NEO_BC3_SKIP_MAPPING | bltCntl_flags |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) // NEO_BC3_DST_XY_ADDR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) 0x0c0000, &par->neo2200->bltCntl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) writel(0, &par->neo2200->srcStart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) // par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) writel(((image->dx & 0xffff) * (info->var.bits_per_pixel >> 3) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) image->dy * info->fix.line_length), &par->neo2200->dstStart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) writel((image->height << 16) | (image->width & 0xffff),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) &par->neo2200->xyExt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) memcpy_toio(par->mmio_vbase + 0x100000, image->data, data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) neofb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) neo2200_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) cfb_fillrect(info, rect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) neofb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) neo2200_copyarea(info, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) cfb_copyarea(info, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) neofb_imageblit(struct fb_info *info, const struct fb_image *image)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) neo2200_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) cfb_imageblit(info, image);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) neofb_sync(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) neo2200_sync(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) neofb_draw_cursor(struct fb_info *info, u8 *dst, u8 *src, unsigned int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) //memset_io(info->sprite.addr, 0xff, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) neofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) struct neofb_par *par = (struct neofb_par *) info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) * Disable cursor *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) write_le32(NEOREG_CURSCNTL, ~NEO_CURS_ENABLE, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (cursor->set & FB_CUR_SETPOS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) u32 x = cursor->image.dx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) u32 y = cursor->image.dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) info->cursor.image.dx = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) info->cursor.image.dy = y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) write_le32(NEOREG_CURSX, x, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) write_le32(NEOREG_CURSY, y, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) if (cursor->set & FB_CUR_SETSIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) info->cursor.image.height = cursor->image.height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) info->cursor.image.width = cursor->image.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) if (cursor->set & FB_CUR_SETHOT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) info->cursor.hot = cursor->hot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) if (cursor->set & FB_CUR_SETCMAP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (cursor->image.depth == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) u32 fg = cursor->image.fg_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) u32 bg = cursor->image.bg_color;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) info->cursor.image.fg_color = fg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) info->cursor.image.bg_color = bg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) write_le32(NEOREG_CURSFGCOLOR, fg, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) write_le32(NEOREG_CURSBGCOLOR, bg, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (cursor->set & FB_CUR_SETSHAPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) fb_load_cursor_image(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) if (info->cursor.enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) write_le32(NEOREG_CURSCNTL, NEO_CURS_ENABLE, par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) static const struct fb_ops neofb_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) .fb_open = neofb_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) .fb_release = neofb_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) .fb_check_var = neofb_check_var,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) .fb_set_par = neofb_set_par,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) .fb_setcolreg = neofb_setcolreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) .fb_pan_display = neofb_pan_display,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) .fb_blank = neofb_blank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) .fb_sync = neofb_sync,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) .fb_fillrect = neofb_fillrect,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) .fb_copyarea = neofb_copyarea,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) .fb_imageblit = neofb_imageblit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /* --------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) static struct fb_videomode mode800x480 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) .xres = 800,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) .yres = 480,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) .pixclock = 25000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) .left_margin = 88,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) .right_margin = 40,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) .upper_margin = 23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) .lower_margin = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) .hsync_len = 128,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) .vsync_len = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) .vmode = FB_VMODE_NONINTERLACED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) static int neo_map_mmio(struct fb_info *info, struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) DBG("neo_map_mmio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) info->fix.mmio_start = pci_resource_start(dev, 0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) 0x100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) info->fix.mmio_start = pci_resource_start(dev, 0)+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) 0x200000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) info->fix.mmio_start = pci_resource_start(dev, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) info->fix.mmio_start = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) info->fix.mmio_len = MMIO_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) if (!request_mem_region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) (info->fix.mmio_start, MMIO_SIZE, "memory mapped I/O")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) printk("neofb: memory mapped IO in use\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) par->mmio_vbase = ioremap(info->fix.mmio_start, MMIO_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) if (!par->mmio_vbase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) printk("neofb: unable to map memory mapped IO\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) release_mem_region(info->fix.mmio_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) info->fix.mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) printk(KERN_INFO "neofb: mapped io at %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) par->mmio_vbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) static void neo_unmap_mmio(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) DBG("neo_unmap_mmio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) iounmap(par->mmio_vbase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) par->mmio_vbase = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) release_mem_region(info->fix.mmio_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) info->fix.mmio_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) static int neo_map_video(struct fb_info *info, struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) int video_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) //unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) DBG("neo_map_video");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) info->fix.smem_start = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) info->fix.smem_len = video_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) if (!request_mem_region(info->fix.smem_start, info->fix.smem_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) "frame buffer")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) printk("neofb: frame buffer in use\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) info->screen_base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) ioremap_wc(info->fix.smem_start, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) if (!info->screen_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) printk("neofb: unable to map screen memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) release_mem_region(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) printk(KERN_INFO "neofb: mapped framebuffer at %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) par->wc_cookie = arch_phys_wc_add(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) pci_resource_len(dev, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /* Clear framebuffer, it's all white in memory after boot */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) memset_io(info->screen_base, 0, info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) /* Allocate Cursor drawing pad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) info->fix.smem_len -= PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) addr = info->fix.smem_start + info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) write_le32(NEOREG_CURSMEMPOS, ((0x000f & (addr >> 10)) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) ((0x0ff0 & (addr >> 10)) >> 4), par);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) addr = (unsigned long) info->screen_base + info->fix.smem_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) info->sprite.addr = (u8 *) addr; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) static void neo_unmap_video(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) DBG("neo_unmap_video");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) arch_phys_wc_del(par->wc_cookie);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) iounmap(info->screen_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) info->screen_base = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) release_mem_region(info->fix.smem_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) info->fix.smem_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) static int neo_scan_monitor(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) unsigned char type, display;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) int w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) // Eventually we will have i2c support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) info->monspecs.modedb = kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (!info->monspecs.modedb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) info->monspecs.modedb_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) /* Determine the panel type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) vga_wgfx(NULL, 0x09, 0x26);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) type = vga_rgfx(NULL, 0x21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) display = vga_rgfx(NULL, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if (!par->internal_display && !par->external_display) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) par->external_display = display & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) printk (KERN_INFO "Autodetected %s display\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) par->internal_display && par->external_display ? "simultaneous" :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) par->internal_display ? "internal" : "external");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) /* Determine panel width -- used in NeoValidMode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) w = vga_rgfx(NULL, 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) vga_wgfx(NULL, 0x09, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) switch ((w & 0x18) >> 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) // 640x480@60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) par->NeoPanelWidth = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) par->NeoPanelHeight = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) case 0x01:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) par->NeoPanelWidth = 800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) if (par->libretto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) par->NeoPanelHeight = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) memcpy(info->monspecs.modedb, &mode800x480, sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) // 800x600@60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) par->NeoPanelHeight = 600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) memcpy(info->monspecs.modedb, &vesa_modes[8], sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) case 0x02:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) // 1024x768@60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) par->NeoPanelWidth = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) par->NeoPanelHeight = 768;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) memcpy(info->monspecs.modedb, &vesa_modes[13], sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) case 0x03:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) /* 1280x1024@60 panel support needs to be added */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) #ifdef NOT_DONE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) par->NeoPanelWidth = 1280;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) par->NeoPanelHeight = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) memcpy(info->monspecs.modedb, &vesa_modes[20], sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) printk(KERN_ERR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) kfree(info->monspecs.modedb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) // 640x480@60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) par->NeoPanelWidth = 640;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) par->NeoPanelHeight = 480;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) memcpy(info->monspecs.modedb, &vesa_modes[3], sizeof(struct fb_videomode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) printk(KERN_INFO "Panel is a %dx%d %s %s display\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) par->NeoPanelWidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) par->NeoPanelHeight,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) (type & 0x02) ? "color" : "monochrome",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) (type & 0x10) ? "TFT" : "dual scan");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) static int neo_init_hw(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) struct neofb_par *par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) int videoRam = 896;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) int maxClock = 65000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) int CursorMem = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) int CursorOff = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) DBG("neo_init_hw");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) neoUnlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) printk(KERN_DEBUG "--- Neo extended register dump ---\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) for (int w = 0; w < 0x85; w++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) (void *) vga_rcrt(NULL, w));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) for (int w = 0; w < 0xC7; w++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) (void *) vga_rgfx(NULL, w));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) videoRam = 896;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) maxClock = 65000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) videoRam = 1152;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) maxClock = 80000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) videoRam = 2048;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) maxClock = 90000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) videoRam = 2560;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) maxClock = 110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) videoRam = 3008;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) maxClock = 110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) videoRam = 4096;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) maxClock = 110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) videoRam = 6144;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) maxClock = 110000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) CursorMem = 2048;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) CursorOff = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) CursorMem = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) CursorOff = 0x100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) CursorMem = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) CursorOff = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) par->neo2200 = (Neo2200 __iomem *) par->mmio_vbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) info->sprite.size = CursorMem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) info->sprite.scan_align = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) info->sprite.buf_align = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) info->sprite.flags = FB_PIXMAP_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) info->sprite.outbuf = neofb_draw_cursor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) par->maxClock = maxClock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) par->cursorOff = CursorOff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) return videoRam * 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) static struct fb_info *neo_alloc_fb_info(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) struct neofb_par *par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) info = framebuffer_alloc(sizeof(struct neofb_par), &dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) par = info->par;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) info->fix.accel = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) par->pci_burst = !nopciburst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) par->lcd_stretch = !nostretch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) par->libretto = libretto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) par->internal_display = internal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) par->external_display = external;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) switch (info->fix.accel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) case FB_ACCEL_NEOMAGIC_NM2070:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) "MagicGraph 128");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) case FB_ACCEL_NEOMAGIC_NM2090:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) "MagicGraph 128V");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) case FB_ACCEL_NEOMAGIC_NM2093:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) "MagicGraph 128ZV");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) case FB_ACCEL_NEOMAGIC_NM2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) "MagicGraph 128ZV+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) case FB_ACCEL_NEOMAGIC_NM2160:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) "MagicGraph 128XD");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) case FB_ACCEL_NEOMAGIC_NM2200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) "MagicGraph 256AV");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) FBINFO_HWACCEL_COPYAREA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) FBINFO_HWACCEL_FILLRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) case FB_ACCEL_NEOMAGIC_NM2230:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) "MagicGraph 256AV+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) info->flags |= 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) FBINFO_HWACCEL_FILLRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) case FB_ACCEL_NEOMAGIC_NM2360:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) "MagicGraph 256ZX");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) FBINFO_HWACCEL_COPYAREA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) FBINFO_HWACCEL_FILLRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) case FB_ACCEL_NEOMAGIC_NM2380:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) snprintf(info->fix.id, sizeof(info->fix.id),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) "MagicGraph 256XL+");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) info->flags |= FBINFO_HWACCEL_IMAGEBLIT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) FBINFO_HWACCEL_COPYAREA |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) FBINFO_HWACCEL_FILLRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) info->fix.type = FB_TYPE_PACKED_PIXELS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) info->fix.type_aux = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) info->fix.xpanstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) info->fix.ypanstep = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) info->fix.ywrapstep = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) info->fix.accel = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) info->fbops = &neofb_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) info->pseudo_palette = par->palette;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) return info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) static void neo_free_fb_info(struct fb_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) * Free the colourmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) framebuffer_release(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) /* --------------------------------------------------------------------- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) static int neofb_probe(struct pci_dev *dev, const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) struct fb_info *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) u_int h_sync, v_sync;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) int video_len, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) DBG("neofb_probe");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) err = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) info = neo_alloc_fb_info(dev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) if (!info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) err = neo_map_mmio(info, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) goto err_map_mmio;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) err = neo_scan_monitor(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) goto err_scan_monitor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) video_len = neo_init_hw(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (video_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) err = video_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) goto err_init_hw;
^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) err = neo_map_video(info, dev, video_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) goto err_init_hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) if (!fb_find_mode(&info->var, info, mode_option, NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) info->monspecs.modedb, 16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) printk(KERN_ERR "neofb: Unable to find usable video mode.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) goto err_map_video;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) * Calculate the hsync and vsync frequencies. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * we split the 1e12 constant up so that we can preserve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) * the precision and fit the results into 32-bit registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) * (1953125000 * 512 = 1e12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) h_sync = 1953125000 / info->var.pixclock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) h_sync =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) h_sync * 512 / (info->var.xres + info->var.left_margin +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) info->var.right_margin + info->var.hsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) v_sync =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) h_sync / (info->var.yres + info->var.upper_margin +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) info->var.lower_margin + info->var.vsync_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) printk(KERN_INFO "neofb v" NEOFB_VERSION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) info->fix.smem_len >> 10, info->var.xres,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) info->var.yres, h_sync / 1000, h_sync % 1000, v_sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) err = fb_alloc_cmap(&info->cmap, 256, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) goto err_map_video;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) err = register_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) goto err_reg_fb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) fb_info(info, "%s frame buffer device\n", info->fix.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) * Our driver data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) pci_set_drvdata(dev, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) err_reg_fb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) fb_dealloc_cmap(&info->cmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) err_map_video:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) neo_unmap_video(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) err_init_hw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) fb_destroy_modedb(info->monspecs.modedb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) err_scan_monitor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) neo_unmap_mmio(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) err_map_mmio:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) neo_free_fb_info(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) static void neofb_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) struct fb_info *info = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) DBG("neofb_remove");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) if (info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) unregister_framebuffer(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) neo_unmap_video(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) fb_destroy_modedb(info->monspecs.modedb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) neo_unmap_mmio(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) neo_free_fb_info(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) static const struct pci_device_id neofb_devices[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2070,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2070},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2090,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2090},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2093,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2093},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2097,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2097},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2160,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2160},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2200,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2200},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2230,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2230},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2360,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2360},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) {PCI_VENDOR_ID_NEOMAGIC, PCI_CHIP_NM2380,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_NEOMAGIC_NM2380},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) {0, 0, 0, 0, 0, 0, 0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) MODULE_DEVICE_TABLE(pci, neofb_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) static struct pci_driver neofb_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) .name = "neofb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) .id_table = neofb_devices,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) .probe = neofb_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) .remove = neofb_remove,
^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) /* ************************* init in-kernel code ************************** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) static int __init neofb_setup(char *options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) char *this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) DBG("neofb_setup");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) if (!options || !*options)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) while ((this_opt = strsep(&options, ",")) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) if (!*this_opt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) if (!strncmp(this_opt, "internal", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) internal = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) else if (!strncmp(this_opt, "external", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) external = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) else if (!strncmp(this_opt, "nostretch", 9))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) nostretch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) else if (!strncmp(this_opt, "nopciburst", 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) nopciburst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) else if (!strncmp(this_opt, "libretto", 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) libretto = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) mode_option = this_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) #endif /* MODULE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) static int __init neofb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) #ifndef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) char *option = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) if (fb_get_options("neofb", &option))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) neofb_setup(option);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) return pci_register_driver(&neofb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) module_init(neofb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) #ifdef MODULE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) static void __exit neofb_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) pci_unregister_driver(&neofb_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) module_exit(neofb_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) #endif /* MODULE */