linux/drivers/video/fbdev/q40fb.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/video/q40fb.c -- Q40 frame buffer device
   3 *
   4 * Copyright (C) 2001
   5 *
   6 *      Richard Zidlicky <rz@linux-m68k.org>
   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
  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 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
  77static const struct fb_ops q40fb_ops = {
  78        .owner          = THIS_MODULE,
  79        .fb_setcolreg   = q40fb_setcolreg,
  80        .fb_fillrect    = cfb_fillrect,
  81        .fb_copyarea    = cfb_copyarea,
  82        .fb_imageblit   = cfb_imageblit,
  83};
  84
  85static int q40fb_probe(struct platform_device *dev)
  86{
  87        struct fb_info *info;
  88
  89        if (!MACH_IS_Q40)
  90                return -ENXIO;
  91
  92        /* mapped in q40/config.c */
  93        q40fb_fix.smem_start = Q40_PHYS_SCREEN_ADDR;
  94
  95        info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
  96        if (!info)
  97                return -ENOMEM;
  98
  99        info->var = q40fb_var;
 100        info->fix = q40fb_fix;
 101        info->fbops = &q40fb_ops;
 102        info->flags = FBINFO_DEFAULT;  /* not as module for now */
 103        info->pseudo_palette = info->par;
 104        info->par = NULL;
 105        info->screen_base = (char *) q40fb_fix.smem_start;
 106
 107        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 108                framebuffer_release(info);
 109                return -ENOMEM;
 110        }
 111
 112        master_outb(3, DISPLAY_CONTROL_REG);
 113
 114        if (register_framebuffer(info) < 0) {
 115                printk(KERN_ERR "Unable to register Q40 frame buffer\n");
 116                fb_dealloc_cmap(&info->cmap);
 117                framebuffer_release(info);
 118                return -EINVAL;
 119        }
 120
 121        fb_info(info, "Q40 frame buffer alive and kicking !\n");
 122        return 0;
 123}
 124
 125static struct platform_driver q40fb_driver = {
 126        .probe  = q40fb_probe,
 127        .driver = {
 128                .name   = "q40fb",
 129        },
 130};
 131
 132static struct platform_device q40fb_device = {
 133        .name   = "q40fb",
 134};
 135
 136int __init q40fb_init(void)
 137{
 138        int ret = 0;
 139
 140        if (fb_get_options("q40fb", NULL))
 141                return -ENODEV;
 142
 143        ret = platform_driver_register(&q40fb_driver);
 144
 145        if (!ret) {
 146                ret = platform_device_register(&q40fb_device);
 147                if (ret)
 148                        platform_driver_unregister(&q40fb_driver);
 149        }
 150        return ret;
 151}
 152
 153module_init(q40fb_init);
 154MODULE_LICENSE("GPL");
 155