1f7018c21STomi Valkeinen /* 2f7018c21STomi Valkeinen * linux/drivers/video/q40fb.c -- Q40 frame buffer device 3f7018c21STomi Valkeinen * 4f7018c21STomi Valkeinen * Copyright (C) 2001 5f7018c21STomi Valkeinen * 6f7018c21STomi Valkeinen * Richard Zidlicky <rz@linux-m68k.org> 7f7018c21STomi Valkeinen * 8f7018c21STomi Valkeinen * This file is subject to the terms and conditions of the GNU General Public 9f7018c21STomi Valkeinen * License. See the file COPYING in the main directory of this archive for 10f7018c21STomi Valkeinen * more details. 11f7018c21STomi Valkeinen */ 12f7018c21STomi Valkeinen 13f7018c21STomi Valkeinen #include <linux/kernel.h> 14f7018c21STomi Valkeinen #include <linux/errno.h> 15f7018c21STomi Valkeinen #include <linux/string.h> 16f7018c21STomi Valkeinen #include <linux/mm.h> 17f7018c21STomi Valkeinen #include <linux/delay.h> 18f7018c21STomi Valkeinen #include <linux/interrupt.h> 19f7018c21STomi Valkeinen #include <linux/platform_device.h> 20f7018c21STomi Valkeinen 217c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 22f7018c21STomi Valkeinen #include <asm/setup.h> 23f7018c21STomi Valkeinen #include <asm/q40_master.h> 24f7018c21STomi Valkeinen #include <linux/fb.h> 25f7018c21STomi Valkeinen #include <linux/module.h> 26f7018c21STomi Valkeinen #include <asm/pgtable.h> 27f7018c21STomi Valkeinen 28f7018c21STomi Valkeinen #define Q40_PHYS_SCREEN_ADDR 0xFE800000 29f7018c21STomi Valkeinen 30f7018c21STomi Valkeinen static struct fb_fix_screeninfo q40fb_fix = { 31f7018c21STomi Valkeinen .id = "Q40", 32f7018c21STomi Valkeinen .smem_len = 1024*1024, 33f7018c21STomi Valkeinen .type = FB_TYPE_PACKED_PIXELS, 34f7018c21STomi Valkeinen .visual = FB_VISUAL_TRUECOLOR, 35f7018c21STomi Valkeinen .line_length = 1024*2, 36f7018c21STomi Valkeinen .accel = FB_ACCEL_NONE, 37f7018c21STomi Valkeinen }; 38f7018c21STomi Valkeinen 39a7582733SBhumika Goyal static const struct fb_var_screeninfo q40fb_var = { 40f7018c21STomi Valkeinen .xres = 1024, 41f7018c21STomi Valkeinen .yres = 512, 42f7018c21STomi Valkeinen .xres_virtual = 1024, 43f7018c21STomi Valkeinen .yres_virtual = 512, 44f7018c21STomi Valkeinen .bits_per_pixel = 16, 45f7018c21STomi Valkeinen .red = {6, 5, 0}, 46f7018c21STomi Valkeinen .green = {11, 5, 0}, 47f7018c21STomi Valkeinen .blue = {0, 6, 0}, 48f7018c21STomi Valkeinen .activate = FB_ACTIVATE_NOW, 49f7018c21STomi Valkeinen .height = 230, 50f7018c21STomi Valkeinen .width = 300, 51f7018c21STomi Valkeinen .vmode = FB_VMODE_NONINTERLACED, 52f7018c21STomi Valkeinen }; 53f7018c21STomi Valkeinen 54f7018c21STomi Valkeinen static int q40fb_setcolreg(unsigned regno, unsigned red, unsigned green, 55f7018c21STomi Valkeinen unsigned blue, unsigned transp, 56f7018c21STomi Valkeinen struct fb_info *info) 57f7018c21STomi Valkeinen { 58f7018c21STomi Valkeinen /* 59f7018c21STomi Valkeinen * Set a single color register. The values supplied have a 16 bit 60f7018c21STomi Valkeinen * magnitude. 61f7018c21STomi Valkeinen * Return != 0 for invalid regno. 62f7018c21STomi Valkeinen */ 63f7018c21STomi Valkeinen 64f7018c21STomi Valkeinen if (regno > 255) 65f7018c21STomi Valkeinen return 1; 66f7018c21STomi Valkeinen red>>=11; 67f7018c21STomi Valkeinen green>>=11; 68f7018c21STomi Valkeinen blue>>=10; 69f7018c21STomi Valkeinen 70f7018c21STomi Valkeinen if (regno < 16) { 71f7018c21STomi Valkeinen ((u32 *)info->pseudo_palette)[regno] = ((red & 31) <<6) | 72f7018c21STomi Valkeinen ((green & 31) << 11) | 73f7018c21STomi Valkeinen (blue & 63); 74f7018c21STomi Valkeinen } 75f7018c21STomi Valkeinen return 0; 76f7018c21STomi Valkeinen } 77f7018c21STomi Valkeinen 788a48ac33SJani Nikula static const struct fb_ops q40fb_ops = { 79f7018c21STomi Valkeinen .owner = THIS_MODULE, 80f7018c21STomi Valkeinen .fb_setcolreg = q40fb_setcolreg, 81f7018c21STomi Valkeinen .fb_fillrect = cfb_fillrect, 82f7018c21STomi Valkeinen .fb_copyarea = cfb_copyarea, 83f7018c21STomi Valkeinen .fb_imageblit = cfb_imageblit, 84f7018c21STomi Valkeinen }; 85f7018c21STomi Valkeinen 86f7018c21STomi Valkeinen static int q40fb_probe(struct platform_device *dev) 87f7018c21STomi Valkeinen { 88f7018c21STomi Valkeinen struct fb_info *info; 89f7018c21STomi Valkeinen 90f7018c21STomi Valkeinen if (!MACH_IS_Q40) 91f7018c21STomi Valkeinen return -ENXIO; 92f7018c21STomi Valkeinen 93f7018c21STomi Valkeinen /* mapped in q40/config.c */ 94f7018c21STomi Valkeinen q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR; 95f7018c21STomi Valkeinen 96f7018c21STomi Valkeinen info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); 97f7018c21STomi Valkeinen if (!info) 98f7018c21STomi Valkeinen return -ENOMEM; 99f7018c21STomi Valkeinen 100f7018c21STomi Valkeinen info->var = q40fb_var; 101f7018c21STomi Valkeinen info->fix = q40fb_fix; 102f7018c21STomi Valkeinen info->fbops = &q40fb_ops; 103f7018c21STomi Valkeinen info->flags = FBINFO_DEFAULT; /* not as module for now */ 104f7018c21STomi Valkeinen info->pseudo_palette = info->par; 105f7018c21STomi Valkeinen info->par = NULL; 106f7018c21STomi Valkeinen info->screen_base = (char *) q40fb_fix.smem_start; 107f7018c21STomi Valkeinen 108f7018c21STomi Valkeinen if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { 109f7018c21STomi Valkeinen framebuffer_release(info); 110f7018c21STomi Valkeinen return -ENOMEM; 111f7018c21STomi Valkeinen } 112f7018c21STomi Valkeinen 113f7018c21STomi Valkeinen master_outb(3, DISPLAY_CONTROL_REG); 114f7018c21STomi Valkeinen 115f7018c21STomi Valkeinen if (register_framebuffer(info) < 0) { 116f7018c21STomi Valkeinen printk(KERN_ERR "Unable to register Q40 frame buffer\n"); 117f7018c21STomi Valkeinen fb_dealloc_cmap(&info->cmap); 118f7018c21STomi Valkeinen framebuffer_release(info); 119f7018c21STomi Valkeinen return -EINVAL; 120f7018c21STomi Valkeinen } 121f7018c21STomi Valkeinen 122f7018c21STomi Valkeinen fb_info(info, "Q40 frame buffer alive and kicking !\n"); 123f7018c21STomi Valkeinen return 0; 124f7018c21STomi Valkeinen } 125f7018c21STomi Valkeinen 126f7018c21STomi Valkeinen static struct platform_driver q40fb_driver = { 127f7018c21STomi Valkeinen .probe = q40fb_probe, 128f7018c21STomi Valkeinen .driver = { 129f7018c21STomi Valkeinen .name = "q40fb", 130f7018c21STomi Valkeinen }, 131f7018c21STomi Valkeinen }; 132f7018c21STomi Valkeinen 133f7018c21STomi Valkeinen static struct platform_device q40fb_device = { 134f7018c21STomi Valkeinen .name = "q40fb", 135f7018c21STomi Valkeinen }; 136f7018c21STomi Valkeinen 137f7018c21STomi Valkeinen int __init q40fb_init(void) 138f7018c21STomi Valkeinen { 139f7018c21STomi Valkeinen int ret = 0; 140f7018c21STomi Valkeinen 141f7018c21STomi Valkeinen if (fb_get_options("q40fb", NULL)) 142f7018c21STomi Valkeinen return -ENODEV; 143f7018c21STomi Valkeinen 144f7018c21STomi Valkeinen ret = platform_driver_register(&q40fb_driver); 145f7018c21STomi Valkeinen 146f7018c21STomi Valkeinen if (!ret) { 147f7018c21STomi Valkeinen ret = platform_device_register(&q40fb_device); 148f7018c21STomi Valkeinen if (ret) 149f7018c21STomi Valkeinen platform_driver_unregister(&q40fb_driver); 150f7018c21STomi Valkeinen } 151f7018c21STomi Valkeinen return ret; 152f7018c21STomi Valkeinen } 153f7018c21STomi Valkeinen 154f7018c21STomi Valkeinen module_init(q40fb_init); 155f7018c21STomi Valkeinen MODULE_LICENSE("GPL"); 156