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