18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/drivers/video/maxinefb.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * DECstation 5000/xx onboard framebuffer support ... derived from: 58c2ecf20Sopenharmony_ci * "HP300 Topcat framebuffer support (derived from macfb of all things) 68c2ecf20Sopenharmony_ci * Phil Blundell <philb@gnu.org> 1998", the original code can be 78c2ecf20Sopenharmony_ci * found in the file hpfb.c in the same directory. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * DECstation related code Copyright (C) 1999,2000,2001 by 108c2ecf20Sopenharmony_ci * Michael Engel <engel@unix-ag.org> and 118c2ecf20Sopenharmony_ci * Karsten Merker <merker@linuxtag.org>. 128c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General 138c2ecf20Sopenharmony_ci * Public License. See the file COPYING in the main directory of this 148c2ecf20Sopenharmony_ci * archive for more details. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/* 198c2ecf20Sopenharmony_ci * Changes: 208c2ecf20Sopenharmony_ci * 2001/01/27 removed debugging and testing code, fixed fb_ops 218c2ecf20Sopenharmony_ci * initialization which had caused a crash before, 228c2ecf20Sopenharmony_ci * general cleanup, first official release (KM) 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/module.h> 278c2ecf20Sopenharmony_ci#include <linux/kernel.h> 288c2ecf20Sopenharmony_ci#include <linux/errno.h> 298c2ecf20Sopenharmony_ci#include <linux/string.h> 308c2ecf20Sopenharmony_ci#include <linux/mm.h> 318c2ecf20Sopenharmony_ci#include <linux/delay.h> 328c2ecf20Sopenharmony_ci#include <linux/init.h> 338c2ecf20Sopenharmony_ci#include <linux/fb.h> 348c2ecf20Sopenharmony_ci#include <video/maxinefb.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* bootinfo.h defines the machine type values, needed when checking */ 378c2ecf20Sopenharmony_ci/* whether are really running on a maxine, KM */ 388c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_cistatic struct fb_info fb_info; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic const struct fb_var_screeninfo maxinefb_defined = { 438c2ecf20Sopenharmony_ci .xres = 1024, 448c2ecf20Sopenharmony_ci .yres = 768, 458c2ecf20Sopenharmony_ci .xres_virtual = 1024, 468c2ecf20Sopenharmony_ci .yres_virtual = 768, 478c2ecf20Sopenharmony_ci .bits_per_pixel =8, 488c2ecf20Sopenharmony_ci .activate = FB_ACTIVATE_NOW, 498c2ecf20Sopenharmony_ci .height = -1, 508c2ecf20Sopenharmony_ci .width = -1, 518c2ecf20Sopenharmony_ci .vmode = FB_VMODE_NONINTERLACED, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic struct fb_fix_screeninfo maxinefb_fix __initdata = { 558c2ecf20Sopenharmony_ci .id = "Maxine", 568c2ecf20Sopenharmony_ci .smem_len = (1024*768), 578c2ecf20Sopenharmony_ci .type = FB_TYPE_PACKED_PIXELS, 588c2ecf20Sopenharmony_ci .visual = FB_VISUAL_PSEUDOCOLOR, 598c2ecf20Sopenharmony_ci .line_length = 1024, 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* Handle the funny Inmos RamDAC/video controller ... */ 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_civoid maxinefb_ims332_write_register(int regno, register unsigned int val) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS; 678c2ecf20Sopenharmony_ci unsigned char *wptr; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci wptr = regs + 0xa0000 + (regno << 4); 708c2ecf20Sopenharmony_ci *((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00; 718c2ecf20Sopenharmony_ci *((volatile unsigned short *) (wptr)) = val; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ciunsigned int maxinefb_ims332_read_register(int regno) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS; 778c2ecf20Sopenharmony_ci unsigned char *rptr; 788c2ecf20Sopenharmony_ci register unsigned int j, k; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci rptr = regs + 0x80000 + (regno << 4); 818c2ecf20Sopenharmony_ci j = *((volatile unsigned short *) rptr); 828c2ecf20Sopenharmony_ci k = *((volatile unsigned short *) regs); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return (j & 0xffff) | ((k & 0xff00) << 8); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* Set the palette */ 888c2ecf20Sopenharmony_cistatic int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green, 898c2ecf20Sopenharmony_ci unsigned blue, unsigned transp, struct fb_info *info) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci /* value to be written into the palette reg. */ 928c2ecf20Sopenharmony_ci unsigned long hw_colorvalue = 0; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (regno > 255) 958c2ecf20Sopenharmony_ci return 1; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci red >>= 8; /* The cmap fields are 16 bits */ 988c2ecf20Sopenharmony_ci green >>= 8; /* wide, but the harware colormap */ 998c2ecf20Sopenharmony_ci blue >>= 8; /* registers are only 8 bits wide */ 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci hw_colorvalue = (blue << 16) + (green << 8) + (red); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + regno, 1048c2ecf20Sopenharmony_ci hw_colorvalue); 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic const struct fb_ops maxinefb_ops = { 1098c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1108c2ecf20Sopenharmony_ci .fb_setcolreg = maxinefb_setcolreg, 1118c2ecf20Sopenharmony_ci .fb_fillrect = cfb_fillrect, 1128c2ecf20Sopenharmony_ci .fb_copyarea = cfb_copyarea, 1138c2ecf20Sopenharmony_ci .fb_imageblit = cfb_imageblit, 1148c2ecf20Sopenharmony_ci}; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciint __init maxinefb_init(void) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci unsigned long fboff; 1198c2ecf20Sopenharmony_ci unsigned long fb_start; 1208c2ecf20Sopenharmony_ci int i; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (fb_get_options("maxinefb", NULL)) 1238c2ecf20Sopenharmony_ci return -ENODEV; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci /* Validate we're on the proper machine type */ 1268c2ecf20Sopenharmony_ci if (mips_machtype != MACH_DS5000_XX) { 1278c2ecf20Sopenharmony_ci return -EINVAL; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci printk(KERN_INFO "Maxinefb: Personal DECstation detected\n"); 1318c2ecf20Sopenharmony_ci printk(KERN_INFO "Maxinefb: initializing onboard framebuffer\n"); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* Framebuffer display memory base address */ 1348c2ecf20Sopenharmony_ci fb_start = DS5000_xx_ONBOARD_FBMEM_START; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* Clear screen */ 1378c2ecf20Sopenharmony_ci for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++) 1388c2ecf20Sopenharmony_ci *(volatile unsigned char *)fboff = 0x0; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci maxinefb_fix.smem_start = fb_start; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* erase hardware cursor */ 1438c2ecf20Sopenharmony_ci for (i = 0; i < 512; i++) { 1448c2ecf20Sopenharmony_ci maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i, 1458c2ecf20Sopenharmony_ci 0); 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci if (i&0x8 == 0) 1488c2ecf20Sopenharmony_ci maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0x0f); 1498c2ecf20Sopenharmony_ci else 1508c2ecf20Sopenharmony_ci maxinefb_ims332_write_register (IMS332_REG_CURSOR_RAM + i, 0xf0); 1518c2ecf20Sopenharmony_ci */ 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci fb_info.fbops = &maxinefb_ops; 1558c2ecf20Sopenharmony_ci fb_info.screen_base = (char *)maxinefb_fix.smem_start; 1568c2ecf20Sopenharmony_ci fb_info.var = maxinefb_defined; 1578c2ecf20Sopenharmony_ci fb_info.fix = maxinefb_fix; 1588c2ecf20Sopenharmony_ci fb_info.flags = FBINFO_DEFAULT; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci fb_alloc_cmap(&fb_info.cmap, 256, 0); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (register_framebuffer(&fb_info) < 0) 1638c2ecf20Sopenharmony_ci return 1; 1648c2ecf20Sopenharmony_ci return 0; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistatic void __exit maxinefb_exit(void) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci unregister_framebuffer(&fb_info); 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci#ifdef MODULE 1738c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1748c2ecf20Sopenharmony_ci#endif 1758c2ecf20Sopenharmony_cimodule_init(maxinefb_init); 1768c2ecf20Sopenharmony_cimodule_exit(maxinefb_exit); 1778c2ecf20Sopenharmony_ci 178