152 lines · c
1/*2 * linux/drivers/video/q40fb.c -- Q40 frame buffer device3 *4 * Copyright (C) 20015 *6 * Richard Zidlicky <rz@linux-m68k.org>7 *8 * This file is subject to the terms and conditions of the GNU General Public9 * License. See the file COPYING in the main directory of this archive for10 * 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 0xFE80000028 29static 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 38static 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 53static 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 bit59 * 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 77static const struct fb_ops q40fb_ops = {78 .owner = THIS_MODULE,79 FB_DEFAULT_IOMEM_OPS,80 .fb_setcolreg = q40fb_setcolreg,81};82 83static int q40fb_probe(struct platform_device *dev)84{85 struct fb_info *info;86 87 if (!MACH_IS_Q40)88 return -ENXIO;89 90 /* mapped in q40/config.c */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 122static struct platform_driver q40fb_driver = {123 .probe = q40fb_probe,124 .driver = {125 .name = "q40fb",126 },127};128 129static struct platform_device q40fb_device = {130 .name = "q40fb",131};132 133static 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 150module_init(q40fb_init);151MODULE_LICENSE("GPL");152