18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Contributors (thanks, all!) 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * David Eger: 98c2ecf20Sopenharmony_ci * Overhaul for Linux 2.6 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Jeff Rugen: 128c2ecf20Sopenharmony_ci * Major contributions; Motorola PowerStack (PPC and PCI) support, 138c2ecf20Sopenharmony_ci * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Geert Uytterhoeven: 168c2ecf20Sopenharmony_ci * Excellent code review. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * Lars Hecking: 198c2ecf20Sopenharmony_ci * Amiga updates and testing. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * Original cirrusfb author: Frank Neumann 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Based on retz3fb.c and cirrusfb.c: 248c2ecf20Sopenharmony_ci * Copyright (C) 1997 Jes Sorensen 258c2ecf20Sopenharmony_ci * Copyright (C) 1996 Frank Neumann 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci *************************************************************** 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * Format this code with GNU indent '-kr -i8 -pcs' options. 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 328c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 338c2ecf20Sopenharmony_ci * for more details. 348c2ecf20Sopenharmony_ci * 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#include <linux/module.h> 388c2ecf20Sopenharmony_ci#include <linux/kernel.h> 398c2ecf20Sopenharmony_ci#include <linux/errno.h> 408c2ecf20Sopenharmony_ci#include <linux/string.h> 418c2ecf20Sopenharmony_ci#include <linux/mm.h> 428c2ecf20Sopenharmony_ci#include <linux/delay.h> 438c2ecf20Sopenharmony_ci#include <linux/fb.h> 448c2ecf20Sopenharmony_ci#include <linux/init.h> 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 478c2ecf20Sopenharmony_ci#include <linux/zorro.h> 488c2ecf20Sopenharmony_ci#endif 498c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 508c2ecf20Sopenharmony_ci#include <linux/pci.h> 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci#ifdef CONFIG_AMIGA 538c2ecf20Sopenharmony_ci#include <asm/amigahw.h> 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#include <video/vga.h> 578c2ecf20Sopenharmony_ci#include <video/cirrus.h> 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/***************************************************************** 608c2ecf20Sopenharmony_ci * 618c2ecf20Sopenharmony_ci * debugging and utility macros 628c2ecf20Sopenharmony_ci * 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* disable runtime assertions? */ 668c2ecf20Sopenharmony_ci/* #define CIRRUSFB_NDEBUG */ 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* debugging assertions */ 698c2ecf20Sopenharmony_ci#ifndef CIRRUSFB_NDEBUG 708c2ecf20Sopenharmony_ci#define assert(expr) \ 718c2ecf20Sopenharmony_ci if (!(expr)) { \ 728c2ecf20Sopenharmony_ci printk("Assertion failed! %s,%s,%s,line=%d\n", \ 738c2ecf20Sopenharmony_ci #expr, __FILE__, __func__, __LINE__); \ 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci#else 768c2ecf20Sopenharmony_ci#define assert(expr) 778c2ecf20Sopenharmony_ci#endif 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci#define MB_ (1024 * 1024) 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/***************************************************************** 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci * chipset information 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci */ 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* board types */ 888c2ecf20Sopenharmony_cienum cirrus_board { 898c2ecf20Sopenharmony_ci BT_NONE = 0, 908c2ecf20Sopenharmony_ci BT_SD64, /* GD5434 */ 918c2ecf20Sopenharmony_ci BT_PICCOLO, /* GD5426 */ 928c2ecf20Sopenharmony_ci BT_PICASSO, /* GD5426 or GD5428 */ 938c2ecf20Sopenharmony_ci BT_SPECTRUM, /* GD5426 or GD5428 */ 948c2ecf20Sopenharmony_ci BT_PICASSO4, /* GD5446 */ 958c2ecf20Sopenharmony_ci BT_ALPINE, /* GD543x/4x */ 968c2ecf20Sopenharmony_ci BT_GD5480, 978c2ecf20Sopenharmony_ci BT_LAGUNA, /* GD5462/64 */ 988c2ecf20Sopenharmony_ci BT_LAGUNAB, /* GD5465 */ 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* 1028c2ecf20Sopenharmony_ci * per-board-type information, used for enumerating and abstracting 1038c2ecf20Sopenharmony_ci * chip-specific information 1048c2ecf20Sopenharmony_ci * NOTE: MUST be in the same order as enum cirrus_board in order to 1058c2ecf20Sopenharmony_ci * use direct indexing on this array 1068c2ecf20Sopenharmony_ci * NOTE: '__initdata' cannot be used as some of this info 1078c2ecf20Sopenharmony_ci * is required at runtime. Maybe separate into an init-only and 1088c2ecf20Sopenharmony_ci * a run-time table? 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_cistatic const struct cirrusfb_board_info_rec { 1118c2ecf20Sopenharmony_ci char *name; /* ASCII name of chipset */ 1128c2ecf20Sopenharmony_ci long maxclock[5]; /* maximum video clock */ 1138c2ecf20Sopenharmony_ci /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ 1148c2ecf20Sopenharmony_ci bool init_sr07 : 1; /* init SR07 during init_vgachip() */ 1158c2ecf20Sopenharmony_ci bool init_sr1f : 1; /* write SR1F during init_vgachip() */ 1168c2ecf20Sopenharmony_ci /* construct bit 19 of screen start address */ 1178c2ecf20Sopenharmony_ci bool scrn_start_bit19 : 1; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* initial SR07 value, then for each mode */ 1208c2ecf20Sopenharmony_ci unsigned char sr07; 1218c2ecf20Sopenharmony_ci unsigned char sr07_1bpp; 1228c2ecf20Sopenharmony_ci unsigned char sr07_1bpp_mux; 1238c2ecf20Sopenharmony_ci unsigned char sr07_8bpp; 1248c2ecf20Sopenharmony_ci unsigned char sr07_8bpp_mux; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci unsigned char sr1f; /* SR1F VGA initial register value */ 1278c2ecf20Sopenharmony_ci} cirrusfb_board_info[] = { 1288c2ecf20Sopenharmony_ci [BT_SD64] = { 1298c2ecf20Sopenharmony_ci .name = "CL SD64", 1308c2ecf20Sopenharmony_ci .maxclock = { 1318c2ecf20Sopenharmony_ci /* guess */ 1328c2ecf20Sopenharmony_ci /* the SD64/P4 have a higher max. videoclock */ 1338c2ecf20Sopenharmony_ci 135100, 135100, 85500, 85500, 0 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci .init_sr07 = true, 1368c2ecf20Sopenharmony_ci .init_sr1f = true, 1378c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 1388c2ecf20Sopenharmony_ci .sr07 = 0xF0, 1398c2ecf20Sopenharmony_ci .sr07_1bpp = 0xF0, 1408c2ecf20Sopenharmony_ci .sr07_1bpp_mux = 0xF6, 1418c2ecf20Sopenharmony_ci .sr07_8bpp = 0xF1, 1428c2ecf20Sopenharmony_ci .sr07_8bpp_mux = 0xF7, 1438c2ecf20Sopenharmony_ci .sr1f = 0x1E 1448c2ecf20Sopenharmony_ci }, 1458c2ecf20Sopenharmony_ci [BT_PICCOLO] = { 1468c2ecf20Sopenharmony_ci .name = "CL Piccolo", 1478c2ecf20Sopenharmony_ci .maxclock = { 1488c2ecf20Sopenharmony_ci /* guess */ 1498c2ecf20Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 1508c2ecf20Sopenharmony_ci }, 1518c2ecf20Sopenharmony_ci .init_sr07 = true, 1528c2ecf20Sopenharmony_ci .init_sr1f = true, 1538c2ecf20Sopenharmony_ci .scrn_start_bit19 = false, 1548c2ecf20Sopenharmony_ci .sr07 = 0x80, 1558c2ecf20Sopenharmony_ci .sr07_1bpp = 0x80, 1568c2ecf20Sopenharmony_ci .sr07_8bpp = 0x81, 1578c2ecf20Sopenharmony_ci .sr1f = 0x22 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci [BT_PICASSO] = { 1608c2ecf20Sopenharmony_ci .name = "CL Picasso", 1618c2ecf20Sopenharmony_ci .maxclock = { 1628c2ecf20Sopenharmony_ci /* guess */ 1638c2ecf20Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 1648c2ecf20Sopenharmony_ci }, 1658c2ecf20Sopenharmony_ci .init_sr07 = true, 1668c2ecf20Sopenharmony_ci .init_sr1f = true, 1678c2ecf20Sopenharmony_ci .scrn_start_bit19 = false, 1688c2ecf20Sopenharmony_ci .sr07 = 0x20, 1698c2ecf20Sopenharmony_ci .sr07_1bpp = 0x20, 1708c2ecf20Sopenharmony_ci .sr07_8bpp = 0x21, 1718c2ecf20Sopenharmony_ci .sr1f = 0x22 1728c2ecf20Sopenharmony_ci }, 1738c2ecf20Sopenharmony_ci [BT_SPECTRUM] = { 1748c2ecf20Sopenharmony_ci .name = "CL Spectrum", 1758c2ecf20Sopenharmony_ci .maxclock = { 1768c2ecf20Sopenharmony_ci /* guess */ 1778c2ecf20Sopenharmony_ci 90000, 90000, 90000, 90000, 90000 1788c2ecf20Sopenharmony_ci }, 1798c2ecf20Sopenharmony_ci .init_sr07 = true, 1808c2ecf20Sopenharmony_ci .init_sr1f = true, 1818c2ecf20Sopenharmony_ci .scrn_start_bit19 = false, 1828c2ecf20Sopenharmony_ci .sr07 = 0x80, 1838c2ecf20Sopenharmony_ci .sr07_1bpp = 0x80, 1848c2ecf20Sopenharmony_ci .sr07_8bpp = 0x81, 1858c2ecf20Sopenharmony_ci .sr1f = 0x22 1868c2ecf20Sopenharmony_ci }, 1878c2ecf20Sopenharmony_ci [BT_PICASSO4] = { 1888c2ecf20Sopenharmony_ci .name = "CL Picasso4", 1898c2ecf20Sopenharmony_ci .maxclock = { 1908c2ecf20Sopenharmony_ci 135100, 135100, 85500, 85500, 0 1918c2ecf20Sopenharmony_ci }, 1928c2ecf20Sopenharmony_ci .init_sr07 = true, 1938c2ecf20Sopenharmony_ci .init_sr1f = false, 1948c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 1958c2ecf20Sopenharmony_ci .sr07 = 0xA0, 1968c2ecf20Sopenharmony_ci .sr07_1bpp = 0xA0, 1978c2ecf20Sopenharmony_ci .sr07_1bpp_mux = 0xA6, 1988c2ecf20Sopenharmony_ci .sr07_8bpp = 0xA1, 1998c2ecf20Sopenharmony_ci .sr07_8bpp_mux = 0xA7, 2008c2ecf20Sopenharmony_ci .sr1f = 0 2018c2ecf20Sopenharmony_ci }, 2028c2ecf20Sopenharmony_ci [BT_ALPINE] = { 2038c2ecf20Sopenharmony_ci .name = "CL Alpine", 2048c2ecf20Sopenharmony_ci .maxclock = { 2058c2ecf20Sopenharmony_ci /* for the GD5430. GD5446 can do more... */ 2068c2ecf20Sopenharmony_ci 85500, 85500, 50000, 28500, 0 2078c2ecf20Sopenharmony_ci }, 2088c2ecf20Sopenharmony_ci .init_sr07 = true, 2098c2ecf20Sopenharmony_ci .init_sr1f = true, 2108c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 2118c2ecf20Sopenharmony_ci .sr07 = 0xA0, 2128c2ecf20Sopenharmony_ci .sr07_1bpp = 0xA0, 2138c2ecf20Sopenharmony_ci .sr07_1bpp_mux = 0xA6, 2148c2ecf20Sopenharmony_ci .sr07_8bpp = 0xA1, 2158c2ecf20Sopenharmony_ci .sr07_8bpp_mux = 0xA7, 2168c2ecf20Sopenharmony_ci .sr1f = 0x1C 2178c2ecf20Sopenharmony_ci }, 2188c2ecf20Sopenharmony_ci [BT_GD5480] = { 2198c2ecf20Sopenharmony_ci .name = "CL GD5480", 2208c2ecf20Sopenharmony_ci .maxclock = { 2218c2ecf20Sopenharmony_ci 135100, 200000, 200000, 135100, 135100 2228c2ecf20Sopenharmony_ci }, 2238c2ecf20Sopenharmony_ci .init_sr07 = true, 2248c2ecf20Sopenharmony_ci .init_sr1f = true, 2258c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 2268c2ecf20Sopenharmony_ci .sr07 = 0x10, 2278c2ecf20Sopenharmony_ci .sr07_1bpp = 0x11, 2288c2ecf20Sopenharmony_ci .sr07_8bpp = 0x11, 2298c2ecf20Sopenharmony_ci .sr1f = 0x1C 2308c2ecf20Sopenharmony_ci }, 2318c2ecf20Sopenharmony_ci [BT_LAGUNA] = { 2328c2ecf20Sopenharmony_ci .name = "CL Laguna", 2338c2ecf20Sopenharmony_ci .maxclock = { 2348c2ecf20Sopenharmony_ci /* taken from X11 code */ 2358c2ecf20Sopenharmony_ci 170000, 170000, 170000, 170000, 135100, 2368c2ecf20Sopenharmony_ci }, 2378c2ecf20Sopenharmony_ci .init_sr07 = false, 2388c2ecf20Sopenharmony_ci .init_sr1f = false, 2398c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 2408c2ecf20Sopenharmony_ci }, 2418c2ecf20Sopenharmony_ci [BT_LAGUNAB] = { 2428c2ecf20Sopenharmony_ci .name = "CL Laguna AGP", 2438c2ecf20Sopenharmony_ci .maxclock = { 2448c2ecf20Sopenharmony_ci /* taken from X11 code */ 2458c2ecf20Sopenharmony_ci 170000, 250000, 170000, 170000, 135100, 2468c2ecf20Sopenharmony_ci }, 2478c2ecf20Sopenharmony_ci .init_sr07 = false, 2488c2ecf20Sopenharmony_ci .init_sr1f = false, 2498c2ecf20Sopenharmony_ci .scrn_start_bit19 = true, 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci}; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 2548c2ecf20Sopenharmony_ci#define CHIP(id, btype) \ 2558c2ecf20Sopenharmony_ci { PCI_VENDOR_ID_CIRRUS, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (btype) } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic struct pci_device_id cirrusfb_pci_table[] = { 2588c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), 2598c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64), 2608c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64), 2618c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ 2628c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), 2638c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), 2648c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5480, BT_GD5480), /* MacPicasso likely */ 2658c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ 2668c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ 2678c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ 2688c2ecf20Sopenharmony_ci CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/ 2698c2ecf20Sopenharmony_ci { 0, } 2708c2ecf20Sopenharmony_ci}; 2718c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); 2728c2ecf20Sopenharmony_ci#undef CHIP 2738c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 2768c2ecf20Sopenharmony_cistruct zorrocl { 2778c2ecf20Sopenharmony_ci enum cirrus_board type; /* Board type */ 2788c2ecf20Sopenharmony_ci u32 regoffset; /* Offset of registers in first Zorro device */ 2798c2ecf20Sopenharmony_ci u32 ramsize; /* Size of video RAM in first Zorro device */ 2808c2ecf20Sopenharmony_ci /* If zero, use autoprobe on RAM device */ 2818c2ecf20Sopenharmony_ci u32 ramoffset; /* Offset of video RAM in first Zorro device */ 2828c2ecf20Sopenharmony_ci zorro_id ramid; /* Zorro ID of RAM device */ 2838c2ecf20Sopenharmony_ci zorro_id ramid2; /* Zorro ID of optional second RAM device */ 2848c2ecf20Sopenharmony_ci}; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_sd64 = { 2878c2ecf20Sopenharmony_ci .type = BT_SD64, 2888c2ecf20Sopenharmony_ci .ramid = ZORRO_PROD_HELFRICH_SD64_RAM, 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_piccolo = { 2928c2ecf20Sopenharmony_ci .type = BT_PICCOLO, 2938c2ecf20Sopenharmony_ci .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 2948c2ecf20Sopenharmony_ci}; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_picasso = { 2978c2ecf20Sopenharmony_ci .type = BT_PICASSO, 2988c2ecf20Sopenharmony_ci .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 2998c2ecf20Sopenharmony_ci}; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_spectrum = { 3028c2ecf20Sopenharmony_ci .type = BT_SPECTRUM, 3038c2ecf20Sopenharmony_ci .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 3048c2ecf20Sopenharmony_ci}; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_picasso4_z3 = { 3078c2ecf20Sopenharmony_ci .type = BT_PICASSO4, 3088c2ecf20Sopenharmony_ci .regoffset = 0x00600000, 3098c2ecf20Sopenharmony_ci .ramsize = 4 * MB_, 3108c2ecf20Sopenharmony_ci .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */ 3118c2ecf20Sopenharmony_ci}; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic const struct zorrocl zcl_picasso4_z2 = { 3148c2ecf20Sopenharmony_ci .type = BT_PICASSO4, 3158c2ecf20Sopenharmony_ci .regoffset = 0x10000, 3168c2ecf20Sopenharmony_ci .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1, 3178c2ecf20Sopenharmony_ci .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2, 3188c2ecf20Sopenharmony_ci}; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic const struct zorro_device_id cirrusfb_zorro_table[] = { 3228c2ecf20Sopenharmony_ci { 3238c2ecf20Sopenharmony_ci .id = ZORRO_PROD_HELFRICH_SD64_REG, 3248c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_sd64, 3258c2ecf20Sopenharmony_ci }, { 3268c2ecf20Sopenharmony_ci .id = ZORRO_PROD_HELFRICH_PICCOLO_REG, 3278c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_piccolo, 3288c2ecf20Sopenharmony_ci }, { 3298c2ecf20Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 3308c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso, 3318c2ecf20Sopenharmony_ci }, { 3328c2ecf20Sopenharmony_ci .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 3338c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_spectrum, 3348c2ecf20Sopenharmony_ci }, { 3358c2ecf20Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 3368c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso4_z3, 3378c2ecf20Sopenharmony_ci }, { 3388c2ecf20Sopenharmony_ci .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG, 3398c2ecf20Sopenharmony_ci .driver_data = (unsigned long)&zcl_picasso4_z2, 3408c2ecf20Sopenharmony_ci }, 3418c2ecf20Sopenharmony_ci { 0 } 3428c2ecf20Sopenharmony_ci}; 3438c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 3448c2ecf20Sopenharmony_ci#endif /* CONFIG_ZORRO */ 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 3478c2ecf20Sopenharmony_cienum cirrusfb_dbg_reg_class { 3488c2ecf20Sopenharmony_ci CRT, 3498c2ecf20Sopenharmony_ci SEQ 3508c2ecf20Sopenharmony_ci}; 3518c2ecf20Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/* info about board */ 3548c2ecf20Sopenharmony_cistruct cirrusfb_info { 3558c2ecf20Sopenharmony_ci u8 __iomem *regbase; 3568c2ecf20Sopenharmony_ci u8 __iomem *laguna_mmio; 3578c2ecf20Sopenharmony_ci enum cirrus_board btype; 3588c2ecf20Sopenharmony_ci unsigned char SFR; /* Shadow of special function register */ 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci int multiplexing; 3618c2ecf20Sopenharmony_ci int doubleVCLK; 3628c2ecf20Sopenharmony_ci int blank_mode; 3638c2ecf20Sopenharmony_ci u32 pseudo_palette[16]; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci void (*unmap)(struct fb_info *info); 3668c2ecf20Sopenharmony_ci}; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_cistatic bool noaccel; 3698c2ecf20Sopenharmony_cistatic char *mode_option = "640x480@60"; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci/****************************************************************************/ 3728c2ecf20Sopenharmony_ci/**** BEGIN PROTOTYPES ******************************************************/ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci/*--- Interface used by the world ------------------------------------------*/ 3758c2ecf20Sopenharmony_cistatic int cirrusfb_pan_display(struct fb_var_screeninfo *var, 3768c2ecf20Sopenharmony_ci struct fb_info *info); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci/*--- Internal routines ----------------------------------------------------*/ 3798c2ecf20Sopenharmony_cistatic void init_vgachip(struct fb_info *info); 3808c2ecf20Sopenharmony_cistatic void switch_monitor(struct cirrusfb_info *cinfo, int on); 3818c2ecf20Sopenharmony_cistatic void WGen(const struct cirrusfb_info *cinfo, 3828c2ecf20Sopenharmony_ci int regnum, unsigned char val); 3838c2ecf20Sopenharmony_cistatic unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum); 3848c2ecf20Sopenharmony_cistatic void AttrOn(const struct cirrusfb_info *cinfo); 3858c2ecf20Sopenharmony_cistatic void WHDR(const struct cirrusfb_info *cinfo, unsigned char val); 3868c2ecf20Sopenharmony_cistatic void WSFR(struct cirrusfb_info *cinfo, unsigned char val); 3878c2ecf20Sopenharmony_cistatic void WSFR2(struct cirrusfb_info *cinfo, unsigned char val); 3888c2ecf20Sopenharmony_cistatic void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, 3898c2ecf20Sopenharmony_ci unsigned char red, unsigned char green, unsigned char blue); 3908c2ecf20Sopenharmony_ci#if 0 3918c2ecf20Sopenharmony_cistatic void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, 3928c2ecf20Sopenharmony_ci unsigned char *red, unsigned char *green, 3938c2ecf20Sopenharmony_ci unsigned char *blue); 3948c2ecf20Sopenharmony_ci#endif 3958c2ecf20Sopenharmony_cistatic void cirrusfb_WaitBLT(u8 __iomem *regbase); 3968c2ecf20Sopenharmony_cistatic void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, 3978c2ecf20Sopenharmony_ci u_short curx, u_short cury, 3988c2ecf20Sopenharmony_ci u_short destx, u_short desty, 3998c2ecf20Sopenharmony_ci u_short width, u_short height, 4008c2ecf20Sopenharmony_ci u_short line_length); 4018c2ecf20Sopenharmony_cistatic void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 4028c2ecf20Sopenharmony_ci u_short x, u_short y, 4038c2ecf20Sopenharmony_ci u_short width, u_short height, 4048c2ecf20Sopenharmony_ci u32 fg_color, u32 bg_color, 4058c2ecf20Sopenharmony_ci u_short line_length, u_char blitmode); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic void bestclock(long freq, int *nom, int *den, int *div); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 4108c2ecf20Sopenharmony_cistatic void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase); 4118c2ecf20Sopenharmony_cistatic void cirrusfb_dbg_print_regs(struct fb_info *info, 4128c2ecf20Sopenharmony_ci caddr_t regbase, 4138c2ecf20Sopenharmony_ci enum cirrusfb_dbg_reg_class reg_class, ...); 4148c2ecf20Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci/*** END PROTOTYPES ********************************************************/ 4178c2ecf20Sopenharmony_ci/*****************************************************************************/ 4188c2ecf20Sopenharmony_ci/*** BEGIN Interface Used by the World ***************************************/ 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic inline int is_laguna(const struct cirrusfb_info *cinfo) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic int opencount; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci/*--- Open /dev/fbx ---------------------------------------------------------*/ 4288c2ecf20Sopenharmony_cistatic int cirrusfb_open(struct fb_info *info, int user) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci if (opencount++ == 0) 4318c2ecf20Sopenharmony_ci switch_monitor(info->par, 1); 4328c2ecf20Sopenharmony_ci return 0; 4338c2ecf20Sopenharmony_ci} 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci/*--- Close /dev/fbx --------------------------------------------------------*/ 4368c2ecf20Sopenharmony_cistatic int cirrusfb_release(struct fb_info *info, int user) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci if (--opencount == 0) 4398c2ecf20Sopenharmony_ci switch_monitor(info->par, 0); 4408c2ecf20Sopenharmony_ci return 0; 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci/**** END Interface used by the World *************************************/ 4448c2ecf20Sopenharmony_ci/****************************************************************************/ 4458c2ecf20Sopenharmony_ci/**** BEGIN Hardware specific Routines **************************************/ 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci/* Check if the MCLK is not a better clock source */ 4488c2ecf20Sopenharmony_cistatic int cirrusfb_check_mclk(struct fb_info *info, long freq) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 4518c2ecf20Sopenharmony_ci long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* Read MCLK value */ 4548c2ecf20Sopenharmony_ci mclk = (14318 * mclk) >> 3; 4558c2ecf20Sopenharmony_ci dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk); 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* Determine if we should use MCLK instead of VCLK, and if so, what we 4588c2ecf20Sopenharmony_ci * should divide it by to get VCLK 4598c2ecf20Sopenharmony_ci */ 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (abs(freq - mclk) < 250) { 4628c2ecf20Sopenharmony_ci dev_dbg(info->device, "Using VCLK = MCLK\n"); 4638c2ecf20Sopenharmony_ci return 1; 4648c2ecf20Sopenharmony_ci } else if (abs(freq - (mclk / 2)) < 250) { 4658c2ecf20Sopenharmony_ci dev_dbg(info->device, "Using VCLK = MCLK/2\n"); 4668c2ecf20Sopenharmony_ci return 2; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return 0; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic int cirrusfb_check_pixclock(struct fb_var_screeninfo *var, 4738c2ecf20Sopenharmony_ci struct fb_info *info) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci long freq; 4768c2ecf20Sopenharmony_ci long maxclock; 4778c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 4788c2ecf20Sopenharmony_ci unsigned maxclockidx = var->bits_per_pixel >> 3; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* convert from ps to kHz */ 4818c2ecf20Sopenharmony_ci freq = PICOS2KHZ(var->pixclock ? : 1); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; 4848c2ecf20Sopenharmony_ci cinfo->multiplexing = 0; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci /* If the frequency is greater than we can support, we might be able 4878c2ecf20Sopenharmony_ci * to use multiplexing for the video mode */ 4888c2ecf20Sopenharmony_ci if (freq > maxclock) { 4898c2ecf20Sopenharmony_ci var->pixclock = KHZ2PICOS(maxclock); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci while ((freq = PICOS2KHZ(var->pixclock)) > maxclock) 4928c2ecf20Sopenharmony_ci var->pixclock++; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci /* 4978c2ecf20Sopenharmony_ci * Additional constraint: 8bpp uses DAC clock doubling to allow maximum 4988c2ecf20Sopenharmony_ci * pixel clock 4998c2ecf20Sopenharmony_ci */ 5008c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 8) { 5018c2ecf20Sopenharmony_ci switch (cinfo->btype) { 5028c2ecf20Sopenharmony_ci case BT_ALPINE: 5038c2ecf20Sopenharmony_ci case BT_SD64: 5048c2ecf20Sopenharmony_ci case BT_PICASSO4: 5058c2ecf20Sopenharmony_ci if (freq > 85500) 5068c2ecf20Sopenharmony_ci cinfo->multiplexing = 1; 5078c2ecf20Sopenharmony_ci break; 5088c2ecf20Sopenharmony_ci case BT_GD5480: 5098c2ecf20Sopenharmony_ci if (freq > 135100) 5108c2ecf20Sopenharmony_ci cinfo->multiplexing = 1; 5118c2ecf20Sopenharmony_ci break; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci default: 5148c2ecf20Sopenharmony_ci break; 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* If we have a 1MB 5434, we need to put ourselves in a mode where 5198c2ecf20Sopenharmony_ci * the VCLK is double the pixel clock. */ 5208c2ecf20Sopenharmony_ci cinfo->doubleVCLK = 0; 5218c2ecf20Sopenharmony_ci if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ && 5228c2ecf20Sopenharmony_ci var->bits_per_pixel == 16) { 5238c2ecf20Sopenharmony_ci cinfo->doubleVCLK = 1; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci return 0; 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int cirrusfb_check_var(struct fb_var_screeninfo *var, 5308c2ecf20Sopenharmony_ci struct fb_info *info) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci int yres; 5338c2ecf20Sopenharmony_ci /* memory size in pixels */ 5348c2ecf20Sopenharmony_ci unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; 5358c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci switch (var->bits_per_pixel) { 5388c2ecf20Sopenharmony_ci case 1: 5398c2ecf20Sopenharmony_ci var->red.offset = 0; 5408c2ecf20Sopenharmony_ci var->red.length = 1; 5418c2ecf20Sopenharmony_ci var->green = var->red; 5428c2ecf20Sopenharmony_ci var->blue = var->red; 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci case 8: 5468c2ecf20Sopenharmony_ci var->red.offset = 0; 5478c2ecf20Sopenharmony_ci var->red.length = 8; 5488c2ecf20Sopenharmony_ci var->green = var->red; 5498c2ecf20Sopenharmony_ci var->blue = var->red; 5508c2ecf20Sopenharmony_ci break; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci case 16: 5538c2ecf20Sopenharmony_ci var->red.offset = 11; 5548c2ecf20Sopenharmony_ci var->green.offset = 5; 5558c2ecf20Sopenharmony_ci var->blue.offset = 0; 5568c2ecf20Sopenharmony_ci var->red.length = 5; 5578c2ecf20Sopenharmony_ci var->green.length = 6; 5588c2ecf20Sopenharmony_ci var->blue.length = 5; 5598c2ecf20Sopenharmony_ci break; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci case 24: 5628c2ecf20Sopenharmony_ci var->red.offset = 16; 5638c2ecf20Sopenharmony_ci var->green.offset = 8; 5648c2ecf20Sopenharmony_ci var->blue.offset = 0; 5658c2ecf20Sopenharmony_ci var->red.length = 8; 5668c2ecf20Sopenharmony_ci var->green.length = 8; 5678c2ecf20Sopenharmony_ci var->blue.length = 8; 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci default: 5718c2ecf20Sopenharmony_ci dev_dbg(info->device, 5728c2ecf20Sopenharmony_ci "Unsupported bpp size: %d\n", var->bits_per_pixel); 5738c2ecf20Sopenharmony_ci return -EINVAL; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (var->xres_virtual < var->xres) 5778c2ecf20Sopenharmony_ci var->xres_virtual = var->xres; 5788c2ecf20Sopenharmony_ci /* use highest possible virtual resolution */ 5798c2ecf20Sopenharmony_ci if (var->yres_virtual == -1) { 5808c2ecf20Sopenharmony_ci var->yres_virtual = pixels / var->xres_virtual; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci dev_info(info->device, 5838c2ecf20Sopenharmony_ci "virtual resolution set to maximum of %dx%d\n", 5848c2ecf20Sopenharmony_ci var->xres_virtual, var->yres_virtual); 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci if (var->yres_virtual < var->yres) 5878c2ecf20Sopenharmony_ci var->yres_virtual = var->yres; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (var->xres_virtual * var->yres_virtual > pixels) { 5908c2ecf20Sopenharmony_ci dev_err(info->device, "mode %dx%dx%d rejected... " 5918c2ecf20Sopenharmony_ci "virtual resolution too high to fit into video memory!\n", 5928c2ecf20Sopenharmony_ci var->xres_virtual, var->yres_virtual, 5938c2ecf20Sopenharmony_ci var->bits_per_pixel); 5948c2ecf20Sopenharmony_ci return -EINVAL; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* truncate xoffset and yoffset to maximum if too high */ 5988c2ecf20Sopenharmony_ci if (var->xoffset > var->xres_virtual - var->xres) 5998c2ecf20Sopenharmony_ci var->xoffset = var->xres_virtual - var->xres - 1; 6008c2ecf20Sopenharmony_ci if (var->yoffset > var->yres_virtual - var->yres) 6018c2ecf20Sopenharmony_ci var->yoffset = var->yres_virtual - var->yres - 1; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci var->red.msb_right = 6048c2ecf20Sopenharmony_ci var->green.msb_right = 6058c2ecf20Sopenharmony_ci var->blue.msb_right = 6068c2ecf20Sopenharmony_ci var->transp.offset = 6078c2ecf20Sopenharmony_ci var->transp.length = 6088c2ecf20Sopenharmony_ci var->transp.msb_right = 0; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci yres = var->yres; 6118c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) 6128c2ecf20Sopenharmony_ci yres *= 2; 6138c2ecf20Sopenharmony_ci else if (var->vmode & FB_VMODE_INTERLACED) 6148c2ecf20Sopenharmony_ci yres = (yres + 1) / 2; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (yres >= 1280) { 6178c2ecf20Sopenharmony_ci dev_err(info->device, "ERROR: VerticalTotal >= 1280; " 6188c2ecf20Sopenharmony_ci "special treatment required! (TODO)\n"); 6198c2ecf20Sopenharmony_ci return -EINVAL; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (cirrusfb_check_pixclock(var, info)) 6238c2ecf20Sopenharmony_ci return -EINVAL; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci if (!is_laguna(cinfo)) 6268c2ecf20Sopenharmony_ci var->accel_flags = FB_ACCELF_TEXT; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci return 0; 6298c2ecf20Sopenharmony_ci} 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_cistatic void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 6348c2ecf20Sopenharmony_ci unsigned char old1f, old1e; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci assert(cinfo != NULL); 6378c2ecf20Sopenharmony_ci old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if (div) { 6408c2ecf20Sopenharmony_ci dev_dbg(info->device, "Set %s as pixclock source.\n", 6418c2ecf20Sopenharmony_ci (div == 2) ? "MCLK/2" : "MCLK"); 6428c2ecf20Sopenharmony_ci old1f |= 0x40; 6438c2ecf20Sopenharmony_ci old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; 6448c2ecf20Sopenharmony_ci if (div == 2) 6458c2ecf20Sopenharmony_ci old1e |= 1; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1E, old1e); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1F, old1f); 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci/************************************************************************* 6538c2ecf20Sopenharmony_ci cirrusfb_set_par_foo() 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci actually writes the values for a new video mode into the hardware, 6568c2ecf20Sopenharmony_ci**************************************************************************/ 6578c2ecf20Sopenharmony_cistatic int cirrusfb_set_par_foo(struct fb_info *info) 6588c2ecf20Sopenharmony_ci{ 6598c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 6608c2ecf20Sopenharmony_ci struct fb_var_screeninfo *var = &info->var; 6618c2ecf20Sopenharmony_ci u8 __iomem *regbase = cinfo->regbase; 6628c2ecf20Sopenharmony_ci unsigned char tmp; 6638c2ecf20Sopenharmony_ci int pitch; 6648c2ecf20Sopenharmony_ci const struct cirrusfb_board_info_rec *bi; 6658c2ecf20Sopenharmony_ci int hdispend, hsyncstart, hsyncend, htotal; 6668c2ecf20Sopenharmony_ci int yres, vdispend, vsyncstart, vsyncend, vtotal; 6678c2ecf20Sopenharmony_ci long freq; 6688c2ecf20Sopenharmony_ci int nom, den, div; 6698c2ecf20Sopenharmony_ci unsigned int control = 0, format = 0, threshold = 0; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci dev_dbg(info->device, "Requested mode: %dx%dx%d\n", 6728c2ecf20Sopenharmony_ci var->xres, var->yres, var->bits_per_pixel); 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci switch (var->bits_per_pixel) { 6758c2ecf20Sopenharmony_ci case 1: 6768c2ecf20Sopenharmony_ci info->fix.line_length = var->xres_virtual / 8; 6778c2ecf20Sopenharmony_ci info->fix.visual = FB_VISUAL_MONO10; 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci case 8: 6818c2ecf20Sopenharmony_ci info->fix.line_length = var->xres_virtual; 6828c2ecf20Sopenharmony_ci info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci case 16: 6868c2ecf20Sopenharmony_ci case 24: 6878c2ecf20Sopenharmony_ci info->fix.line_length = var->xres_virtual * 6888c2ecf20Sopenharmony_ci var->bits_per_pixel >> 3; 6898c2ecf20Sopenharmony_ci info->fix.visual = FB_VISUAL_TRUECOLOR; 6908c2ecf20Sopenharmony_ci break; 6918c2ecf20Sopenharmony_ci } 6928c2ecf20Sopenharmony_ci info->fix.type = FB_TYPE_PACKED_PIXELS; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci init_vgachip(info); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci bi = &cirrusfb_board_info[cinfo->btype]; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci hsyncstart = var->xres + var->right_margin; 6998c2ecf20Sopenharmony_ci hsyncend = hsyncstart + var->hsync_len; 7008c2ecf20Sopenharmony_ci htotal = (hsyncend + var->left_margin) / 8; 7018c2ecf20Sopenharmony_ci hdispend = var->xres / 8; 7028c2ecf20Sopenharmony_ci hsyncstart = hsyncstart / 8; 7038c2ecf20Sopenharmony_ci hsyncend = hsyncend / 8; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci vdispend = var->yres; 7068c2ecf20Sopenharmony_ci vsyncstart = vdispend + var->lower_margin; 7078c2ecf20Sopenharmony_ci vsyncend = vsyncstart + var->vsync_len; 7088c2ecf20Sopenharmony_ci vtotal = vsyncend + var->upper_margin; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) { 7118c2ecf20Sopenharmony_ci vdispend *= 2; 7128c2ecf20Sopenharmony_ci vsyncstart *= 2; 7138c2ecf20Sopenharmony_ci vsyncend *= 2; 7148c2ecf20Sopenharmony_ci vtotal *= 2; 7158c2ecf20Sopenharmony_ci } else if (var->vmode & FB_VMODE_INTERLACED) { 7168c2ecf20Sopenharmony_ci vdispend = (vdispend + 1) / 2; 7178c2ecf20Sopenharmony_ci vsyncstart = (vsyncstart + 1) / 2; 7188c2ecf20Sopenharmony_ci vsyncend = (vsyncend + 1) / 2; 7198c2ecf20Sopenharmony_ci vtotal = (vtotal + 1) / 2; 7208c2ecf20Sopenharmony_ci } 7218c2ecf20Sopenharmony_ci yres = vdispend; 7228c2ecf20Sopenharmony_ci if (yres >= 1024) { 7238c2ecf20Sopenharmony_ci vtotal /= 2; 7248c2ecf20Sopenharmony_ci vsyncstart /= 2; 7258c2ecf20Sopenharmony_ci vsyncend /= 2; 7268c2ecf20Sopenharmony_ci vdispend /= 2; 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci vdispend -= 1; 7308c2ecf20Sopenharmony_ci vsyncstart -= 1; 7318c2ecf20Sopenharmony_ci vsyncend -= 1; 7328c2ecf20Sopenharmony_ci vtotal -= 2; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci if (cinfo->multiplexing) { 7358c2ecf20Sopenharmony_ci htotal /= 2; 7368c2ecf20Sopenharmony_ci hsyncstart /= 2; 7378c2ecf20Sopenharmony_ci hsyncend /= 2; 7388c2ecf20Sopenharmony_ci hdispend /= 2; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci htotal -= 5; 7428c2ecf20Sopenharmony_ci hdispend -= 1; 7438c2ecf20Sopenharmony_ci hsyncstart += 1; 7448c2ecf20Sopenharmony_ci hsyncend += 1; 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ 7478c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* if debugging is enabled, all parameters get output before writing */ 7508c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT0: %d\n", htotal); 7518c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT1: %d\n", hdispend); 7548c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT2: %d\n", var->xres / 8); 7578c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* + 128: Compatible read */ 7608c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32); 7618c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, 7628c2ecf20Sopenharmony_ci 128 + ((htotal + 5) % 32)); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT4: %d\n", hsyncstart); 7658c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci tmp = hsyncend % 32; 7688c2ecf20Sopenharmony_ci if ((htotal + 5) & 32) 7698c2ecf20Sopenharmony_ci tmp += 128; 7708c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT5: %d\n", tmp); 7718c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff); 7748c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci tmp = 16; /* LineCompare bit #9 */ 7778c2ecf20Sopenharmony_ci if (vtotal & 256) 7788c2ecf20Sopenharmony_ci tmp |= 1; 7798c2ecf20Sopenharmony_ci if (vdispend & 256) 7808c2ecf20Sopenharmony_ci tmp |= 2; 7818c2ecf20Sopenharmony_ci if (vsyncstart & 256) 7828c2ecf20Sopenharmony_ci tmp |= 4; 7838c2ecf20Sopenharmony_ci if ((vdispend + 1) & 256) 7848c2ecf20Sopenharmony_ci tmp |= 8; 7858c2ecf20Sopenharmony_ci if (vtotal & 512) 7868c2ecf20Sopenharmony_ci tmp |= 32; 7878c2ecf20Sopenharmony_ci if (vdispend & 512) 7888c2ecf20Sopenharmony_ci tmp |= 64; 7898c2ecf20Sopenharmony_ci if (vsyncstart & 512) 7908c2ecf20Sopenharmony_ci tmp |= 128; 7918c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT7: %d\n", tmp); 7928c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci tmp = 0x40; /* LineCompare bit #8 */ 7958c2ecf20Sopenharmony_ci if ((vdispend + 1) & 512) 7968c2ecf20Sopenharmony_ci tmp |= 0x20; 7978c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) 7988c2ecf20Sopenharmony_ci tmp |= 0x80; 7998c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT9: %d\n", tmp); 8008c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff); 8038c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16); 8068c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff); 8098c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff); 8128c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff); 8158c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT18: 0xff\n"); 8188c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci tmp = 0; 8218c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_INTERLACED) 8228c2ecf20Sopenharmony_ci tmp |= 1; 8238c2ecf20Sopenharmony_ci if ((htotal + 5) & 64) 8248c2ecf20Sopenharmony_ci tmp |= 16; 8258c2ecf20Sopenharmony_ci if ((htotal + 5) & 128) 8268c2ecf20Sopenharmony_ci tmp |= 32; 8278c2ecf20Sopenharmony_ci if (vtotal & 256) 8288c2ecf20Sopenharmony_ci tmp |= 64; 8298c2ecf20Sopenharmony_ci if (vtotal & 512) 8308c2ecf20Sopenharmony_ci tmp |= 128; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT1a: %d\n", tmp); 8338c2ecf20Sopenharmony_ci vga_wcrt(regbase, CL_CRT1A, tmp); 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci freq = PICOS2KHZ(var->pixclock); 8368c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 24) 8378c2ecf20Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) 8388c2ecf20Sopenharmony_ci freq *= 3; 8398c2ecf20Sopenharmony_ci if (cinfo->multiplexing) 8408c2ecf20Sopenharmony_ci freq /= 2; 8418c2ecf20Sopenharmony_ci if (cinfo->doubleVCLK) 8428c2ecf20Sopenharmony_ci freq *= 2; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci bestclock(freq, &nom, &den, &div); 8458c2ecf20Sopenharmony_ci 8468c2ecf20Sopenharmony_ci dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n", 8478c2ecf20Sopenharmony_ci freq, nom, den, div); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* set VCLK0 */ 8508c2ecf20Sopenharmony_ci /* hardware RefClock: 14.31818 MHz */ 8518c2ecf20Sopenharmony_ci /* formula: VClk = (OSC * N) / (D * (1+P)) */ 8528c2ecf20Sopenharmony_ci /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 || 8558c2ecf20Sopenharmony_ci cinfo->btype == BT_SD64) { 8568c2ecf20Sopenharmony_ci /* if freq is close to mclk or mclk/2 select mclk 8578c2ecf20Sopenharmony_ci * as clock source 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci int divMCLK = cirrusfb_check_mclk(info, freq); 8608c2ecf20Sopenharmony_ci if (divMCLK) 8618c2ecf20Sopenharmony_ci nom = 0; 8628c2ecf20Sopenharmony_ci cirrusfb_set_mclk_as_source(info, divMCLK); 8638c2ecf20Sopenharmony_ci } 8648c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) { 8658c2ecf20Sopenharmony_ci long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); 8668c2ecf20Sopenharmony_ci unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407); 8678c2ecf20Sopenharmony_ci unsigned short tile_control; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci if (cinfo->btype == BT_LAGUNAB) { 8708c2ecf20Sopenharmony_ci tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4); 8718c2ecf20Sopenharmony_ci tile_control &= ~0x80; 8728c2ecf20Sopenharmony_ci fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4); 8738c2ecf20Sopenharmony_ci } 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc); 8768c2ecf20Sopenharmony_ci fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407); 8778c2ecf20Sopenharmony_ci control = fb_readw(cinfo->laguna_mmio + 0x402); 8788c2ecf20Sopenharmony_ci threshold = fb_readw(cinfo->laguna_mmio + 0xea); 8798c2ecf20Sopenharmony_ci control &= ~0x6800; 8808c2ecf20Sopenharmony_ci format = 0; 8818c2ecf20Sopenharmony_ci threshold &= 0xffc0 & 0x3fbf; 8828c2ecf20Sopenharmony_ci } 8838c2ecf20Sopenharmony_ci if (nom) { 8848c2ecf20Sopenharmony_ci tmp = den << 1; 8858c2ecf20Sopenharmony_ci if (div != 0) 8868c2ecf20Sopenharmony_ci tmp |= 1; 8878c2ecf20Sopenharmony_ci /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ 8888c2ecf20Sopenharmony_ci if ((cinfo->btype == BT_SD64) || 8898c2ecf20Sopenharmony_ci (cinfo->btype == BT_ALPINE) || 8908c2ecf20Sopenharmony_ci (cinfo->btype == BT_GD5480)) 8918c2ecf20Sopenharmony_ci tmp |= 0x80; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* Laguna chipset has reversed clock registers */ 8948c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) { 8958c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRE, tmp); 8968c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR1E, nom); 8978c2ecf20Sopenharmony_ci } else { 8988c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRE, nom); 8998c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR1E, tmp); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci if (yres >= 1024) 9048c2ecf20Sopenharmony_ci /* 1280x1024 */ 9058c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); 9068c2ecf20Sopenharmony_ci else 9078c2ecf20Sopenharmony_ci /* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 9088c2ecf20Sopenharmony_ci * address wrap, no compat. */ 9098c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci /* don't know if it would hurt to also program this if no interlaced */ 9128c2ecf20Sopenharmony_ci /* mode is used, but I feel better this way.. :-) */ 9138c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_INTERLACED) 9148c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2); 9158c2ecf20Sopenharmony_ci else 9168c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci /* adjust horizontal/vertical sync type (low/high), use VCLK3 */ 9198c2ecf20Sopenharmony_ci /* enable display memory & CRTC I/O address for color mode */ 9208c2ecf20Sopenharmony_ci tmp = 0x03 | 0xc; 9218c2ecf20Sopenharmony_ci if (var->sync & FB_SYNC_HOR_HIGH_ACT) 9228c2ecf20Sopenharmony_ci tmp |= 0x40; 9238c2ecf20Sopenharmony_ci if (var->sync & FB_SYNC_VERT_HIGH_ACT) 9248c2ecf20Sopenharmony_ci tmp |= 0x80; 9258c2ecf20Sopenharmony_ci WGen(cinfo, VGA_MIS_W, tmp); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci /* text cursor on and start line */ 9288c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); 9298c2ecf20Sopenharmony_ci /* text cursor end line */ 9308c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31); 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_ci /****************************************************** 9338c2ecf20Sopenharmony_ci * 9348c2ecf20Sopenharmony_ci * 1 bpp 9358c2ecf20Sopenharmony_ci * 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci /* programming for different color depths */ 9398c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 1) { 9408c2ecf20Sopenharmony_ci dev_dbg(info->device, "preparing for 1 bit deep display\n"); 9418c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci /* SR07 */ 9448c2ecf20Sopenharmony_ci switch (cinfo->btype) { 9458c2ecf20Sopenharmony_ci case BT_SD64: 9468c2ecf20Sopenharmony_ci case BT_PICCOLO: 9478c2ecf20Sopenharmony_ci case BT_PICASSO: 9488c2ecf20Sopenharmony_ci case BT_SPECTRUM: 9498c2ecf20Sopenharmony_ci case BT_PICASSO4: 9508c2ecf20Sopenharmony_ci case BT_ALPINE: 9518c2ecf20Sopenharmony_ci case BT_GD5480: 9528c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 9538c2ecf20Sopenharmony_ci cinfo->multiplexing ? 9548c2ecf20Sopenharmony_ci bi->sr07_1bpp_mux : bi->sr07_1bpp); 9558c2ecf20Sopenharmony_ci break; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci case BT_LAGUNA: 9588c2ecf20Sopenharmony_ci case BT_LAGUNAB: 9598c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 9608c2ecf20Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 9618c2ecf20Sopenharmony_ci break; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci default: 9648c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 9658c2ecf20Sopenharmony_ci break; 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* Extended Sequencer Mode */ 9698c2ecf20Sopenharmony_ci switch (cinfo->btype) { 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci case BT_PICCOLO: 9728c2ecf20Sopenharmony_ci case BT_SPECTRUM: 9738c2ecf20Sopenharmony_ci /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ 9748c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 9758c2ecf20Sopenharmony_ci break; 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci case BT_PICASSO: 9788c2ecf20Sopenharmony_ci /* ## vorher d0 avoid FIFO underruns..? */ 9798c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xd0); 9808c2ecf20Sopenharmony_ci break; 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci case BT_SD64: 9838c2ecf20Sopenharmony_ci case BT_PICASSO4: 9848c2ecf20Sopenharmony_ci case BT_ALPINE: 9858c2ecf20Sopenharmony_ci case BT_GD5480: 9868c2ecf20Sopenharmony_ci case BT_LAGUNA: 9878c2ecf20Sopenharmony_ci case BT_LAGUNAB: 9888c2ecf20Sopenharmony_ci /* do nothing */ 9898c2ecf20Sopenharmony_ci break; 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci default: 9928c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 9938c2ecf20Sopenharmony_ci break; 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci /* pixel mask: pass-through for first plane */ 9978c2ecf20Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0x01); 9988c2ecf20Sopenharmony_ci if (cinfo->multiplexing) 9998c2ecf20Sopenharmony_ci /* hidden dac reg: 1280x1024 */ 10008c2ecf20Sopenharmony_ci WHDR(cinfo, 0x4a); 10018c2ecf20Sopenharmony_ci else 10028c2ecf20Sopenharmony_ci /* hidden dac: nothing */ 10038c2ecf20Sopenharmony_ci WHDR(cinfo, 0); 10048c2ecf20Sopenharmony_ci /* memory mode: odd/even, ext. memory */ 10058c2ecf20Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); 10068c2ecf20Sopenharmony_ci /* plane mask: only write to first plane */ 10078c2ecf20Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci /****************************************************** 10118c2ecf20Sopenharmony_ci * 10128c2ecf20Sopenharmony_ci * 8 bpp 10138c2ecf20Sopenharmony_ci * 10148c2ecf20Sopenharmony_ci */ 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci else if (var->bits_per_pixel == 8) { 10178c2ecf20Sopenharmony_ci dev_dbg(info->device, "preparing for 8 bit deep display\n"); 10188c2ecf20Sopenharmony_ci switch (cinfo->btype) { 10198c2ecf20Sopenharmony_ci case BT_SD64: 10208c2ecf20Sopenharmony_ci case BT_PICCOLO: 10218c2ecf20Sopenharmony_ci case BT_PICASSO: 10228c2ecf20Sopenharmony_ci case BT_SPECTRUM: 10238c2ecf20Sopenharmony_ci case BT_PICASSO4: 10248c2ecf20Sopenharmony_ci case BT_ALPINE: 10258c2ecf20Sopenharmony_ci case BT_GD5480: 10268c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 10278c2ecf20Sopenharmony_ci cinfo->multiplexing ? 10288c2ecf20Sopenharmony_ci bi->sr07_8bpp_mux : bi->sr07_8bpp); 10298c2ecf20Sopenharmony_ci break; 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci case BT_LAGUNA: 10328c2ecf20Sopenharmony_ci case BT_LAGUNAB: 10338c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 10348c2ecf20Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) | 0x01); 10358c2ecf20Sopenharmony_ci threshold |= 0x10; 10368c2ecf20Sopenharmony_ci break; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci default: 10398c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 10408c2ecf20Sopenharmony_ci break; 10418c2ecf20Sopenharmony_ci } 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci switch (cinfo->btype) { 10448c2ecf20Sopenharmony_ci case BT_PICCOLO: 10458c2ecf20Sopenharmony_ci case BT_PICASSO: 10468c2ecf20Sopenharmony_ci case BT_SPECTRUM: 10478c2ecf20Sopenharmony_ci /* Fast Page-Mode writes */ 10488c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 10498c2ecf20Sopenharmony_ci break; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci case BT_PICASSO4: 10528c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 10538c2ecf20Sopenharmony_ci /* ### INCOMPLETE!! */ 10548c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb8); 10558c2ecf20Sopenharmony_ci#endif 10568c2ecf20Sopenharmony_ci case BT_ALPINE: 10578c2ecf20Sopenharmony_ci case BT_SD64: 10588c2ecf20Sopenharmony_ci case BT_GD5480: 10598c2ecf20Sopenharmony_ci case BT_LAGUNA: 10608c2ecf20Sopenharmony_ci case BT_LAGUNAB: 10618c2ecf20Sopenharmony_ci /* do nothing */ 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci default: 10658c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown board\n"); 10668c2ecf20Sopenharmony_ci break; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci /* mode register: 256 color mode */ 10708c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 10718c2ecf20Sopenharmony_ci if (cinfo->multiplexing) 10728c2ecf20Sopenharmony_ci /* hidden dac reg: 1280x1024 */ 10738c2ecf20Sopenharmony_ci WHDR(cinfo, 0x4a); 10748c2ecf20Sopenharmony_ci else 10758c2ecf20Sopenharmony_ci /* hidden dac: nothing */ 10768c2ecf20Sopenharmony_ci WHDR(cinfo, 0); 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /****************************************************** 10808c2ecf20Sopenharmony_ci * 10818c2ecf20Sopenharmony_ci * 16 bpp 10828c2ecf20Sopenharmony_ci * 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci else if (var->bits_per_pixel == 16) { 10868c2ecf20Sopenharmony_ci dev_dbg(info->device, "preparing for 16 bit deep display\n"); 10878c2ecf20Sopenharmony_ci switch (cinfo->btype) { 10888c2ecf20Sopenharmony_ci case BT_PICCOLO: 10898c2ecf20Sopenharmony_ci case BT_SPECTRUM: 10908c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x87); 10918c2ecf20Sopenharmony_ci /* Fast Page-Mode writes */ 10928c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 10938c2ecf20Sopenharmony_ci break; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci case BT_PICASSO: 10968c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x27); 10978c2ecf20Sopenharmony_ci /* Fast Page-Mode writes */ 10988c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 10998c2ecf20Sopenharmony_ci break; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci case BT_SD64: 11028c2ecf20Sopenharmony_ci case BT_PICASSO4: 11038c2ecf20Sopenharmony_ci case BT_ALPINE: 11048c2ecf20Sopenharmony_ci /* Extended Sequencer Mode: 256c col. mode */ 11058c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 11068c2ecf20Sopenharmony_ci cinfo->doubleVCLK ? 0xa3 : 0xa7); 11078c2ecf20Sopenharmony_ci break; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci case BT_GD5480: 11108c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x17); 11118c2ecf20Sopenharmony_ci /* We already set SRF and SR1F */ 11128c2ecf20Sopenharmony_ci break; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci case BT_LAGUNA: 11158c2ecf20Sopenharmony_ci case BT_LAGUNAB: 11168c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 11178c2ecf20Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 11188c2ecf20Sopenharmony_ci control |= 0x2000; 11198c2ecf20Sopenharmony_ci format |= 0x1400; 11208c2ecf20Sopenharmony_ci threshold |= 0x10; 11218c2ecf20Sopenharmony_ci break; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci default: 11248c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 11258c2ecf20Sopenharmony_ci break; 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci /* mode register: 256 color mode */ 11298c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 11308c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 11318c2ecf20Sopenharmony_ci WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1); 11328c2ecf20Sopenharmony_ci#elif defined(CONFIG_ZORRO) 11338c2ecf20Sopenharmony_ci /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ 11348c2ecf20Sopenharmony_ci WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ 11358c2ecf20Sopenharmony_ci#endif 11368c2ecf20Sopenharmony_ci } 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci /****************************************************** 11398c2ecf20Sopenharmony_ci * 11408c2ecf20Sopenharmony_ci * 24 bpp 11418c2ecf20Sopenharmony_ci * 11428c2ecf20Sopenharmony_ci */ 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci else if (var->bits_per_pixel == 24) { 11458c2ecf20Sopenharmony_ci dev_dbg(info->device, "preparing for 24 bit deep display\n"); 11468c2ecf20Sopenharmony_ci switch (cinfo->btype) { 11478c2ecf20Sopenharmony_ci case BT_PICCOLO: 11488c2ecf20Sopenharmony_ci case BT_SPECTRUM: 11498c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x85); 11508c2ecf20Sopenharmony_ci /* Fast Page-Mode writes */ 11518c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 11528c2ecf20Sopenharmony_ci break; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ci case BT_PICASSO: 11558c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x25); 11568c2ecf20Sopenharmony_ci /* Fast Page-Mode writes */ 11578c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQRF, 0xb0); 11588c2ecf20Sopenharmony_ci break; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci case BT_SD64: 11618c2ecf20Sopenharmony_ci case BT_PICASSO4: 11628c2ecf20Sopenharmony_ci case BT_ALPINE: 11638c2ecf20Sopenharmony_ci /* Extended Sequencer Mode: 256c col. mode */ 11648c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0xa5); 11658c2ecf20Sopenharmony_ci break; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci case BT_GD5480: 11688c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 0x15); 11698c2ecf20Sopenharmony_ci /* We already set SRF and SR1F */ 11708c2ecf20Sopenharmony_ci break; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci case BT_LAGUNA: 11738c2ecf20Sopenharmony_ci case BT_LAGUNAB: 11748c2ecf20Sopenharmony_ci vga_wseq(regbase, CL_SEQR7, 11758c2ecf20Sopenharmony_ci vga_rseq(regbase, CL_SEQR7) & ~0x01); 11768c2ecf20Sopenharmony_ci control |= 0x4000; 11778c2ecf20Sopenharmony_ci format |= 0x2400; 11788c2ecf20Sopenharmony_ci threshold |= 0x20; 11798c2ecf20Sopenharmony_ci break; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci default: 11828c2ecf20Sopenharmony_ci dev_warn(info->device, "unknown Board\n"); 11838c2ecf20Sopenharmony_ci break; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci /* mode register: 256 color mode */ 11878c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_MODE, 64); 11888c2ecf20Sopenharmony_ci /* hidden dac reg: 8-8-8 mode (24 or 32) */ 11898c2ecf20Sopenharmony_ci WHDR(cinfo, 0xc5); 11908c2ecf20Sopenharmony_ci } 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci /****************************************************** 11938c2ecf20Sopenharmony_ci * 11948c2ecf20Sopenharmony_ci * unknown/unsupported bpp 11958c2ecf20Sopenharmony_ci * 11968c2ecf20Sopenharmony_ci */ 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci else 11998c2ecf20Sopenharmony_ci dev_err(info->device, 12008c2ecf20Sopenharmony_ci "What's this? requested color depth == %d.\n", 12018c2ecf20Sopenharmony_ci var->bits_per_pixel); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci pitch = info->fix.line_length >> 3; 12048c2ecf20Sopenharmony_ci vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff); 12058c2ecf20Sopenharmony_ci tmp = 0x22; 12068c2ecf20Sopenharmony_ci if (pitch & 0x100) 12078c2ecf20Sopenharmony_ci tmp |= 0x10; /* offset overflow bit */ 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci /* screen start addr #16-18, fastpagemode cycles */ 12108c2ecf20Sopenharmony_ci vga_wcrt(regbase, CL_CRT1B, tmp); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci /* screen start address bit 19 */ 12138c2ecf20Sopenharmony_ci if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) 12148c2ecf20Sopenharmony_ci vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1); 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) { 12178c2ecf20Sopenharmony_ci tmp = 0; 12188c2ecf20Sopenharmony_ci if ((htotal + 5) & 256) 12198c2ecf20Sopenharmony_ci tmp |= 128; 12208c2ecf20Sopenharmony_ci if (hdispend & 256) 12218c2ecf20Sopenharmony_ci tmp |= 64; 12228c2ecf20Sopenharmony_ci if (hsyncstart & 256) 12238c2ecf20Sopenharmony_ci tmp |= 48; 12248c2ecf20Sopenharmony_ci if (vtotal & 1024) 12258c2ecf20Sopenharmony_ci tmp |= 8; 12268c2ecf20Sopenharmony_ci if (vdispend & 1024) 12278c2ecf20Sopenharmony_ci tmp |= 4; 12288c2ecf20Sopenharmony_ci if (vsyncstart & 1024) 12298c2ecf20Sopenharmony_ci tmp |= 3; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci vga_wcrt(regbase, CL_CRT1E, tmp); 12328c2ecf20Sopenharmony_ci dev_dbg(info->device, "CRT1e: %d\n", tmp); 12338c2ecf20Sopenharmony_ci } 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci /* pixel panning */ 12368c2ecf20Sopenharmony_ci vga_wattr(regbase, CL_AR33, 0); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* [ EGS: SetOffset(); ] */ 12398c2ecf20Sopenharmony_ci /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ 12408c2ecf20Sopenharmony_ci AttrOn(cinfo); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) { 12438c2ecf20Sopenharmony_ci /* no tiles */ 12448c2ecf20Sopenharmony_ci fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402); 12458c2ecf20Sopenharmony_ci fb_writew(format, cinfo->laguna_mmio + 0xc0); 12468c2ecf20Sopenharmony_ci fb_writew(threshold, cinfo->laguna_mmio + 0xea); 12478c2ecf20Sopenharmony_ci } 12488c2ecf20Sopenharmony_ci /* finally, turn on everything - turn off "FullBandwidth" bit */ 12498c2ecf20Sopenharmony_ci /* also, set "DotClock%2" bit where requested */ 12508c2ecf20Sopenharmony_ci tmp = 0x01; 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci/*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ? 12538c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_CLOCK_HALVE) 12548c2ecf20Sopenharmony_ci tmp |= 0x08; 12558c2ecf20Sopenharmony_ci*/ 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); 12588c2ecf20Sopenharmony_ci dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 12618c2ecf20Sopenharmony_ci cirrusfb_dbg_reg_dump(info, NULL); 12628c2ecf20Sopenharmony_ci#endif 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci return 0; 12658c2ecf20Sopenharmony_ci} 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_ci/* for some reason incomprehensible to me, cirrusfb requires that you write 12688c2ecf20Sopenharmony_ci * the registers twice for the settings to take..grr. -dte */ 12698c2ecf20Sopenharmony_cistatic int cirrusfb_set_par(struct fb_info *info) 12708c2ecf20Sopenharmony_ci{ 12718c2ecf20Sopenharmony_ci cirrusfb_set_par_foo(info); 12728c2ecf20Sopenharmony_ci return cirrusfb_set_par_foo(info); 12738c2ecf20Sopenharmony_ci} 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_cistatic int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, 12768c2ecf20Sopenharmony_ci unsigned blue, unsigned transp, 12778c2ecf20Sopenharmony_ci struct fb_info *info) 12788c2ecf20Sopenharmony_ci{ 12798c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci if (regno > 255) 12828c2ecf20Sopenharmony_ci return -EINVAL; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci if (info->fix.visual == FB_VISUAL_TRUECOLOR) { 12858c2ecf20Sopenharmony_ci u32 v; 12868c2ecf20Sopenharmony_ci red >>= (16 - info->var.red.length); 12878c2ecf20Sopenharmony_ci green >>= (16 - info->var.green.length); 12888c2ecf20Sopenharmony_ci blue >>= (16 - info->var.blue.length); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci if (regno >= 16) 12918c2ecf20Sopenharmony_ci return 1; 12928c2ecf20Sopenharmony_ci v = (red << info->var.red.offset) | 12938c2ecf20Sopenharmony_ci (green << info->var.green.offset) | 12948c2ecf20Sopenharmony_ci (blue << info->var.blue.offset); 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci cinfo->pseudo_palette[regno] = v; 12978c2ecf20Sopenharmony_ci return 0; 12988c2ecf20Sopenharmony_ci } 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 8) 13018c2ecf20Sopenharmony_ci WClut(cinfo, regno, red >> 10, green >> 10, blue >> 10); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci return 0; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci} 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci/************************************************************************* 13088c2ecf20Sopenharmony_ci cirrusfb_pan_display() 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci performs display panning - provided hardware permits this 13118c2ecf20Sopenharmony_ci**************************************************************************/ 13128c2ecf20Sopenharmony_cistatic int cirrusfb_pan_display(struct fb_var_screeninfo *var, 13138c2ecf20Sopenharmony_ci struct fb_info *info) 13148c2ecf20Sopenharmony_ci{ 13158c2ecf20Sopenharmony_ci int xoffset; 13168c2ecf20Sopenharmony_ci unsigned long base; 13178c2ecf20Sopenharmony_ci unsigned char tmp, xpix; 13188c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci /* no range checks for xoffset and yoffset, */ 13218c2ecf20Sopenharmony_ci /* as fb_pan_display has already done this */ 13228c2ecf20Sopenharmony_ci if (var->vmode & FB_VMODE_YWRAP) 13238c2ecf20Sopenharmony_ci return -EINVAL; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci xoffset = var->xoffset * info->var.bits_per_pixel / 8; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci base = var->yoffset * info->fix.line_length + xoffset; 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 1) { 13308c2ecf20Sopenharmony_ci /* base is already correct */ 13318c2ecf20Sopenharmony_ci xpix = (unsigned char) (var->xoffset % 8); 13328c2ecf20Sopenharmony_ci } else { 13338c2ecf20Sopenharmony_ci base /= 4; 13348c2ecf20Sopenharmony_ci xpix = (unsigned char) ((xoffset % 4) * 2); 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci if (!is_laguna(cinfo)) 13388c2ecf20Sopenharmony_ci cirrusfb_WaitBLT(cinfo->regbase); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci /* lower 8 + 8 bits of screen start address */ 13418c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff); 13428c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci /* 0xf2 is %11110010, exclude tmp bits */ 13458c2ecf20Sopenharmony_ci tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2; 13468c2ecf20Sopenharmony_ci /* construct bits 16, 17 and 18 of screen start address */ 13478c2ecf20Sopenharmony_ci if (base & 0x10000) 13488c2ecf20Sopenharmony_ci tmp |= 0x01; 13498c2ecf20Sopenharmony_ci if (base & 0x20000) 13508c2ecf20Sopenharmony_ci tmp |= 0x04; 13518c2ecf20Sopenharmony_ci if (base & 0x40000) 13528c2ecf20Sopenharmony_ci tmp |= 0x08; 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1B, tmp); 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci /* construct bit 19 of screen start address */ 13578c2ecf20Sopenharmony_ci if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { 13588c2ecf20Sopenharmony_ci tmp = vga_rcrt(cinfo->regbase, CL_CRT1D); 13598c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) 13608c2ecf20Sopenharmony_ci tmp = (tmp & ~0x18) | ((base >> 16) & 0x18); 13618c2ecf20Sopenharmony_ci else 13628c2ecf20Sopenharmony_ci tmp = (tmp & ~0x80) | ((base >> 12) & 0x80); 13638c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); 13648c2ecf20Sopenharmony_ci } 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci /* write pixel panning value to AR33; this does not quite work in 8bpp 13678c2ecf20Sopenharmony_ci * 13688c2ecf20Sopenharmony_ci * ### Piccolo..? Will this work? 13698c2ecf20Sopenharmony_ci */ 13708c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 1) 13718c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, CL_AR33, xpix); 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci return 0; 13748c2ecf20Sopenharmony_ci} 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_cistatic int cirrusfb_blank(int blank_mode, struct fb_info *info) 13778c2ecf20Sopenharmony_ci{ 13788c2ecf20Sopenharmony_ci /* 13798c2ecf20Sopenharmony_ci * Blank the screen if blank_mode != 0, else unblank. If blank == NULL 13808c2ecf20Sopenharmony_ci * then the caller blanks by setting the CLUT (Color Look Up Table) 13818c2ecf20Sopenharmony_ci * to all black. Return 0 if blanking succeeded, != 0 if un-/blanking 13828c2ecf20Sopenharmony_ci * failed due to e.g. a video mode which doesn't support it. 13838c2ecf20Sopenharmony_ci * Implements VESA suspend and powerdown modes on hardware that 13848c2ecf20Sopenharmony_ci * supports disabling hsync/vsync: 13858c2ecf20Sopenharmony_ci * blank_mode == 2: suspend vsync 13868c2ecf20Sopenharmony_ci * blank_mode == 3: suspend hsync 13878c2ecf20Sopenharmony_ci * blank_mode == 4: powerdown 13888c2ecf20Sopenharmony_ci */ 13898c2ecf20Sopenharmony_ci unsigned char val; 13908c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 13918c2ecf20Sopenharmony_ci int current_mode = cinfo->blank_mode; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode); 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING || 13968c2ecf20Sopenharmony_ci current_mode == blank_mode) { 13978c2ecf20Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 0\n"); 13988c2ecf20Sopenharmony_ci return 0; 13998c2ecf20Sopenharmony_ci } 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci /* Undo current */ 14028c2ecf20Sopenharmony_ci if (current_mode == FB_BLANK_NORMAL || 14038c2ecf20Sopenharmony_ci current_mode == FB_BLANK_UNBLANK) 14048c2ecf20Sopenharmony_ci /* clear "FullBandwidth" bit */ 14058c2ecf20Sopenharmony_ci val = 0; 14068c2ecf20Sopenharmony_ci else 14078c2ecf20Sopenharmony_ci /* set "FullBandwidth" bit */ 14088c2ecf20Sopenharmony_ci val = 0x20; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf; 14118c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci switch (blank_mode) { 14148c2ecf20Sopenharmony_ci case FB_BLANK_UNBLANK: 14158c2ecf20Sopenharmony_ci case FB_BLANK_NORMAL: 14168c2ecf20Sopenharmony_ci val = 0x00; 14178c2ecf20Sopenharmony_ci break; 14188c2ecf20Sopenharmony_ci case FB_BLANK_VSYNC_SUSPEND: 14198c2ecf20Sopenharmony_ci val = 0x04; 14208c2ecf20Sopenharmony_ci break; 14218c2ecf20Sopenharmony_ci case FB_BLANK_HSYNC_SUSPEND: 14228c2ecf20Sopenharmony_ci val = 0x02; 14238c2ecf20Sopenharmony_ci break; 14248c2ecf20Sopenharmony_ci case FB_BLANK_POWERDOWN: 14258c2ecf20Sopenharmony_ci val = 0x06; 14268c2ecf20Sopenharmony_ci break; 14278c2ecf20Sopenharmony_ci default: 14288c2ecf20Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 1\n"); 14298c2ecf20Sopenharmony_ci return 1; 14308c2ecf20Sopenharmony_ci } 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRE, val); 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci cinfo->blank_mode = blank_mode; 14358c2ecf20Sopenharmony_ci dev_dbg(info->device, "EXIT, returning 0\n"); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci /* Let fbcon do a soft blank for us */ 14388c2ecf20Sopenharmony_ci return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci/**** END Hardware specific Routines **************************************/ 14428c2ecf20Sopenharmony_ci/****************************************************************************/ 14438c2ecf20Sopenharmony_ci/**** BEGIN Internal Routines ***********************************************/ 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_cistatic void init_vgachip(struct fb_info *info) 14468c2ecf20Sopenharmony_ci{ 14478c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 14488c2ecf20Sopenharmony_ci const struct cirrusfb_board_info_rec *bi; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci assert(cinfo != NULL); 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci bi = &cirrusfb_board_info[cinfo->btype]; 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* reset board globally */ 14558c2ecf20Sopenharmony_ci switch (cinfo->btype) { 14568c2ecf20Sopenharmony_ci case BT_PICCOLO: 14578c2ecf20Sopenharmony_ci WSFR(cinfo, 0x01); 14588c2ecf20Sopenharmony_ci udelay(500); 14598c2ecf20Sopenharmony_ci WSFR(cinfo, 0x51); 14608c2ecf20Sopenharmony_ci udelay(500); 14618c2ecf20Sopenharmony_ci break; 14628c2ecf20Sopenharmony_ci case BT_PICASSO: 14638c2ecf20Sopenharmony_ci WSFR2(cinfo, 0xff); 14648c2ecf20Sopenharmony_ci udelay(500); 14658c2ecf20Sopenharmony_ci break; 14668c2ecf20Sopenharmony_ci case BT_SD64: 14678c2ecf20Sopenharmony_ci case BT_SPECTRUM: 14688c2ecf20Sopenharmony_ci WSFR(cinfo, 0x1f); 14698c2ecf20Sopenharmony_ci udelay(500); 14708c2ecf20Sopenharmony_ci WSFR(cinfo, 0x4f); 14718c2ecf20Sopenharmony_ci udelay(500); 14728c2ecf20Sopenharmony_ci break; 14738c2ecf20Sopenharmony_ci case BT_PICASSO4: 14748c2ecf20Sopenharmony_ci /* disable flickerfixer */ 14758c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); 14768c2ecf20Sopenharmony_ci mdelay(100); 14778c2ecf20Sopenharmony_ci /* mode */ 14788c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x00); 14798c2ecf20Sopenharmony_ci fallthrough; 14808c2ecf20Sopenharmony_ci case BT_GD5480: 14818c2ecf20Sopenharmony_ci /* from Klaus' NetBSD driver: */ 14828c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); 14838c2ecf20Sopenharmony_ci fallthrough; 14848c2ecf20Sopenharmony_ci case BT_ALPINE: 14858c2ecf20Sopenharmony_ci /* put blitter into 542x compat */ 14868c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR33, 0x00); 14878c2ecf20Sopenharmony_ci break; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci case BT_LAGUNA: 14908c2ecf20Sopenharmony_ci case BT_LAGUNAB: 14918c2ecf20Sopenharmony_ci /* Nothing to do to reset the board. */ 14928c2ecf20Sopenharmony_ci break; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci default: 14958c2ecf20Sopenharmony_ci dev_err(info->device, "Warning: Unknown board type\n"); 14968c2ecf20Sopenharmony_ci break; 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci /* make sure RAM size set by this point */ 15008c2ecf20Sopenharmony_ci assert(info->screen_size > 0); 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* the P4 is not fully initialized here; I rely on it having been */ 15038c2ecf20Sopenharmony_ci /* inited under AmigaOS already, which seems to work just fine */ 15048c2ecf20Sopenharmony_ci /* (Klaus advised to do it this way) */ 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci if (cinfo->btype != BT_PICASSO4) { 15078c2ecf20Sopenharmony_ci WGen(cinfo, CL_VSSM, 0x10); /* EGS: 0x16 */ 15088c2ecf20Sopenharmony_ci WGen(cinfo, CL_POS102, 0x01); 15098c2ecf20Sopenharmony_ci WGen(cinfo, CL_VSSM, 0x08); /* EGS: 0x0e */ 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci if (cinfo->btype != BT_SD64) 15128c2ecf20Sopenharmony_ci WGen(cinfo, CL_VSSM2, 0x01); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* reset sequencer logic */ 15158c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03); 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci /* FullBandwidth (video off) and 8/9 dot clock */ 15188c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci /* "magic cookie" - doesn't make any sense to me.. */ 15218c2ecf20Sopenharmony_ci/* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ 15228c2ecf20Sopenharmony_ci /* unlock all extension registers */ 15238c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci switch (cinfo->btype) { 15268c2ecf20Sopenharmony_ci case BT_GD5480: 15278c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); 15288c2ecf20Sopenharmony_ci break; 15298c2ecf20Sopenharmony_ci case BT_ALPINE: 15308c2ecf20Sopenharmony_ci case BT_LAGUNA: 15318c2ecf20Sopenharmony_ci case BT_LAGUNAB: 15328c2ecf20Sopenharmony_ci break; 15338c2ecf20Sopenharmony_ci case BT_SD64: 15348c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 15358c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); 15368c2ecf20Sopenharmony_ci#endif 15378c2ecf20Sopenharmony_ci break; 15388c2ecf20Sopenharmony_ci default: 15398c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); 15408c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0); 15418c2ecf20Sopenharmony_ci break; 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci /* plane mask: nothing */ 15458c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); 15468c2ecf20Sopenharmony_ci /* character map select: doesn't even matter in gx mode */ 15478c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); 15488c2ecf20Sopenharmony_ci /* memory mode: chain4, ext. memory */ 15498c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a); 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci /* controller-internal base address of video memory */ 15528c2ecf20Sopenharmony_ci if (bi->init_sr07) 15538c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07); 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci /* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */ 15568c2ecf20Sopenharmony_ci /* EEPROM control: shouldn't be necessary to write to this at all.. */ 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_ci /* graphics cursor X position (incomplete; position gives rem. 3 bits */ 15598c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR10, 0x00); 15608c2ecf20Sopenharmony_ci /* graphics cursor Y position (..."... ) */ 15618c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR11, 0x00); 15628c2ecf20Sopenharmony_ci /* graphics cursor attributes */ 15638c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR12, 0x00); 15648c2ecf20Sopenharmony_ci /* graphics cursor pattern address */ 15658c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR13, 0x00); 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci /* writing these on a P4 might give problems.. */ 15688c2ecf20Sopenharmony_ci if (cinfo->btype != BT_PICASSO4) { 15698c2ecf20Sopenharmony_ci /* configuration readback and ext. color */ 15708c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR17, 0x00); 15718c2ecf20Sopenharmony_ci /* signature generator */ 15728c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); 15738c2ecf20Sopenharmony_ci } 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci /* Screen A preset row scan: none */ 15768c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); 15778c2ecf20Sopenharmony_ci /* Text cursor start: disable text cursor */ 15788c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); 15798c2ecf20Sopenharmony_ci /* Text cursor end: - */ 15808c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); 15818c2ecf20Sopenharmony_ci /* text cursor location high: 0 */ 15828c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); 15838c2ecf20Sopenharmony_ci /* text cursor location low: 0 */ 15848c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00); 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci /* Underline Row scanline: - */ 15878c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); 15888c2ecf20Sopenharmony_ci /* ### add 0x40 for text modes with > 30 MHz pixclock */ 15898c2ecf20Sopenharmony_ci /* ext. display controls: ext.adr. wrap */ 15908c2ecf20Sopenharmony_ci vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci /* Set/Reset registers: - */ 15938c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_SR_VALUE, 0x00); 15948c2ecf20Sopenharmony_ci /* Set/Reset enable: - */ 15958c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_SR_ENABLE, 0x00); 15968c2ecf20Sopenharmony_ci /* Color Compare: - */ 15978c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_VALUE, 0x00); 15988c2ecf20Sopenharmony_ci /* Data Rotate: - */ 15998c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_DATA_ROTATE, 0x00); 16008c2ecf20Sopenharmony_ci /* Read Map Select: - */ 16018c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_PLANE_READ, 0x00); 16028c2ecf20Sopenharmony_ci /* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */ 16038c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_MODE, 0x00); 16048c2ecf20Sopenharmony_ci /* Miscellaneous: memory map base address, graphics mode */ 16058c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_MISC, 0x01); 16068c2ecf20Sopenharmony_ci /* Color Don't care: involve all planes */ 16078c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); 16088c2ecf20Sopenharmony_ci /* Bit Mask: no mask at all */ 16098c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 || 16128c2ecf20Sopenharmony_ci is_laguna(cinfo)) 16138c2ecf20Sopenharmony_ci /* (5434 can't have bit 3 set for bitblt) */ 16148c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRB, 0x20); 16158c2ecf20Sopenharmony_ci else 16168c2ecf20Sopenharmony_ci /* Graphics controller mode extensions: finer granularity, 16178c2ecf20Sopenharmony_ci * 8byte data latches 16188c2ecf20Sopenharmony_ci */ 16198c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRB, 0x28); 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRC, 0xff); /* Color Key compare: - */ 16228c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRD, 0x00); /* Color Key compare mask: - */ 16238c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GRE, 0x00); /* Miscellaneous control: - */ 16248c2ecf20Sopenharmony_ci /* Background color byte 1: - */ 16258c2ecf20Sopenharmony_ci /* vga_wgfx (cinfo->regbase, CL_GR10, 0x00); */ 16268c2ecf20Sopenharmony_ci /* vga_wgfx (cinfo->regbase, CL_GR11, 0x00); */ 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci /* Attribute Controller palette registers: "identity mapping" */ 16298c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE0, 0x00); 16308c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE1, 0x01); 16318c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE2, 0x02); 16328c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE3, 0x03); 16338c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE4, 0x04); 16348c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE5, 0x05); 16358c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE6, 0x06); 16368c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE7, 0x07); 16378c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE8, 0x08); 16388c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTE9, 0x09); 16398c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEA, 0x0a); 16408c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEB, 0x0b); 16418c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEC, 0x0c); 16428c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTED, 0x0d); 16438c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEE, 0x0e); 16448c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PALETTEF, 0x0f); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci /* Attribute Controller mode: graphics mode */ 16478c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_MODE, 0x01); 16488c2ecf20Sopenharmony_ci /* Overscan color reg.: reg. 0 */ 16498c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); 16508c2ecf20Sopenharmony_ci /* Color Plane enable: Enable all 4 planes */ 16518c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); 16528c2ecf20Sopenharmony_ci /* Color Select: - */ 16538c2ecf20Sopenharmony_ci vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci /* BLT Start/status: Blitter reset */ 16588c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x04); 16598c2ecf20Sopenharmony_ci /* - " - : "end-of-reset" */ 16608c2ecf20Sopenharmony_ci vga_wgfx(cinfo->regbase, CL_GR31, 0x00); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci /* misc... */ 16638c2ecf20Sopenharmony_ci WHDR(cinfo, 0); /* Hidden DAC register: - */ 16648c2ecf20Sopenharmony_ci return; 16658c2ecf20Sopenharmony_ci} 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_cistatic void switch_monitor(struct cirrusfb_info *cinfo, int on) 16688c2ecf20Sopenharmony_ci{ 16698c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO /* only works on Zorro boards */ 16708c2ecf20Sopenharmony_ci static int IsOn = 0; /* XXX not ok for multiple boards */ 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO4) 16738c2ecf20Sopenharmony_ci return; /* nothing to switch */ 16748c2ecf20Sopenharmony_ci if (cinfo->btype == BT_ALPINE) 16758c2ecf20Sopenharmony_ci return; /* nothing to switch */ 16768c2ecf20Sopenharmony_ci if (cinfo->btype == BT_GD5480) 16778c2ecf20Sopenharmony_ci return; /* nothing to switch */ 16788c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 16798c2ecf20Sopenharmony_ci if ((on && !IsOn) || (!on && IsOn)) 16808c2ecf20Sopenharmony_ci WSFR(cinfo, 0xff); 16818c2ecf20Sopenharmony_ci return; 16828c2ecf20Sopenharmony_ci } 16838c2ecf20Sopenharmony_ci if (on) { 16848c2ecf20Sopenharmony_ci switch (cinfo->btype) { 16858c2ecf20Sopenharmony_ci case BT_SD64: 16868c2ecf20Sopenharmony_ci WSFR(cinfo, cinfo->SFR | 0x21); 16878c2ecf20Sopenharmony_ci break; 16888c2ecf20Sopenharmony_ci case BT_PICCOLO: 16898c2ecf20Sopenharmony_ci WSFR(cinfo, cinfo->SFR | 0x28); 16908c2ecf20Sopenharmony_ci break; 16918c2ecf20Sopenharmony_ci case BT_SPECTRUM: 16928c2ecf20Sopenharmony_ci WSFR(cinfo, 0x6f); 16938c2ecf20Sopenharmony_ci break; 16948c2ecf20Sopenharmony_ci default: /* do nothing */ break; 16958c2ecf20Sopenharmony_ci } 16968c2ecf20Sopenharmony_ci } else { 16978c2ecf20Sopenharmony_ci switch (cinfo->btype) { 16988c2ecf20Sopenharmony_ci case BT_SD64: 16998c2ecf20Sopenharmony_ci WSFR(cinfo, cinfo->SFR & 0xde); 17008c2ecf20Sopenharmony_ci break; 17018c2ecf20Sopenharmony_ci case BT_PICCOLO: 17028c2ecf20Sopenharmony_ci WSFR(cinfo, cinfo->SFR & 0xd7); 17038c2ecf20Sopenharmony_ci break; 17048c2ecf20Sopenharmony_ci case BT_SPECTRUM: 17058c2ecf20Sopenharmony_ci WSFR(cinfo, 0x4f); 17068c2ecf20Sopenharmony_ci break; 17078c2ecf20Sopenharmony_ci default: /* do nothing */ 17088c2ecf20Sopenharmony_ci break; 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci } 17118c2ecf20Sopenharmony_ci#endif /* CONFIG_ZORRO */ 17128c2ecf20Sopenharmony_ci} 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci/******************************************/ 17158c2ecf20Sopenharmony_ci/* Linux 2.6-style accelerated functions */ 17168c2ecf20Sopenharmony_ci/******************************************/ 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_cistatic int cirrusfb_sync(struct fb_info *info) 17198c2ecf20Sopenharmony_ci{ 17208c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci if (!is_laguna(cinfo)) { 17238c2ecf20Sopenharmony_ci while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03) 17248c2ecf20Sopenharmony_ci cpu_relax(); 17258c2ecf20Sopenharmony_ci } 17268c2ecf20Sopenharmony_ci return 0; 17278c2ecf20Sopenharmony_ci} 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_cistatic void cirrusfb_fillrect(struct fb_info *info, 17308c2ecf20Sopenharmony_ci const struct fb_fillrect *region) 17318c2ecf20Sopenharmony_ci{ 17328c2ecf20Sopenharmony_ci struct fb_fillrect modded; 17338c2ecf20Sopenharmony_ci int vxres, vyres; 17348c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 17358c2ecf20Sopenharmony_ci int m = info->var.bits_per_pixel; 17368c2ecf20Sopenharmony_ci u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ? 17378c2ecf20Sopenharmony_ci cinfo->pseudo_palette[region->color] : region->color; 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 17408c2ecf20Sopenharmony_ci return; 17418c2ecf20Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED) { 17428c2ecf20Sopenharmony_ci cfb_fillrect(info, region); 17438c2ecf20Sopenharmony_ci return; 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci vxres = info->var.xres_virtual; 17478c2ecf20Sopenharmony_ci vyres = info->var.yres_virtual; 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci memcpy(&modded, region, sizeof(struct fb_fillrect)); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci if (!modded.width || !modded.height || 17528c2ecf20Sopenharmony_ci modded.dx >= vxres || modded.dy >= vyres) 17538c2ecf20Sopenharmony_ci return; 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci if (modded.dx + modded.width > vxres) 17568c2ecf20Sopenharmony_ci modded.width = vxres - modded.dx; 17578c2ecf20Sopenharmony_ci if (modded.dy + modded.height > vyres) 17588c2ecf20Sopenharmony_ci modded.height = vyres - modded.dy; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 17618c2ecf20Sopenharmony_ci info->var.bits_per_pixel, 17628c2ecf20Sopenharmony_ci (region->dx * m) / 8, region->dy, 17638c2ecf20Sopenharmony_ci (region->width * m) / 8, region->height, 17648c2ecf20Sopenharmony_ci color, color, 17658c2ecf20Sopenharmony_ci info->fix.line_length, 0x40); 17668c2ecf20Sopenharmony_ci} 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_cistatic void cirrusfb_copyarea(struct fb_info *info, 17698c2ecf20Sopenharmony_ci const struct fb_copyarea *area) 17708c2ecf20Sopenharmony_ci{ 17718c2ecf20Sopenharmony_ci struct fb_copyarea modded; 17728c2ecf20Sopenharmony_ci u32 vxres, vyres; 17738c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 17748c2ecf20Sopenharmony_ci int m = info->var.bits_per_pixel; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 17778c2ecf20Sopenharmony_ci return; 17788c2ecf20Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED) { 17798c2ecf20Sopenharmony_ci cfb_copyarea(info, area); 17808c2ecf20Sopenharmony_ci return; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci vxres = info->var.xres_virtual; 17848c2ecf20Sopenharmony_ci vyres = info->var.yres_virtual; 17858c2ecf20Sopenharmony_ci memcpy(&modded, area, sizeof(struct fb_copyarea)); 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci if (!modded.width || !modded.height || 17888c2ecf20Sopenharmony_ci modded.sx >= vxres || modded.sy >= vyres || 17898c2ecf20Sopenharmony_ci modded.dx >= vxres || modded.dy >= vyres) 17908c2ecf20Sopenharmony_ci return; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci if (modded.sx + modded.width > vxres) 17938c2ecf20Sopenharmony_ci modded.width = vxres - modded.sx; 17948c2ecf20Sopenharmony_ci if (modded.dx + modded.width > vxres) 17958c2ecf20Sopenharmony_ci modded.width = vxres - modded.dx; 17968c2ecf20Sopenharmony_ci if (modded.sy + modded.height > vyres) 17978c2ecf20Sopenharmony_ci modded.height = vyres - modded.sy; 17988c2ecf20Sopenharmony_ci if (modded.dy + modded.height > vyres) 17998c2ecf20Sopenharmony_ci modded.height = vyres - modded.dy; 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci cirrusfb_BitBLT(cinfo->regbase, info->var.bits_per_pixel, 18028c2ecf20Sopenharmony_ci (area->sx * m) / 8, area->sy, 18038c2ecf20Sopenharmony_ci (area->dx * m) / 8, area->dy, 18048c2ecf20Sopenharmony_ci (area->width * m) / 8, area->height, 18058c2ecf20Sopenharmony_ci info->fix.line_length); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci} 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_cistatic void cirrusfb_imageblit(struct fb_info *info, 18108c2ecf20Sopenharmony_ci const struct fb_image *image) 18118c2ecf20Sopenharmony_ci{ 18128c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 18138c2ecf20Sopenharmony_ci unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci if (info->state != FBINFO_STATE_RUNNING) 18168c2ecf20Sopenharmony_ci return; 18178c2ecf20Sopenharmony_ci /* Alpine/SD64 does not work at 24bpp ??? */ 18188c2ecf20Sopenharmony_ci if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) 18198c2ecf20Sopenharmony_ci cfb_imageblit(info, image); 18208c2ecf20Sopenharmony_ci else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) && 18218c2ecf20Sopenharmony_ci op == 0xc) 18228c2ecf20Sopenharmony_ci cfb_imageblit(info, image); 18238c2ecf20Sopenharmony_ci else { 18248c2ecf20Sopenharmony_ci unsigned size = ((image->width + 7) >> 3) * image->height; 18258c2ecf20Sopenharmony_ci int m = info->var.bits_per_pixel; 18268c2ecf20Sopenharmony_ci u32 fg, bg; 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 8) { 18298c2ecf20Sopenharmony_ci fg = image->fg_color; 18308c2ecf20Sopenharmony_ci bg = image->bg_color; 18318c2ecf20Sopenharmony_ci } else { 18328c2ecf20Sopenharmony_ci fg = ((u32 *)(info->pseudo_palette))[image->fg_color]; 18338c2ecf20Sopenharmony_ci bg = ((u32 *)(info->pseudo_palette))[image->bg_color]; 18348c2ecf20Sopenharmony_ci } 18358c2ecf20Sopenharmony_ci if (info->var.bits_per_pixel == 24) { 18368c2ecf20Sopenharmony_ci /* clear background first */ 18378c2ecf20Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 18388c2ecf20Sopenharmony_ci info->var.bits_per_pixel, 18398c2ecf20Sopenharmony_ci (image->dx * m) / 8, image->dy, 18408c2ecf20Sopenharmony_ci (image->width * m) / 8, 18418c2ecf20Sopenharmony_ci image->height, 18428c2ecf20Sopenharmony_ci bg, bg, 18438c2ecf20Sopenharmony_ci info->fix.line_length, 0x40); 18448c2ecf20Sopenharmony_ci } 18458c2ecf20Sopenharmony_ci cirrusfb_RectFill(cinfo->regbase, 18468c2ecf20Sopenharmony_ci info->var.bits_per_pixel, 18478c2ecf20Sopenharmony_ci (image->dx * m) / 8, image->dy, 18488c2ecf20Sopenharmony_ci (image->width * m) / 8, image->height, 18498c2ecf20Sopenharmony_ci fg, bg, 18508c2ecf20Sopenharmony_ci info->fix.line_length, op); 18518c2ecf20Sopenharmony_ci memcpy(info->screen_base, image->data, size); 18528c2ecf20Sopenharmony_ci } 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 18568c2ecf20Sopenharmony_cistatic int release_io_ports; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci/* Pulled the logic from XFree86 Cirrus driver to get the memory size, 18598c2ecf20Sopenharmony_ci * based on the DRAM bandwidth bit and DRAM bank switching bit. This 18608c2ecf20Sopenharmony_ci * works with 1MB, 2MB and 4MB configurations (which the Motorola boards 18618c2ecf20Sopenharmony_ci * seem to have. */ 18628c2ecf20Sopenharmony_cistatic unsigned int cirrusfb_get_memsize(struct fb_info *info, 18638c2ecf20Sopenharmony_ci u8 __iomem *regbase) 18648c2ecf20Sopenharmony_ci{ 18658c2ecf20Sopenharmony_ci unsigned long mem; 18668c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) { 18698c2ecf20Sopenharmony_ci unsigned char SR14 = vga_rseq(regbase, CL_SEQR14); 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci mem = ((SR14 & 7) + 1) << 20; 18728c2ecf20Sopenharmony_ci } else { 18738c2ecf20Sopenharmony_ci unsigned char SRF = vga_rseq(regbase, CL_SEQRF); 18748c2ecf20Sopenharmony_ci switch ((SRF & 0x18)) { 18758c2ecf20Sopenharmony_ci case 0x08: 18768c2ecf20Sopenharmony_ci mem = 512 * 1024; 18778c2ecf20Sopenharmony_ci break; 18788c2ecf20Sopenharmony_ci case 0x10: 18798c2ecf20Sopenharmony_ci mem = 1024 * 1024; 18808c2ecf20Sopenharmony_ci break; 18818c2ecf20Sopenharmony_ci /* 64-bit DRAM data bus width; assume 2MB. 18828c2ecf20Sopenharmony_ci * Also indicates 2MB memory on the 5430. 18838c2ecf20Sopenharmony_ci */ 18848c2ecf20Sopenharmony_ci case 0x18: 18858c2ecf20Sopenharmony_ci mem = 2048 * 1024; 18868c2ecf20Sopenharmony_ci break; 18878c2ecf20Sopenharmony_ci default: 18888c2ecf20Sopenharmony_ci dev_warn(info->device, "Unknown memory size!\n"); 18898c2ecf20Sopenharmony_ci mem = 1024 * 1024; 18908c2ecf20Sopenharmony_ci } 18918c2ecf20Sopenharmony_ci /* If DRAM bank switching is enabled, there must be 18928c2ecf20Sopenharmony_ci * twice as much memory installed. (4MB on the 5434) 18938c2ecf20Sopenharmony_ci */ 18948c2ecf20Sopenharmony_ci if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0) 18958c2ecf20Sopenharmony_ci mem *= 2; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ 18998c2ecf20Sopenharmony_ci return mem; 19008c2ecf20Sopenharmony_ci} 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_cistatic void get_pci_addrs(const struct pci_dev *pdev, 19038c2ecf20Sopenharmony_ci unsigned long *display, unsigned long *registers) 19048c2ecf20Sopenharmony_ci{ 19058c2ecf20Sopenharmony_ci assert(pdev != NULL); 19068c2ecf20Sopenharmony_ci assert(display != NULL); 19078c2ecf20Sopenharmony_ci assert(registers != NULL); 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci *display = 0; 19108c2ecf20Sopenharmony_ci *registers = 0; 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci /* This is a best-guess for now */ 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_ci if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 19158c2ecf20Sopenharmony_ci *display = pci_resource_start(pdev, 1); 19168c2ecf20Sopenharmony_ci *registers = pci_resource_start(pdev, 0); 19178c2ecf20Sopenharmony_ci } else { 19188c2ecf20Sopenharmony_ci *display = pci_resource_start(pdev, 0); 19198c2ecf20Sopenharmony_ci *registers = pci_resource_start(pdev, 1); 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci assert(*display != 0); 19238c2ecf20Sopenharmony_ci} 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_cistatic void cirrusfb_pci_unmap(struct fb_info *info) 19268c2ecf20Sopenharmony_ci{ 19278c2ecf20Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(info->device); 19288c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci if (cinfo->laguna_mmio == NULL) 19318c2ecf20Sopenharmony_ci iounmap(cinfo->laguna_mmio); 19328c2ecf20Sopenharmony_ci iounmap(info->screen_base); 19338c2ecf20Sopenharmony_ci#if 0 /* if system didn't claim this region, we would... */ 19348c2ecf20Sopenharmony_ci release_mem_region(0xA0000, 65535); 19358c2ecf20Sopenharmony_ci#endif 19368c2ecf20Sopenharmony_ci if (release_io_ports) 19378c2ecf20Sopenharmony_ci release_region(0x3C0, 32); 19388c2ecf20Sopenharmony_ci pci_release_regions(pdev); 19398c2ecf20Sopenharmony_ci} 19408c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 19418c2ecf20Sopenharmony_ci 19428c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 19438c2ecf20Sopenharmony_cistatic void cirrusfb_zorro_unmap(struct fb_info *info) 19448c2ecf20Sopenharmony_ci{ 19458c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 19468c2ecf20Sopenharmony_ci struct zorro_dev *zdev = to_zorro_dev(info->device); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci if (info->fix.smem_start > 16 * MB_) 19498c2ecf20Sopenharmony_ci iounmap(info->screen_base); 19508c2ecf20Sopenharmony_ci if (info->fix.mmio_start > 16 * MB_) 19518c2ecf20Sopenharmony_ci iounmap(cinfo->regbase); 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci zorro_release_device(zdev); 19548c2ecf20Sopenharmony_ci} 19558c2ecf20Sopenharmony_ci#endif /* CONFIG_ZORRO */ 19568c2ecf20Sopenharmony_ci 19578c2ecf20Sopenharmony_ci/* function table of the above functions */ 19588c2ecf20Sopenharmony_cistatic const struct fb_ops cirrusfb_ops = { 19598c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 19608c2ecf20Sopenharmony_ci .fb_open = cirrusfb_open, 19618c2ecf20Sopenharmony_ci .fb_release = cirrusfb_release, 19628c2ecf20Sopenharmony_ci .fb_setcolreg = cirrusfb_setcolreg, 19638c2ecf20Sopenharmony_ci .fb_check_var = cirrusfb_check_var, 19648c2ecf20Sopenharmony_ci .fb_set_par = cirrusfb_set_par, 19658c2ecf20Sopenharmony_ci .fb_pan_display = cirrusfb_pan_display, 19668c2ecf20Sopenharmony_ci .fb_blank = cirrusfb_blank, 19678c2ecf20Sopenharmony_ci .fb_fillrect = cirrusfb_fillrect, 19688c2ecf20Sopenharmony_ci .fb_copyarea = cirrusfb_copyarea, 19698c2ecf20Sopenharmony_ci .fb_sync = cirrusfb_sync, 19708c2ecf20Sopenharmony_ci .fb_imageblit = cirrusfb_imageblit, 19718c2ecf20Sopenharmony_ci}; 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_cistatic int cirrusfb_set_fbinfo(struct fb_info *info) 19748c2ecf20Sopenharmony_ci{ 19758c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 19768c2ecf20Sopenharmony_ci struct fb_var_screeninfo *var = &info->var; 19778c2ecf20Sopenharmony_ci 19788c2ecf20Sopenharmony_ci info->pseudo_palette = cinfo->pseudo_palette; 19798c2ecf20Sopenharmony_ci info->flags = FBINFO_DEFAULT 19808c2ecf20Sopenharmony_ci | FBINFO_HWACCEL_XPAN 19818c2ecf20Sopenharmony_ci | FBINFO_HWACCEL_YPAN 19828c2ecf20Sopenharmony_ci | FBINFO_HWACCEL_FILLRECT 19838c2ecf20Sopenharmony_ci | FBINFO_HWACCEL_IMAGEBLIT 19848c2ecf20Sopenharmony_ci | FBINFO_HWACCEL_COPYAREA; 19858c2ecf20Sopenharmony_ci if (noaccel || is_laguna(cinfo)) { 19868c2ecf20Sopenharmony_ci info->flags |= FBINFO_HWACCEL_DISABLED; 19878c2ecf20Sopenharmony_ci info->fix.accel = FB_ACCEL_NONE; 19888c2ecf20Sopenharmony_ci } else 19898c2ecf20Sopenharmony_ci info->fix.accel = FB_ACCEL_CIRRUS_ALPINE; 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci info->fbops = &cirrusfb_ops; 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci if (cinfo->btype == BT_GD5480) { 19948c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 16) 19958c2ecf20Sopenharmony_ci info->screen_base += 1 * MB_; 19968c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 32) 19978c2ecf20Sopenharmony_ci info->screen_base += 2 * MB_; 19988c2ecf20Sopenharmony_ci } 19998c2ecf20Sopenharmony_ci 20008c2ecf20Sopenharmony_ci /* Fill fix common fields */ 20018c2ecf20Sopenharmony_ci strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name, 20028c2ecf20Sopenharmony_ci sizeof(info->fix.id)); 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci /* monochrome: only 1 memory plane */ 20058c2ecf20Sopenharmony_ci /* 8 bit and above: Use whole memory area */ 20068c2ecf20Sopenharmony_ci info->fix.smem_len = info->screen_size; 20078c2ecf20Sopenharmony_ci if (var->bits_per_pixel == 1) 20088c2ecf20Sopenharmony_ci info->fix.smem_len /= 4; 20098c2ecf20Sopenharmony_ci info->fix.type_aux = 0; 20108c2ecf20Sopenharmony_ci info->fix.xpanstep = 1; 20118c2ecf20Sopenharmony_ci info->fix.ypanstep = 1; 20128c2ecf20Sopenharmony_ci info->fix.ywrapstep = 0; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci /* FIXME: map region at 0xB8000 if available, fill in here */ 20158c2ecf20Sopenharmony_ci info->fix.mmio_len = 0; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci fb_alloc_cmap(&info->cmap, 256, 0); 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci return 0; 20208c2ecf20Sopenharmony_ci} 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_cistatic int cirrusfb_register(struct fb_info *info) 20238c2ecf20Sopenharmony_ci{ 20248c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 20258c2ecf20Sopenharmony_ci int err; 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci /* sanity checks */ 20288c2ecf20Sopenharmony_ci assert(cinfo->btype != BT_NONE); 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_ci /* set all the vital stuff */ 20318c2ecf20Sopenharmony_ci cirrusfb_set_fbinfo(info); 20328c2ecf20Sopenharmony_ci 20338c2ecf20Sopenharmony_ci dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base); 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ci err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 20368c2ecf20Sopenharmony_ci if (!err) { 20378c2ecf20Sopenharmony_ci dev_dbg(info->device, "wrong initial video mode\n"); 20388c2ecf20Sopenharmony_ci err = -EINVAL; 20398c2ecf20Sopenharmony_ci goto err_dealloc_cmap; 20408c2ecf20Sopenharmony_ci } 20418c2ecf20Sopenharmony_ci 20428c2ecf20Sopenharmony_ci info->var.activate = FB_ACTIVATE_NOW; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci err = cirrusfb_check_var(&info->var, info); 20458c2ecf20Sopenharmony_ci if (err < 0) { 20468c2ecf20Sopenharmony_ci /* should never happen */ 20478c2ecf20Sopenharmony_ci dev_dbg(info->device, 20488c2ecf20Sopenharmony_ci "choking on default var... umm, no good.\n"); 20498c2ecf20Sopenharmony_ci goto err_dealloc_cmap; 20508c2ecf20Sopenharmony_ci } 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci err = register_framebuffer(info); 20538c2ecf20Sopenharmony_ci if (err < 0) { 20548c2ecf20Sopenharmony_ci dev_err(info->device, 20558c2ecf20Sopenharmony_ci "could not register fb device; err = %d!\n", err); 20568c2ecf20Sopenharmony_ci goto err_dealloc_cmap; 20578c2ecf20Sopenharmony_ci } 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci return 0; 20608c2ecf20Sopenharmony_ci 20618c2ecf20Sopenharmony_cierr_dealloc_cmap: 20628c2ecf20Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 20638c2ecf20Sopenharmony_ci return err; 20648c2ecf20Sopenharmony_ci} 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_cistatic void cirrusfb_cleanup(struct fb_info *info) 20678c2ecf20Sopenharmony_ci{ 20688c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo = info->par; 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci switch_monitor(cinfo, 0); 20718c2ecf20Sopenharmony_ci unregister_framebuffer(info); 20728c2ecf20Sopenharmony_ci fb_dealloc_cmap(&info->cmap); 20738c2ecf20Sopenharmony_ci dev_dbg(info->device, "Framebuffer unregistered\n"); 20748c2ecf20Sopenharmony_ci cinfo->unmap(info); 20758c2ecf20Sopenharmony_ci framebuffer_release(info); 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 20798c2ecf20Sopenharmony_cistatic int cirrusfb_pci_register(struct pci_dev *pdev, 20808c2ecf20Sopenharmony_ci const struct pci_device_id *ent) 20818c2ecf20Sopenharmony_ci{ 20828c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo; 20838c2ecf20Sopenharmony_ci struct fb_info *info; 20848c2ecf20Sopenharmony_ci unsigned long board_addr, board_size; 20858c2ecf20Sopenharmony_ci int ret; 20868c2ecf20Sopenharmony_ci 20878c2ecf20Sopenharmony_ci ret = pci_enable_device(pdev); 20888c2ecf20Sopenharmony_ci if (ret < 0) { 20898c2ecf20Sopenharmony_ci printk(KERN_ERR "cirrusfb: Cannot enable PCI device\n"); 20908c2ecf20Sopenharmony_ci goto err_out; 20918c2ecf20Sopenharmony_ci } 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_ci info = framebuffer_alloc(sizeof(struct cirrusfb_info), &pdev->dev); 20948c2ecf20Sopenharmony_ci if (!info) { 20958c2ecf20Sopenharmony_ci ret = -ENOMEM; 20968c2ecf20Sopenharmony_ci goto err_out; 20978c2ecf20Sopenharmony_ci } 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci cinfo = info->par; 21008c2ecf20Sopenharmony_ci cinfo->btype = (enum cirrus_board) ent->driver_data; 21018c2ecf20Sopenharmony_ci 21028c2ecf20Sopenharmony_ci dev_dbg(info->device, 21038c2ecf20Sopenharmony_ci " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n", 21048c2ecf20Sopenharmony_ci (unsigned long long)pdev->resource[0].start, cinfo->btype); 21058c2ecf20Sopenharmony_ci dev_dbg(info->device, " base address 1 is 0x%Lx\n", 21068c2ecf20Sopenharmony_ci (unsigned long long)pdev->resource[1].start); 21078c2ecf20Sopenharmony_ci 21088c2ecf20Sopenharmony_ci dev_dbg(info->device, 21098c2ecf20Sopenharmony_ci "Attempt to get PCI info for Cirrus Graphics Card\n"); 21108c2ecf20Sopenharmony_ci get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); 21118c2ecf20Sopenharmony_ci /* FIXME: this forces VGA. alternatives? */ 21128c2ecf20Sopenharmony_ci cinfo->regbase = NULL; 21138c2ecf20Sopenharmony_ci cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000); 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", 21168c2ecf20Sopenharmony_ci board_addr, info->fix.mmio_start); 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci board_size = (cinfo->btype == BT_GD5480) ? 21198c2ecf20Sopenharmony_ci 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase); 21208c2ecf20Sopenharmony_ci 21218c2ecf20Sopenharmony_ci ret = pci_request_regions(pdev, "cirrusfb"); 21228c2ecf20Sopenharmony_ci if (ret < 0) { 21238c2ecf20Sopenharmony_ci dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 21248c2ecf20Sopenharmony_ci board_addr); 21258c2ecf20Sopenharmony_ci goto err_release_fb; 21268c2ecf20Sopenharmony_ci } 21278c2ecf20Sopenharmony_ci#if 0 /* if the system didn't claim this region, we would... */ 21288c2ecf20Sopenharmony_ci if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { 21298c2ecf20Sopenharmony_ci dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 21308c2ecf20Sopenharmony_ci 0xA0000L); 21318c2ecf20Sopenharmony_ci ret = -EBUSY; 21328c2ecf20Sopenharmony_ci goto err_release_regions; 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci#endif 21358c2ecf20Sopenharmony_ci if (request_region(0x3C0, 32, "cirrusfb")) 21368c2ecf20Sopenharmony_ci release_io_ports = 1; 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_ci info->screen_base = ioremap(board_addr, board_size); 21398c2ecf20Sopenharmony_ci if (!info->screen_base) { 21408c2ecf20Sopenharmony_ci ret = -EIO; 21418c2ecf20Sopenharmony_ci goto err_release_legacy; 21428c2ecf20Sopenharmony_ci } 21438c2ecf20Sopenharmony_ci 21448c2ecf20Sopenharmony_ci info->fix.smem_start = board_addr; 21458c2ecf20Sopenharmony_ci info->screen_size = board_size; 21468c2ecf20Sopenharmony_ci cinfo->unmap = cirrusfb_pci_unmap; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci dev_info(info->device, 21498c2ecf20Sopenharmony_ci "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n", 21508c2ecf20Sopenharmony_ci info->screen_size >> 10, board_addr); 21518c2ecf20Sopenharmony_ci pci_set_drvdata(pdev, info); 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci ret = cirrusfb_register(info); 21548c2ecf20Sopenharmony_ci if (!ret) 21558c2ecf20Sopenharmony_ci return 0; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci iounmap(info->screen_base); 21588c2ecf20Sopenharmony_cierr_release_legacy: 21598c2ecf20Sopenharmony_ci if (release_io_ports) 21608c2ecf20Sopenharmony_ci release_region(0x3C0, 32); 21618c2ecf20Sopenharmony_ci#if 0 21628c2ecf20Sopenharmony_ci release_mem_region(0xA0000, 65535); 21638c2ecf20Sopenharmony_cierr_release_regions: 21648c2ecf20Sopenharmony_ci#endif 21658c2ecf20Sopenharmony_ci pci_release_regions(pdev); 21668c2ecf20Sopenharmony_cierr_release_fb: 21678c2ecf20Sopenharmony_ci if (cinfo->laguna_mmio != NULL) 21688c2ecf20Sopenharmony_ci iounmap(cinfo->laguna_mmio); 21698c2ecf20Sopenharmony_ci framebuffer_release(info); 21708c2ecf20Sopenharmony_cierr_out: 21718c2ecf20Sopenharmony_ci return ret; 21728c2ecf20Sopenharmony_ci} 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_cistatic void cirrusfb_pci_unregister(struct pci_dev *pdev) 21758c2ecf20Sopenharmony_ci{ 21768c2ecf20Sopenharmony_ci struct fb_info *info = pci_get_drvdata(pdev); 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci cirrusfb_cleanup(info); 21798c2ecf20Sopenharmony_ci} 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_cistatic struct pci_driver cirrusfb_pci_driver = { 21828c2ecf20Sopenharmony_ci .name = "cirrusfb", 21838c2ecf20Sopenharmony_ci .id_table = cirrusfb_pci_table, 21848c2ecf20Sopenharmony_ci .probe = cirrusfb_pci_register, 21858c2ecf20Sopenharmony_ci .remove = cirrusfb_pci_unregister, 21868c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 21878c2ecf20Sopenharmony_ci#if 0 21888c2ecf20Sopenharmony_ci .suspend = cirrusfb_pci_suspend, 21898c2ecf20Sopenharmony_ci .resume = cirrusfb_pci_resume, 21908c2ecf20Sopenharmony_ci#endif 21918c2ecf20Sopenharmony_ci#endif 21928c2ecf20Sopenharmony_ci}; 21938c2ecf20Sopenharmony_ci#endif /* CONFIG_PCI */ 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 21968c2ecf20Sopenharmony_cistatic int cirrusfb_zorro_register(struct zorro_dev *z, 21978c2ecf20Sopenharmony_ci const struct zorro_device_id *ent) 21988c2ecf20Sopenharmony_ci{ 21998c2ecf20Sopenharmony_ci struct fb_info *info; 22008c2ecf20Sopenharmony_ci int error; 22018c2ecf20Sopenharmony_ci const struct zorrocl *zcl; 22028c2ecf20Sopenharmony_ci enum cirrus_board btype; 22038c2ecf20Sopenharmony_ci unsigned long regbase, ramsize, rambase; 22048c2ecf20Sopenharmony_ci struct cirrusfb_info *cinfo; 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ci info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 22078c2ecf20Sopenharmony_ci if (!info) 22088c2ecf20Sopenharmony_ci return -ENOMEM; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci zcl = (const struct zorrocl *)ent->driver_data; 22118c2ecf20Sopenharmony_ci btype = zcl->type; 22128c2ecf20Sopenharmony_ci regbase = zorro_resource_start(z) + zcl->regoffset; 22138c2ecf20Sopenharmony_ci ramsize = zcl->ramsize; 22148c2ecf20Sopenharmony_ci if (ramsize) { 22158c2ecf20Sopenharmony_ci rambase = zorro_resource_start(z) + zcl->ramoffset; 22168c2ecf20Sopenharmony_ci if (zorro_resource_len(z) == 64 * MB_) { 22178c2ecf20Sopenharmony_ci /* Quirk for 64 MiB Picasso IV */ 22188c2ecf20Sopenharmony_ci rambase += zcl->ramoffset; 22198c2ecf20Sopenharmony_ci } 22208c2ecf20Sopenharmony_ci } else { 22218c2ecf20Sopenharmony_ci struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL); 22228c2ecf20Sopenharmony_ci if (!ram || !zorro_resource_len(ram)) { 22238c2ecf20Sopenharmony_ci dev_err(info->device, "No video RAM found\n"); 22248c2ecf20Sopenharmony_ci error = -ENODEV; 22258c2ecf20Sopenharmony_ci goto err_release_fb; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci rambase = zorro_resource_start(ram); 22288c2ecf20Sopenharmony_ci ramsize = zorro_resource_len(ram); 22298c2ecf20Sopenharmony_ci if (zcl->ramid2 && 22308c2ecf20Sopenharmony_ci (ram = zorro_find_device(zcl->ramid2, NULL))) { 22318c2ecf20Sopenharmony_ci if (zorro_resource_start(ram) != rambase + ramsize) { 22328c2ecf20Sopenharmony_ci dev_warn(info->device, 22338c2ecf20Sopenharmony_ci "Skipping non-contiguous RAM at %pR\n", 22348c2ecf20Sopenharmony_ci &ram->resource); 22358c2ecf20Sopenharmony_ci } else { 22368c2ecf20Sopenharmony_ci ramsize += zorro_resource_len(ram); 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci } 22398c2ecf20Sopenharmony_ci } 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci dev_info(info->device, 22428c2ecf20Sopenharmony_ci "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n", 22438c2ecf20Sopenharmony_ci cirrusfb_board_info[btype].name, regbase, ramsize / MB_, 22448c2ecf20Sopenharmony_ci rambase); 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_ci if (!zorro_request_device(z, "cirrusfb")) { 22478c2ecf20Sopenharmony_ci dev_err(info->device, "Cannot reserve %pR\n", &z->resource); 22488c2ecf20Sopenharmony_ci error = -EBUSY; 22498c2ecf20Sopenharmony_ci goto err_release_fb; 22508c2ecf20Sopenharmony_ci } 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci cinfo = info->par; 22538c2ecf20Sopenharmony_ci cinfo->btype = btype; 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_ci info->fix.mmio_start = regbase; 22568c2ecf20Sopenharmony_ci cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) 22578c2ecf20Sopenharmony_ci : ZTWO_VADDR(regbase); 22588c2ecf20Sopenharmony_ci if (!cinfo->regbase) { 22598c2ecf20Sopenharmony_ci dev_err(info->device, "Cannot map registers\n"); 22608c2ecf20Sopenharmony_ci error = -EIO; 22618c2ecf20Sopenharmony_ci goto err_release_dev; 22628c2ecf20Sopenharmony_ci } 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_ci info->fix.smem_start = rambase; 22658c2ecf20Sopenharmony_ci info->screen_size = ramsize; 22668c2ecf20Sopenharmony_ci info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) 22678c2ecf20Sopenharmony_ci : ZTWO_VADDR(rambase); 22688c2ecf20Sopenharmony_ci if (!info->screen_base) { 22698c2ecf20Sopenharmony_ci dev_err(info->device, "Cannot map video RAM\n"); 22708c2ecf20Sopenharmony_ci error = -EIO; 22718c2ecf20Sopenharmony_ci goto err_unmap_reg; 22728c2ecf20Sopenharmony_ci } 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci cinfo->unmap = cirrusfb_zorro_unmap; 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci dev_info(info->device, 22778c2ecf20Sopenharmony_ci "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n", 22788c2ecf20Sopenharmony_ci ramsize / MB_, rambase); 22798c2ecf20Sopenharmony_ci 22808c2ecf20Sopenharmony_ci /* MCLK select etc. */ 22818c2ecf20Sopenharmony_ci if (cirrusfb_board_info[btype].init_sr1f) 22828c2ecf20Sopenharmony_ci vga_wseq(cinfo->regbase, CL_SEQR1F, 22838c2ecf20Sopenharmony_ci cirrusfb_board_info[btype].sr1f); 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci error = cirrusfb_register(info); 22868c2ecf20Sopenharmony_ci if (error) { 22878c2ecf20Sopenharmony_ci dev_err(info->device, "Failed to register device, error %d\n", 22888c2ecf20Sopenharmony_ci error); 22898c2ecf20Sopenharmony_ci goto err_unmap_ram; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci zorro_set_drvdata(z, info); 22938c2ecf20Sopenharmony_ci return 0; 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_cierr_unmap_ram: 22968c2ecf20Sopenharmony_ci if (rambase > 16 * MB_) 22978c2ecf20Sopenharmony_ci iounmap(info->screen_base); 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_cierr_unmap_reg: 23008c2ecf20Sopenharmony_ci if (regbase > 16 * MB_) 23018c2ecf20Sopenharmony_ci iounmap(cinfo->regbase); 23028c2ecf20Sopenharmony_cierr_release_dev: 23038c2ecf20Sopenharmony_ci zorro_release_device(z); 23048c2ecf20Sopenharmony_cierr_release_fb: 23058c2ecf20Sopenharmony_ci framebuffer_release(info); 23068c2ecf20Sopenharmony_ci return error; 23078c2ecf20Sopenharmony_ci} 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_civoid cirrusfb_zorro_unregister(struct zorro_dev *z) 23108c2ecf20Sopenharmony_ci{ 23118c2ecf20Sopenharmony_ci struct fb_info *info = zorro_get_drvdata(z); 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci cirrusfb_cleanup(info); 23148c2ecf20Sopenharmony_ci zorro_set_drvdata(z, NULL); 23158c2ecf20Sopenharmony_ci} 23168c2ecf20Sopenharmony_ci 23178c2ecf20Sopenharmony_cistatic struct zorro_driver cirrusfb_zorro_driver = { 23188c2ecf20Sopenharmony_ci .name = "cirrusfb", 23198c2ecf20Sopenharmony_ci .id_table = cirrusfb_zorro_table, 23208c2ecf20Sopenharmony_ci .probe = cirrusfb_zorro_register, 23218c2ecf20Sopenharmony_ci .remove = cirrusfb_zorro_unregister, 23228c2ecf20Sopenharmony_ci}; 23238c2ecf20Sopenharmony_ci#endif /* CONFIG_ZORRO */ 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci#ifndef MODULE 23268c2ecf20Sopenharmony_cistatic int __init cirrusfb_setup(char *options) 23278c2ecf20Sopenharmony_ci{ 23288c2ecf20Sopenharmony_ci char *this_opt; 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci if (!options || !*options) 23318c2ecf20Sopenharmony_ci return 0; 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_ci while ((this_opt = strsep(&options, ",")) != NULL) { 23348c2ecf20Sopenharmony_ci if (!*this_opt) 23358c2ecf20Sopenharmony_ci continue; 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci if (!strcmp(this_opt, "noaccel")) 23388c2ecf20Sopenharmony_ci noaccel = 1; 23398c2ecf20Sopenharmony_ci else if (!strncmp(this_opt, "mode:", 5)) 23408c2ecf20Sopenharmony_ci mode_option = this_opt + 5; 23418c2ecf20Sopenharmony_ci else 23428c2ecf20Sopenharmony_ci mode_option = this_opt; 23438c2ecf20Sopenharmony_ci } 23448c2ecf20Sopenharmony_ci return 0; 23458c2ecf20Sopenharmony_ci} 23468c2ecf20Sopenharmony_ci#endif 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci /* 23498c2ecf20Sopenharmony_ci * Modularization 23508c2ecf20Sopenharmony_ci */ 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); 23538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); 23548c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 23558c2ecf20Sopenharmony_ci 23568c2ecf20Sopenharmony_cistatic int __init cirrusfb_init(void) 23578c2ecf20Sopenharmony_ci{ 23588c2ecf20Sopenharmony_ci int error = 0; 23598c2ecf20Sopenharmony_ci 23608c2ecf20Sopenharmony_ci#ifndef MODULE 23618c2ecf20Sopenharmony_ci char *option = NULL; 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_ci if (fb_get_options("cirrusfb", &option)) 23648c2ecf20Sopenharmony_ci return -ENODEV; 23658c2ecf20Sopenharmony_ci cirrusfb_setup(option); 23668c2ecf20Sopenharmony_ci#endif 23678c2ecf20Sopenharmony_ci 23688c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 23698c2ecf20Sopenharmony_ci error |= zorro_register_driver(&cirrusfb_zorro_driver); 23708c2ecf20Sopenharmony_ci#endif 23718c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 23728c2ecf20Sopenharmony_ci error |= pci_register_driver(&cirrusfb_pci_driver); 23738c2ecf20Sopenharmony_ci#endif 23748c2ecf20Sopenharmony_ci return error; 23758c2ecf20Sopenharmony_ci} 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_cistatic void __exit cirrusfb_exit(void) 23788c2ecf20Sopenharmony_ci{ 23798c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI 23808c2ecf20Sopenharmony_ci pci_unregister_driver(&cirrusfb_pci_driver); 23818c2ecf20Sopenharmony_ci#endif 23828c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 23838c2ecf20Sopenharmony_ci zorro_unregister_driver(&cirrusfb_zorro_driver); 23848c2ecf20Sopenharmony_ci#endif 23858c2ecf20Sopenharmony_ci} 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_cimodule_init(cirrusfb_init); 23888c2ecf20Sopenharmony_ci 23898c2ecf20Sopenharmony_cimodule_param(mode_option, charp, 0); 23908c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); 23918c2ecf20Sopenharmony_cimodule_param(noaccel, bool, 0); 23928c2ecf20Sopenharmony_ciMODULE_PARM_DESC(noaccel, "Disable acceleration"); 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci#ifdef MODULE 23958c2ecf20Sopenharmony_cimodule_exit(cirrusfb_exit); 23968c2ecf20Sopenharmony_ci#endif 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci/**********************************************************************/ 23998c2ecf20Sopenharmony_ci/* about the following functions - I have used the same names for the */ 24008c2ecf20Sopenharmony_ci/* functions as Markus Wild did in his Retina driver for NetBSD as */ 24018c2ecf20Sopenharmony_ci/* they just made sense for this purpose. Apart from that, I wrote */ 24028c2ecf20Sopenharmony_ci/* these functions myself. */ 24038c2ecf20Sopenharmony_ci/**********************************************************************/ 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci/*** WGen() - write into one of the external/general registers ***/ 24068c2ecf20Sopenharmony_cistatic void WGen(const struct cirrusfb_info *cinfo, 24078c2ecf20Sopenharmony_ci int regnum, unsigned char val) 24088c2ecf20Sopenharmony_ci{ 24098c2ecf20Sopenharmony_ci unsigned long regofs = 0; 24108c2ecf20Sopenharmony_ci 24118c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 24128c2ecf20Sopenharmony_ci /* Picasso II specific hack */ 24138c2ecf20Sopenharmony_ci/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || 24148c2ecf20Sopenharmony_ci regnum == CL_VSSM2) */ 24158c2ecf20Sopenharmony_ci if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 24168c2ecf20Sopenharmony_ci regofs = 0xfff; 24178c2ecf20Sopenharmony_ci } 24188c2ecf20Sopenharmony_ci 24198c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, regofs + regnum, val); 24208c2ecf20Sopenharmony_ci} 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci/*** RGen() - read out one of the external/general registers ***/ 24238c2ecf20Sopenharmony_cistatic unsigned char RGen(const struct cirrusfb_info *cinfo, int regnum) 24248c2ecf20Sopenharmony_ci{ 24258c2ecf20Sopenharmony_ci unsigned long regofs = 0; 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 24288c2ecf20Sopenharmony_ci /* Picasso II specific hack */ 24298c2ecf20Sopenharmony_ci/* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || 24308c2ecf20Sopenharmony_ci regnum == CL_VSSM2) */ 24318c2ecf20Sopenharmony_ci if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D) 24328c2ecf20Sopenharmony_ci regofs = 0xfff; 24338c2ecf20Sopenharmony_ci } 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_ci return vga_r(cinfo->regbase, regofs + regnum); 24368c2ecf20Sopenharmony_ci} 24378c2ecf20Sopenharmony_ci 24388c2ecf20Sopenharmony_ci/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ 24398c2ecf20Sopenharmony_cistatic void AttrOn(const struct cirrusfb_info *cinfo) 24408c2ecf20Sopenharmony_ci{ 24418c2ecf20Sopenharmony_ci assert(cinfo != NULL); 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { 24448c2ecf20Sopenharmony_ci /* if we're just in "write value" mode, write back the */ 24458c2ecf20Sopenharmony_ci /* same value as before to not modify anything */ 24468c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 24478c2ecf20Sopenharmony_ci vga_r(cinfo->regbase, VGA_ATT_R)); 24488c2ecf20Sopenharmony_ci } 24498c2ecf20Sopenharmony_ci /* turn on video bit */ 24508c2ecf20Sopenharmony_ci/* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */ 24518c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 0x33); 24528c2ecf20Sopenharmony_ci 24538c2ecf20Sopenharmony_ci /* dummy write on Reg0 to be on "write index" mode next time */ 24548c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); 24558c2ecf20Sopenharmony_ci} 24568c2ecf20Sopenharmony_ci 24578c2ecf20Sopenharmony_ci/*** WHDR() - write into the Hidden DAC register ***/ 24588c2ecf20Sopenharmony_ci/* as the HDR is the only extension register that requires special treatment 24598c2ecf20Sopenharmony_ci * (the other extension registers are accessible just like the "ordinary" 24608c2ecf20Sopenharmony_ci * registers of their functional group) here is a specialized routine for 24618c2ecf20Sopenharmony_ci * accessing the HDR 24628c2ecf20Sopenharmony_ci */ 24638c2ecf20Sopenharmony_cistatic void WHDR(const struct cirrusfb_info *cinfo, unsigned char val) 24648c2ecf20Sopenharmony_ci{ 24658c2ecf20Sopenharmony_ci unsigned char dummy; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci if (is_laguna(cinfo)) 24688c2ecf20Sopenharmony_ci return; 24698c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 24708c2ecf20Sopenharmony_ci /* Klaus' hint for correct access to HDR on some boards */ 24718c2ecf20Sopenharmony_ci /* first write 0 to pixel mask (3c6) */ 24728c2ecf20Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0x00); 24738c2ecf20Sopenharmony_ci udelay(200); 24748c2ecf20Sopenharmony_ci /* next read dummy from pixel address (3c8) */ 24758c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_IW); 24768c2ecf20Sopenharmony_ci udelay(200); 24778c2ecf20Sopenharmony_ci } 24788c2ecf20Sopenharmony_ci /* now do the usual stuff to access the HDR */ 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_MSK); 24818c2ecf20Sopenharmony_ci udelay(200); 24828c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_MSK); 24838c2ecf20Sopenharmony_ci udelay(200); 24848c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_MSK); 24858c2ecf20Sopenharmony_ci udelay(200); 24868c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_MSK); 24878c2ecf20Sopenharmony_ci udelay(200); 24888c2ecf20Sopenharmony_ci 24898c2ecf20Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, val); 24908c2ecf20Sopenharmony_ci udelay(200); 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) { 24938c2ecf20Sopenharmony_ci /* now first reset HDR access counter */ 24948c2ecf20Sopenharmony_ci dummy = RGen(cinfo, VGA_PEL_IW); 24958c2ecf20Sopenharmony_ci udelay(200); 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci /* and at the end, restore the mask value */ 24988c2ecf20Sopenharmony_ci /* ## is this mask always 0xff? */ 24998c2ecf20Sopenharmony_ci WGen(cinfo, VGA_PEL_MSK, 0xff); 25008c2ecf20Sopenharmony_ci udelay(200); 25018c2ecf20Sopenharmony_ci } 25028c2ecf20Sopenharmony_ci} 25038c2ecf20Sopenharmony_ci 25048c2ecf20Sopenharmony_ci/*** WSFR() - write to the "special function register" (SFR) ***/ 25058c2ecf20Sopenharmony_cistatic void WSFR(struct cirrusfb_info *cinfo, unsigned char val) 25068c2ecf20Sopenharmony_ci{ 25078c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 25088c2ecf20Sopenharmony_ci assert(cinfo->regbase != NULL); 25098c2ecf20Sopenharmony_ci cinfo->SFR = val; 25108c2ecf20Sopenharmony_ci z_writeb(val, cinfo->regbase + 0x8000); 25118c2ecf20Sopenharmony_ci#endif 25128c2ecf20Sopenharmony_ci} 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci/* The Picasso has a second register for switching the monitor bit */ 25158c2ecf20Sopenharmony_cistatic void WSFR2(struct cirrusfb_info *cinfo, unsigned char val) 25168c2ecf20Sopenharmony_ci{ 25178c2ecf20Sopenharmony_ci#ifdef CONFIG_ZORRO 25188c2ecf20Sopenharmony_ci /* writing an arbitrary value to this one causes the monitor switcher */ 25198c2ecf20Sopenharmony_ci /* to flip to Amiga display */ 25208c2ecf20Sopenharmony_ci assert(cinfo->regbase != NULL); 25218c2ecf20Sopenharmony_ci cinfo->SFR = val; 25228c2ecf20Sopenharmony_ci z_writeb(val, cinfo->regbase + 0x9000); 25238c2ecf20Sopenharmony_ci#endif 25248c2ecf20Sopenharmony_ci} 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci/*** WClut - set CLUT entry (range: 0..63) ***/ 25278c2ecf20Sopenharmony_cistatic void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char red, 25288c2ecf20Sopenharmony_ci unsigned char green, unsigned char blue) 25298c2ecf20Sopenharmony_ci{ 25308c2ecf20Sopenharmony_ci unsigned int data = VGA_PEL_D; 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci /* address write mode register is not translated.. */ 25338c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, VGA_PEL_IW, regnum); 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 25368c2ecf20Sopenharmony_ci cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 || 25378c2ecf20Sopenharmony_ci cinfo->btype == BT_SD64 || is_laguna(cinfo)) { 25388c2ecf20Sopenharmony_ci /* but DAC data register IS, at least for Picasso II */ 25398c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) 25408c2ecf20Sopenharmony_ci data += 0xfff; 25418c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, red); 25428c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, green); 25438c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, blue); 25448c2ecf20Sopenharmony_ci } else { 25458c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, blue); 25468c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, green); 25478c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, data, red); 25488c2ecf20Sopenharmony_ci } 25498c2ecf20Sopenharmony_ci} 25508c2ecf20Sopenharmony_ci 25518c2ecf20Sopenharmony_ci#if 0 25528c2ecf20Sopenharmony_ci/*** RClut - read CLUT entry (range 0..63) ***/ 25538c2ecf20Sopenharmony_cistatic void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned char *red, 25548c2ecf20Sopenharmony_ci unsigned char *green, unsigned char *blue) 25558c2ecf20Sopenharmony_ci{ 25568c2ecf20Sopenharmony_ci unsigned int data = VGA_PEL_D; 25578c2ecf20Sopenharmony_ci 25588c2ecf20Sopenharmony_ci vga_w(cinfo->regbase, VGA_PEL_IR, regnum); 25598c2ecf20Sopenharmony_ci 25608c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || 25618c2ecf20Sopenharmony_ci cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) { 25628c2ecf20Sopenharmony_ci if (cinfo->btype == BT_PICASSO) 25638c2ecf20Sopenharmony_ci data += 0xfff; 25648c2ecf20Sopenharmony_ci *red = vga_r(cinfo->regbase, data); 25658c2ecf20Sopenharmony_ci *green = vga_r(cinfo->regbase, data); 25668c2ecf20Sopenharmony_ci *blue = vga_r(cinfo->regbase, data); 25678c2ecf20Sopenharmony_ci } else { 25688c2ecf20Sopenharmony_ci *blue = vga_r(cinfo->regbase, data); 25698c2ecf20Sopenharmony_ci *green = vga_r(cinfo->regbase, data); 25708c2ecf20Sopenharmony_ci *red = vga_r(cinfo->regbase, data); 25718c2ecf20Sopenharmony_ci } 25728c2ecf20Sopenharmony_ci} 25738c2ecf20Sopenharmony_ci#endif 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci/******************************************************************* 25768c2ecf20Sopenharmony_ci cirrusfb_WaitBLT() 25778c2ecf20Sopenharmony_ci 25788c2ecf20Sopenharmony_ci Wait for the BitBLT engine to complete a possible earlier job 25798c2ecf20Sopenharmony_ci*********************************************************************/ 25808c2ecf20Sopenharmony_ci 25818c2ecf20Sopenharmony_ci/* FIXME: use interrupts instead */ 25828c2ecf20Sopenharmony_cistatic void cirrusfb_WaitBLT(u8 __iomem *regbase) 25838c2ecf20Sopenharmony_ci{ 25848c2ecf20Sopenharmony_ci while (vga_rgfx(regbase, CL_GR31) & 0x08) 25858c2ecf20Sopenharmony_ci cpu_relax(); 25868c2ecf20Sopenharmony_ci} 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci/******************************************************************* 25898c2ecf20Sopenharmony_ci cirrusfb_BitBLT() 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci perform accelerated "scrolling" 25928c2ecf20Sopenharmony_ci********************************************************************/ 25938c2ecf20Sopenharmony_ci 25948c2ecf20Sopenharmony_cistatic void cirrusfb_set_blitter(u8 __iomem *regbase, 25958c2ecf20Sopenharmony_ci u_short nwidth, u_short nheight, 25968c2ecf20Sopenharmony_ci u_long nsrc, u_long ndest, 25978c2ecf20Sopenharmony_ci u_short bltmode, u_short line_length) 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_ci{ 26008c2ecf20Sopenharmony_ci /* pitch: set to line_length */ 26018c2ecf20Sopenharmony_ci /* dest pitch low */ 26028c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR24, line_length & 0xff); 26038c2ecf20Sopenharmony_ci /* dest pitch hi */ 26048c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR25, line_length >> 8); 26058c2ecf20Sopenharmony_ci /* source pitch low */ 26068c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR26, line_length & 0xff); 26078c2ecf20Sopenharmony_ci /* source pitch hi */ 26088c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR27, line_length >> 8); 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci /* BLT width: actual number of pixels - 1 */ 26118c2ecf20Sopenharmony_ci /* BLT width low */ 26128c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR20, nwidth & 0xff); 26138c2ecf20Sopenharmony_ci /* BLT width hi */ 26148c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR21, nwidth >> 8); 26158c2ecf20Sopenharmony_ci 26168c2ecf20Sopenharmony_ci /* BLT height: actual number of lines -1 */ 26178c2ecf20Sopenharmony_ci /* BLT height low */ 26188c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR22, nheight & 0xff); 26198c2ecf20Sopenharmony_ci /* BLT width hi */ 26208c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR23, nheight >> 8); 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci /* BLT destination */ 26238c2ecf20Sopenharmony_ci /* BLT dest low */ 26248c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff)); 26258c2ecf20Sopenharmony_ci /* BLT dest mid */ 26268c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8)); 26278c2ecf20Sopenharmony_ci /* BLT dest hi */ 26288c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16)); 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci /* BLT source */ 26318c2ecf20Sopenharmony_ci /* BLT src low */ 26328c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR2C, (u_char) (nsrc & 0xff)); 26338c2ecf20Sopenharmony_ci /* BLT src mid */ 26348c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR2D, (u_char) (nsrc >> 8)); 26358c2ecf20Sopenharmony_ci /* BLT src hi */ 26368c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR2E, (u_char) (nsrc >> 16)); 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci /* BLT mode */ 26398c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR30, bltmode); /* BLT mode */ 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_ci /* BLT ROP: SrcCopy */ 26428c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ 26438c2ecf20Sopenharmony_ci 26448c2ecf20Sopenharmony_ci /* and finally: GO! */ 26458c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ 26468c2ecf20Sopenharmony_ci} 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci/******************************************************************* 26498c2ecf20Sopenharmony_ci cirrusfb_BitBLT() 26508c2ecf20Sopenharmony_ci 26518c2ecf20Sopenharmony_ci perform accelerated "scrolling" 26528c2ecf20Sopenharmony_ci********************************************************************/ 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_cistatic void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, 26558c2ecf20Sopenharmony_ci u_short curx, u_short cury, 26568c2ecf20Sopenharmony_ci u_short destx, u_short desty, 26578c2ecf20Sopenharmony_ci u_short width, u_short height, 26588c2ecf20Sopenharmony_ci u_short line_length) 26598c2ecf20Sopenharmony_ci{ 26608c2ecf20Sopenharmony_ci u_short nwidth = width - 1; 26618c2ecf20Sopenharmony_ci u_short nheight = height - 1; 26628c2ecf20Sopenharmony_ci u_long nsrc, ndest; 26638c2ecf20Sopenharmony_ci u_char bltmode; 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_ci bltmode = 0x00; 26668c2ecf20Sopenharmony_ci /* if source adr < dest addr, do the Blt backwards */ 26678c2ecf20Sopenharmony_ci if (cury <= desty) { 26688c2ecf20Sopenharmony_ci if (cury == desty) { 26698c2ecf20Sopenharmony_ci /* if src and dest are on the same line, check x */ 26708c2ecf20Sopenharmony_ci if (curx < destx) 26718c2ecf20Sopenharmony_ci bltmode |= 0x01; 26728c2ecf20Sopenharmony_ci } else 26738c2ecf20Sopenharmony_ci bltmode |= 0x01; 26748c2ecf20Sopenharmony_ci } 26758c2ecf20Sopenharmony_ci /* standard case: forward blitting */ 26768c2ecf20Sopenharmony_ci nsrc = (cury * line_length) + curx; 26778c2ecf20Sopenharmony_ci ndest = (desty * line_length) + destx; 26788c2ecf20Sopenharmony_ci if (bltmode) { 26798c2ecf20Sopenharmony_ci /* this means start addresses are at the end, 26808c2ecf20Sopenharmony_ci * counting backwards 26818c2ecf20Sopenharmony_ci */ 26828c2ecf20Sopenharmony_ci nsrc += nheight * line_length + nwidth; 26838c2ecf20Sopenharmony_ci ndest += nheight * line_length + nwidth; 26848c2ecf20Sopenharmony_ci } 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ci cirrusfb_WaitBLT(regbase); 26878c2ecf20Sopenharmony_ci 26888c2ecf20Sopenharmony_ci cirrusfb_set_blitter(regbase, nwidth, nheight, 26898c2ecf20Sopenharmony_ci nsrc, ndest, bltmode, line_length); 26908c2ecf20Sopenharmony_ci} 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci/******************************************************************* 26938c2ecf20Sopenharmony_ci cirrusfb_RectFill() 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci perform accelerated rectangle fill 26968c2ecf20Sopenharmony_ci********************************************************************/ 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_cistatic void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, 26998c2ecf20Sopenharmony_ci u_short x, u_short y, u_short width, u_short height, 27008c2ecf20Sopenharmony_ci u32 fg_color, u32 bg_color, u_short line_length, 27018c2ecf20Sopenharmony_ci u_char blitmode) 27028c2ecf20Sopenharmony_ci{ 27038c2ecf20Sopenharmony_ci u_long ndest = (y * line_length) + x; 27048c2ecf20Sopenharmony_ci u_char op; 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci cirrusfb_WaitBLT(regbase); 27078c2ecf20Sopenharmony_ci 27088c2ecf20Sopenharmony_ci /* This is a ColorExpand Blt, using the */ 27098c2ecf20Sopenharmony_ci /* same color for foreground and background */ 27108c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color); 27118c2ecf20Sopenharmony_ci vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color); 27128c2ecf20Sopenharmony_ci 27138c2ecf20Sopenharmony_ci op = 0x80; 27148c2ecf20Sopenharmony_ci if (bits_per_pixel >= 16) { 27158c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR10, bg_color >> 8); 27168c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR11, fg_color >> 8); 27178c2ecf20Sopenharmony_ci op = 0x90; 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci if (bits_per_pixel >= 24) { 27208c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR12, bg_color >> 16); 27218c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR13, fg_color >> 16); 27228c2ecf20Sopenharmony_ci op = 0xa0; 27238c2ecf20Sopenharmony_ci } 27248c2ecf20Sopenharmony_ci if (bits_per_pixel == 32) { 27258c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR14, bg_color >> 24); 27268c2ecf20Sopenharmony_ci vga_wgfx(regbase, CL_GR15, fg_color >> 24); 27278c2ecf20Sopenharmony_ci op = 0xb0; 27288c2ecf20Sopenharmony_ci } 27298c2ecf20Sopenharmony_ci cirrusfb_set_blitter(regbase, width - 1, height - 1, 27308c2ecf20Sopenharmony_ci 0, ndest, op | blitmode, line_length); 27318c2ecf20Sopenharmony_ci} 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci/************************************************************************** 27348c2ecf20Sopenharmony_ci * bestclock() - determine closest possible clock lower(?) than the 27358c2ecf20Sopenharmony_ci * desired pixel clock 27368c2ecf20Sopenharmony_ci **************************************************************************/ 27378c2ecf20Sopenharmony_cistatic void bestclock(long freq, int *nom, int *den, int *div) 27388c2ecf20Sopenharmony_ci{ 27398c2ecf20Sopenharmony_ci int n, d; 27408c2ecf20Sopenharmony_ci long h, diff; 27418c2ecf20Sopenharmony_ci 27428c2ecf20Sopenharmony_ci assert(nom != NULL); 27438c2ecf20Sopenharmony_ci assert(den != NULL); 27448c2ecf20Sopenharmony_ci assert(div != NULL); 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci *nom = 0; 27478c2ecf20Sopenharmony_ci *den = 0; 27488c2ecf20Sopenharmony_ci *div = 0; 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci if (freq < 8000) 27518c2ecf20Sopenharmony_ci freq = 8000; 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci diff = freq; 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci for (n = 32; n < 128; n++) { 27568c2ecf20Sopenharmony_ci int s = 0; 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci d = (14318 * n) / freq; 27598c2ecf20Sopenharmony_ci if ((d >= 7) && (d <= 63)) { 27608c2ecf20Sopenharmony_ci int temp = d; 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci if (temp > 31) { 27638c2ecf20Sopenharmony_ci s = 1; 27648c2ecf20Sopenharmony_ci temp >>= 1; 27658c2ecf20Sopenharmony_ci } 27668c2ecf20Sopenharmony_ci h = ((14318 * n) / temp) >> s; 27678c2ecf20Sopenharmony_ci h = h > freq ? h - freq : freq - h; 27688c2ecf20Sopenharmony_ci if (h < diff) { 27698c2ecf20Sopenharmony_ci diff = h; 27708c2ecf20Sopenharmony_ci *nom = n; 27718c2ecf20Sopenharmony_ci *den = temp; 27728c2ecf20Sopenharmony_ci *div = s; 27738c2ecf20Sopenharmony_ci } 27748c2ecf20Sopenharmony_ci } 27758c2ecf20Sopenharmony_ci d++; 27768c2ecf20Sopenharmony_ci if ((d >= 7) && (d <= 63)) { 27778c2ecf20Sopenharmony_ci if (d > 31) { 27788c2ecf20Sopenharmony_ci s = 1; 27798c2ecf20Sopenharmony_ci d >>= 1; 27808c2ecf20Sopenharmony_ci } 27818c2ecf20Sopenharmony_ci h = ((14318 * n) / d) >> s; 27828c2ecf20Sopenharmony_ci h = h > freq ? h - freq : freq - h; 27838c2ecf20Sopenharmony_ci if (h < diff) { 27848c2ecf20Sopenharmony_ci diff = h; 27858c2ecf20Sopenharmony_ci *nom = n; 27868c2ecf20Sopenharmony_ci *den = d; 27878c2ecf20Sopenharmony_ci *div = s; 27888c2ecf20Sopenharmony_ci } 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci} 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci/* ------------------------------------------------------------------------- 27948c2ecf20Sopenharmony_ci * 27958c2ecf20Sopenharmony_ci * debugging functions 27968c2ecf20Sopenharmony_ci * 27978c2ecf20Sopenharmony_ci * ------------------------------------------------------------------------- 27988c2ecf20Sopenharmony_ci */ 27998c2ecf20Sopenharmony_ci 28008c2ecf20Sopenharmony_ci#ifdef CIRRUSFB_DEBUG 28018c2ecf20Sopenharmony_ci 28028c2ecf20Sopenharmony_ci/** 28038c2ecf20Sopenharmony_ci * cirrusfb_dbg_print_regs 28048c2ecf20Sopenharmony_ci * @base: If using newmmio, the newmmio base address, otherwise %NULL 28058c2ecf20Sopenharmony_ci * @reg_class: type of registers to read: %CRT, or %SEQ 28068c2ecf20Sopenharmony_ci * 28078c2ecf20Sopenharmony_ci * DESCRIPTION: 28088c2ecf20Sopenharmony_ci * Dumps the given list of VGA CRTC registers. If @base is %NULL, 28098c2ecf20Sopenharmony_ci * old-style I/O ports are queried for information, otherwise MMIO is 28108c2ecf20Sopenharmony_ci * used at the given @base address to query the information. 28118c2ecf20Sopenharmony_ci */ 28128c2ecf20Sopenharmony_ci 28138c2ecf20Sopenharmony_cistatic void cirrusfb_dbg_print_regs(struct fb_info *info, 28148c2ecf20Sopenharmony_ci caddr_t regbase, 28158c2ecf20Sopenharmony_ci enum cirrusfb_dbg_reg_class reg_class, ...) 28168c2ecf20Sopenharmony_ci{ 28178c2ecf20Sopenharmony_ci va_list list; 28188c2ecf20Sopenharmony_ci unsigned char val = 0; 28198c2ecf20Sopenharmony_ci unsigned reg; 28208c2ecf20Sopenharmony_ci char *name; 28218c2ecf20Sopenharmony_ci 28228c2ecf20Sopenharmony_ci va_start(list, reg_class); 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci name = va_arg(list, char *); 28258c2ecf20Sopenharmony_ci while (name != NULL) { 28268c2ecf20Sopenharmony_ci reg = va_arg(list, int); 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci switch (reg_class) { 28298c2ecf20Sopenharmony_ci case CRT: 28308c2ecf20Sopenharmony_ci val = vga_rcrt(regbase, (unsigned char) reg); 28318c2ecf20Sopenharmony_ci break; 28328c2ecf20Sopenharmony_ci case SEQ: 28338c2ecf20Sopenharmony_ci val = vga_rseq(regbase, (unsigned char) reg); 28348c2ecf20Sopenharmony_ci break; 28358c2ecf20Sopenharmony_ci default: 28368c2ecf20Sopenharmony_ci /* should never occur */ 28378c2ecf20Sopenharmony_ci assert(false); 28388c2ecf20Sopenharmony_ci break; 28398c2ecf20Sopenharmony_ci } 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_ci dev_dbg(info->device, "%8s = 0x%02X\n", name, val); 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci name = va_arg(list, char *); 28448c2ecf20Sopenharmony_ci } 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_ci va_end(list); 28478c2ecf20Sopenharmony_ci} 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ci/** 28508c2ecf20Sopenharmony_ci * cirrusfb_dbg_reg_dump 28518c2ecf20Sopenharmony_ci * @base: If using newmmio, the newmmio base address, otherwise %NULL 28528c2ecf20Sopenharmony_ci * 28538c2ecf20Sopenharmony_ci * DESCRIPTION: 28548c2ecf20Sopenharmony_ci * Dumps a list of interesting VGA and CIRRUSFB registers. If @base is %NULL, 28558c2ecf20Sopenharmony_ci * old-style I/O ports are queried for information, otherwise MMIO is 28568c2ecf20Sopenharmony_ci * used at the given @base address to query the information. 28578c2ecf20Sopenharmony_ci */ 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_cistatic void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase) 28608c2ecf20Sopenharmony_ci{ 28618c2ecf20Sopenharmony_ci dev_dbg(info->device, "VGA CRTC register dump:\n"); 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci cirrusfb_dbg_print_regs(info, regbase, CRT, 28648c2ecf20Sopenharmony_ci "CR00", 0x00, 28658c2ecf20Sopenharmony_ci "CR01", 0x01, 28668c2ecf20Sopenharmony_ci "CR02", 0x02, 28678c2ecf20Sopenharmony_ci "CR03", 0x03, 28688c2ecf20Sopenharmony_ci "CR04", 0x04, 28698c2ecf20Sopenharmony_ci "CR05", 0x05, 28708c2ecf20Sopenharmony_ci "CR06", 0x06, 28718c2ecf20Sopenharmony_ci "CR07", 0x07, 28728c2ecf20Sopenharmony_ci "CR08", 0x08, 28738c2ecf20Sopenharmony_ci "CR09", 0x09, 28748c2ecf20Sopenharmony_ci "CR0A", 0x0A, 28758c2ecf20Sopenharmony_ci "CR0B", 0x0B, 28768c2ecf20Sopenharmony_ci "CR0C", 0x0C, 28778c2ecf20Sopenharmony_ci "CR0D", 0x0D, 28788c2ecf20Sopenharmony_ci "CR0E", 0x0E, 28798c2ecf20Sopenharmony_ci "CR0F", 0x0F, 28808c2ecf20Sopenharmony_ci "CR10", 0x10, 28818c2ecf20Sopenharmony_ci "CR11", 0x11, 28828c2ecf20Sopenharmony_ci "CR12", 0x12, 28838c2ecf20Sopenharmony_ci "CR13", 0x13, 28848c2ecf20Sopenharmony_ci "CR14", 0x14, 28858c2ecf20Sopenharmony_ci "CR15", 0x15, 28868c2ecf20Sopenharmony_ci "CR16", 0x16, 28878c2ecf20Sopenharmony_ci "CR17", 0x17, 28888c2ecf20Sopenharmony_ci "CR18", 0x18, 28898c2ecf20Sopenharmony_ci "CR22", 0x22, 28908c2ecf20Sopenharmony_ci "CR24", 0x24, 28918c2ecf20Sopenharmony_ci "CR26", 0x26, 28928c2ecf20Sopenharmony_ci "CR2D", 0x2D, 28938c2ecf20Sopenharmony_ci "CR2E", 0x2E, 28948c2ecf20Sopenharmony_ci "CR2F", 0x2F, 28958c2ecf20Sopenharmony_ci "CR30", 0x30, 28968c2ecf20Sopenharmony_ci "CR31", 0x31, 28978c2ecf20Sopenharmony_ci "CR32", 0x32, 28988c2ecf20Sopenharmony_ci "CR33", 0x33, 28998c2ecf20Sopenharmony_ci "CR34", 0x34, 29008c2ecf20Sopenharmony_ci "CR35", 0x35, 29018c2ecf20Sopenharmony_ci "CR36", 0x36, 29028c2ecf20Sopenharmony_ci "CR37", 0x37, 29038c2ecf20Sopenharmony_ci "CR38", 0x38, 29048c2ecf20Sopenharmony_ci "CR39", 0x39, 29058c2ecf20Sopenharmony_ci "CR3A", 0x3A, 29068c2ecf20Sopenharmony_ci "CR3B", 0x3B, 29078c2ecf20Sopenharmony_ci "CR3C", 0x3C, 29088c2ecf20Sopenharmony_ci "CR3D", 0x3D, 29098c2ecf20Sopenharmony_ci "CR3E", 0x3E, 29108c2ecf20Sopenharmony_ci "CR3F", 0x3F, 29118c2ecf20Sopenharmony_ci NULL); 29128c2ecf20Sopenharmony_ci 29138c2ecf20Sopenharmony_ci dev_dbg(info->device, "\n"); 29148c2ecf20Sopenharmony_ci 29158c2ecf20Sopenharmony_ci dev_dbg(info->device, "VGA SEQ register dump:\n"); 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci cirrusfb_dbg_print_regs(info, regbase, SEQ, 29188c2ecf20Sopenharmony_ci "SR00", 0x00, 29198c2ecf20Sopenharmony_ci "SR01", 0x01, 29208c2ecf20Sopenharmony_ci "SR02", 0x02, 29218c2ecf20Sopenharmony_ci "SR03", 0x03, 29228c2ecf20Sopenharmony_ci "SR04", 0x04, 29238c2ecf20Sopenharmony_ci "SR08", 0x08, 29248c2ecf20Sopenharmony_ci "SR09", 0x09, 29258c2ecf20Sopenharmony_ci "SR0A", 0x0A, 29268c2ecf20Sopenharmony_ci "SR0B", 0x0B, 29278c2ecf20Sopenharmony_ci "SR0D", 0x0D, 29288c2ecf20Sopenharmony_ci "SR10", 0x10, 29298c2ecf20Sopenharmony_ci "SR11", 0x11, 29308c2ecf20Sopenharmony_ci "SR12", 0x12, 29318c2ecf20Sopenharmony_ci "SR13", 0x13, 29328c2ecf20Sopenharmony_ci "SR14", 0x14, 29338c2ecf20Sopenharmony_ci "SR15", 0x15, 29348c2ecf20Sopenharmony_ci "SR16", 0x16, 29358c2ecf20Sopenharmony_ci "SR17", 0x17, 29368c2ecf20Sopenharmony_ci "SR18", 0x18, 29378c2ecf20Sopenharmony_ci "SR19", 0x19, 29388c2ecf20Sopenharmony_ci "SR1A", 0x1A, 29398c2ecf20Sopenharmony_ci "SR1B", 0x1B, 29408c2ecf20Sopenharmony_ci "SR1C", 0x1C, 29418c2ecf20Sopenharmony_ci "SR1D", 0x1D, 29428c2ecf20Sopenharmony_ci "SR1E", 0x1E, 29438c2ecf20Sopenharmony_ci "SR1F", 0x1F, 29448c2ecf20Sopenharmony_ci NULL); 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_ci dev_dbg(info->device, "\n"); 29478c2ecf20Sopenharmony_ci} 29488c2ecf20Sopenharmony_ci 29498c2ecf20Sopenharmony_ci#endif /* CIRRUSFB_DEBUG */ 29508c2ecf20Sopenharmony_ci 2951