0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <linux/module.h>
0027 #include <linux/kernel.h>
0028 #include <linux/errno.h>
0029 #include <linux/string.h>
0030 #include <linux/mm.h>
0031 #include <linux/delay.h>
0032 #include <linux/init.h>
0033 #include <linux/fb.h>
0034 #include <video/maxinefb.h>
0035
0036
0037
0038 #include <asm/bootinfo.h>
0039
0040 static struct fb_info fb_info;
0041
0042 static const struct fb_var_screeninfo maxinefb_defined = {
0043 .xres = 1024,
0044 .yres = 768,
0045 .xres_virtual = 1024,
0046 .yres_virtual = 768,
0047 .bits_per_pixel =8,
0048 .activate = FB_ACTIVATE_NOW,
0049 .height = -1,
0050 .width = -1,
0051 .vmode = FB_VMODE_NONINTERLACED,
0052 };
0053
0054 static struct fb_fix_screeninfo maxinefb_fix __initdata = {
0055 .id = "Maxine",
0056 .smem_len = (1024*768),
0057 .type = FB_TYPE_PACKED_PIXELS,
0058 .visual = FB_VISUAL_PSEUDOCOLOR,
0059 .line_length = 1024,
0060 };
0061
0062
0063
0064 void maxinefb_ims332_write_register(int regno, register unsigned int val)
0065 {
0066 register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
0067 unsigned char *wptr;
0068
0069 wptr = regs + 0xa0000 + (regno << 4);
0070 *((volatile unsigned int *) (regs)) = (val >> 8) & 0xff00;
0071 *((volatile unsigned short *) (wptr)) = val;
0072 }
0073
0074 unsigned int maxinefb_ims332_read_register(int regno)
0075 {
0076 register unsigned char *regs = (char *) MAXINEFB_IMS332_ADDRESS;
0077 unsigned char *rptr;
0078 register unsigned int j, k;
0079
0080 rptr = regs + 0x80000 + (regno << 4);
0081 j = *((volatile unsigned short *) rptr);
0082 k = *((volatile unsigned short *) regs);
0083
0084 return (j & 0xffff) | ((k & 0xff00) << 8);
0085 }
0086
0087
0088 static int maxinefb_setcolreg(unsigned regno, unsigned red, unsigned green,
0089 unsigned blue, unsigned transp, struct fb_info *info)
0090 {
0091
0092 unsigned long hw_colorvalue = 0;
0093
0094 if (regno > 255)
0095 return 1;
0096
0097 red >>= 8;
0098 green >>= 8;
0099 blue >>= 8;
0100
0101 hw_colorvalue = (blue << 16) + (green << 8) + (red);
0102
0103 maxinefb_ims332_write_register(IMS332_REG_COLOR_PALETTE + regno,
0104 hw_colorvalue);
0105 return 0;
0106 }
0107
0108 static const struct fb_ops maxinefb_ops = {
0109 .owner = THIS_MODULE,
0110 .fb_setcolreg = maxinefb_setcolreg,
0111 .fb_fillrect = cfb_fillrect,
0112 .fb_copyarea = cfb_copyarea,
0113 .fb_imageblit = cfb_imageblit,
0114 };
0115
0116 int __init maxinefb_init(void)
0117 {
0118 unsigned long fboff;
0119 unsigned long fb_start;
0120 int i;
0121
0122 if (fb_get_options("maxinefb", NULL))
0123 return -ENODEV;
0124
0125
0126 if (mips_machtype != MACH_DS5000_XX) {
0127 return -EINVAL;
0128 }
0129
0130 printk(KERN_INFO "Maxinefb: Personal DECstation detected\n");
0131 printk(KERN_INFO "Maxinefb: initializing onboard framebuffer\n");
0132
0133
0134 fb_start = DS5000_xx_ONBOARD_FBMEM_START;
0135
0136
0137 for (fboff = fb_start; fboff < fb_start + 0x1ffff; fboff++)
0138 *(volatile unsigned char *)fboff = 0x0;
0139
0140 maxinefb_fix.smem_start = fb_start;
0141
0142
0143 for (i = 0; i < 512; i++) {
0144 maxinefb_ims332_write_register(IMS332_REG_CURSOR_RAM + i,
0145 0);
0146
0147
0148
0149
0150
0151
0152 }
0153
0154 fb_info.fbops = &maxinefb_ops;
0155 fb_info.screen_base = (char *)maxinefb_fix.smem_start;
0156 fb_info.var = maxinefb_defined;
0157 fb_info.fix = maxinefb_fix;
0158 fb_info.flags = FBINFO_DEFAULT;
0159
0160 fb_alloc_cmap(&fb_info.cmap, 256, 0);
0161
0162 if (register_framebuffer(&fb_info) < 0)
0163 return 1;
0164 return 0;
0165 }
0166
0167 static void __exit maxinefb_exit(void)
0168 {
0169 unregister_framebuffer(&fb_info);
0170 }
0171
0172 #ifdef MODULE
0173 MODULE_LICENSE("GPL");
0174 #endif
0175 module_init(maxinefb_init);
0176 module_exit(maxinefb_exit);
0177