linux/drivers/video/fm2fb.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/video/fm2fb.c -- BSC FrameMaster II/Rainbow II frame buffer
   3 *                                 device
   4 *
   5 *      Copyright (C) 1998 Steffen A. Mork (linux-dev@morknet.de)
   6 *      Copyright (C) 1999 Geert Uytterhoeven
   7 *
   8 *  Written for 2.0.x by Steffen A. Mork
   9 *  Ported to 2.1.x by Geert Uytterhoeven
  10 *  Ported to new api by James Simmons
  11 *
  12 *  This file is subject to the terms and conditions of the GNU General Public
  13 *  License. See the file COPYING in the main directory of this archive for
  14 *  more details.
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/mm.h>
  19#include <linux/fb.h>
  20#include <linux/init.h>
  21#include <linux/zorro.h>
  22#include <asm/io.h>
  23
  24/*
  25 *      Some technical notes:
  26 *
  27 *      The BSC FrameMaster II (or Rainbow II) is a simple very dumb
  28 *      frame buffer which allows to display 24 bit true color images.
  29 *      Each pixel is 32 bit width so it's very easy to maintain the
  30 *      frame buffer. One long word has the following layout:
  31 *      AARRGGBB which means: AA the alpha channel byte, RR the red
  32 *      channel, GG the green channel and BB the blue channel.
  33 *
  34 *      The FrameMaster II supports the following video modes.
  35 *      - PAL/NTSC
  36 *      - interlaced/non interlaced
  37 *      - composite sync/sync/sync over green
  38 *
  39 *      The resolution is to the following both ones:
  40 *      - 768x576 (PAL)
  41 *      - 768x480 (NTSC)
  42 *
  43 *      This means that pixel access per line is fixed due to the
  44 *      fixed line width. In case of maximal resolution the frame
  45 *      buffer needs an amount of memory of 1.769.472 bytes which
  46 *      is near to 2 MByte (the allocated address space of Zorro2).
  47 *      The memory is channel interleaved. That means every channel
  48 *      owns four VRAMs. Unfortunately most FrameMasters II are
  49 *      not assembled with memory for the alpha channel. In this
  50 *      case it could be possible to add the frame buffer into the
  51 *      normal memory pool.
  52 *
  53 *      At relative address 0x1ffff8 of the frame buffers base address
  54 *      there exists a control register with the number of
  55 *      four control bits. They have the following meaning:
  56 *      bit value meaning
  57 *
  58 *       0    1   0=interlaced/1=non interlaced
  59 *       1    2   0=video out disabled/1=video out enabled
  60 *       2    4   0=normal mode as jumpered via JP8/1=complement mode
  61 *       3    8   0=read  onboard ROM/1 normal operation (required)
  62 *
  63 *      As mentioned above there are several jumper. I think there
  64 *      is not very much information about the FrameMaster II in
  65 *      the world so I add these information for completeness.
  66 *
  67 *      JP1  interlace selection (1-2 non interlaced/2-3 interlaced)
  68 *      JP2  wait state creation (leave as is!)
  69 *      JP3  wait state creation (leave as is!)
  70 *      JP4  modulate composite sync on green output (1-2 composite
  71 *           sync on green channel/2-3 normal composite sync)
  72 *      JP5  create test signal, shorting this jumper will create
  73 *           a white screen
  74 *      JP6  sync creation (1-2 composite sync/2-3 H-sync output)
  75 *      JP8  video mode (1-2 PAL/2-3 NTSC)
  76 *
  77 *      With the following jumpering table you can connect the
  78 *      FrameMaster II to a normal TV via SCART connector:
  79 *      JP1:  2-3
  80 *      JP4:  2-3
  81 *      JP6:  2-3
  82 *      JP8:  1-2 (means PAL for Europe)
  83 *
  84 *      NOTE:
  85 *      There is no other possibility to change the video timings
  86 *      except the interlaced/non interlaced, sync control and the
  87 *      video mode PAL (50 Hz)/NTSC (60 Hz). Inside this
  88 *      FrameMaster II driver are assumed values to avoid anomalies
  89 *      to a future X server. Except the pixel clock is really
  90 *      constant at 30 MHz.
  91 *
  92 *      9 pin female video connector:
  93 *
  94 *      1  analog red 0.7 Vss
  95 *      2  analog green 0.7 Vss
  96 *      3  analog blue 0.7 Vss
  97 *      4  H-sync TTL
  98 *      5  V-sync TTL
  99 *      6  ground
 100 *      7  ground
 101 *      8  ground
 102 *      9  ground
 103 *
 104 *      Some performance notes:
 105 *      The FrameMaster II was not designed to display a console
 106 *      this driver would do! It was designed to display still true
 107 *      color images. Imagine: When scroll up a text line there
 108 *      must copied ca. 1.7 MBytes to another place inside this
 109 *      frame buffer. This means 1.7 MByte read and 1.7 MByte write
 110 *      over the slow 16 bit wide Zorro2 bus! A scroll of one
 111 *      line needs 1 second so do not expect to much from this
 112 *      driver - he is at the limit!
 113 *
 114 */
 115
 116/*
 117 *      definitions
 118 */
 119
 120#define FRAMEMASTER_SIZE        0x200000
 121#define FRAMEMASTER_REG         0x1ffff8
 122
 123#define FRAMEMASTER_NOLACE      1
 124#define FRAMEMASTER_ENABLE      2
 125#define FRAMEMASTER_COMPL       4
 126#define FRAMEMASTER_ROM         8
 127
 128static volatile unsigned char *fm2fb_reg;
 129
 130static struct fb_fix_screeninfo fb_fix __devinitdata = {
 131        .smem_len =     FRAMEMASTER_REG,
 132        .type =         FB_TYPE_PACKED_PIXELS,
 133        .visual =       FB_VISUAL_TRUECOLOR,
 134        .line_length =  (768 << 2),
 135        .mmio_len =     (8),
 136        .accel =        FB_ACCEL_NONE,
 137};
 138
 139static int fm2fb_mode __devinitdata = -1;
 140
 141#define FM2FB_MODE_PAL  0
 142#define FM2FB_MODE_NTSC 1
 143
 144static struct fb_var_screeninfo fb_var_modes[] __devinitdata = {
 145    {
 146        /* 768 x 576, 32 bpp (PAL) */
 147        768, 576, 768, 576, 0, 0, 32, 0,
 148        { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
 149        0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
 150        33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
 151    }, {
 152        /* 768 x 480, 32 bpp (NTSC - not supported yet */
 153        768, 480, 768, 480, 0, 0, 32, 0,
 154        { 16, 8, 0 }, { 8, 8, 0 }, { 0, 8, 0 }, { 24, 8, 0 },
 155        0, FB_ACTIVATE_NOW, -1, -1, FB_ACCEL_NONE,
 156        33333, 10, 102, 10, 5, 80, 34, FB_SYNC_COMP_HIGH_ACT, 0
 157    }
 158};
 159
 160    /*
 161     *  Interface used by the world
 162     */
 163
 164static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 165                           u_int transp, struct fb_info *info);
 166static int fm2fb_blank(int blank, struct fb_info *info);
 167
 168static struct fb_ops fm2fb_ops = {
 169        .owner          = THIS_MODULE,
 170        .fb_setcolreg   = fm2fb_setcolreg,
 171        .fb_blank       = fm2fb_blank,
 172        .fb_fillrect    = cfb_fillrect,
 173        .fb_copyarea    = cfb_copyarea,
 174        .fb_imageblit   = cfb_imageblit,
 175};
 176
 177    /*
 178     *  Blank the display.
 179     */
 180static int fm2fb_blank(int blank, struct fb_info *info)
 181{
 182        unsigned char t = FRAMEMASTER_ROM;
 183
 184        if (!blank)
 185                t |= FRAMEMASTER_ENABLE | FRAMEMASTER_NOLACE;
 186        fm2fb_reg[0] = t;
 187        return 0;
 188}
 189
 190    /*
 191     *  Set a single color register. The values supplied are already
 192     *  rounded down to the hardware's capabilities (according to the
 193     *  entries in the var structure). Return != 0 for invalid regno.
 194     */
 195static int fm2fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 196                         u_int transp, struct fb_info *info)
 197{
 198        if (regno < 16) {
 199                red >>= 8;
 200                green >>= 8;
 201                blue >>= 8;
 202
 203                ((u32*)(info->pseudo_palette))[regno] = (red << 16) |
 204                        (green << 8) | blue;
 205        }
 206
 207        return 0;
 208}
 209
 210    /*
 211     *  Initialisation
 212     */
 213
 214static int __devinit fm2fb_probe(struct zorro_dev *z,
 215                                 const struct zorro_device_id *id);
 216
 217static struct zorro_device_id fm2fb_devices[] __devinitdata = {
 218        { ZORRO_PROD_BSC_FRAMEMASTER_II },
 219        { ZORRO_PROD_HELFRICH_RAINBOW_II },
 220        { 0 }
 221};
 222MODULE_DEVICE_TABLE(zorro, fm2fb_devices);
 223
 224static struct zorro_driver fm2fb_driver = {
 225        .name           = "fm2fb",
 226        .id_table       = fm2fb_devices,
 227        .probe          = fm2fb_probe,
 228};
 229
 230static int __devinit fm2fb_probe(struct zorro_dev *z,
 231                                 const struct zorro_device_id *id)
 232{
 233        struct fb_info *info;
 234        unsigned long *ptr;
 235        int is_fm;
 236        int x, y;
 237
 238        is_fm = z->id == ZORRO_PROD_BSC_FRAMEMASTER_II;
 239
 240        if (!zorro_request_device(z,"fm2fb"))
 241                return -ENXIO;
 242
 243        info = framebuffer_alloc(16 * sizeof(u32), &z->dev);
 244        if (!info) {
 245                zorro_release_device(z);
 246                return -ENOMEM;
 247        }
 248
 249        if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
 250                framebuffer_release(info);
 251                zorro_release_device(z);
 252                return -ENOMEM;
 253        }
 254
 255        /* assigning memory to kernel space */
 256        fb_fix.smem_start = zorro_resource_start(z);
 257        info->screen_base = ioremap(fb_fix.smem_start, FRAMEMASTER_SIZE);
 258        fb_fix.mmio_start = fb_fix.smem_start + FRAMEMASTER_REG;
 259        fm2fb_reg  = (unsigned char *)(info->screen_base+FRAMEMASTER_REG);
 260
 261        strcpy(fb_fix.id, is_fm ? "FrameMaster II" : "Rainbow II");
 262
 263        /* make EBU color bars on display */
 264        ptr = (unsigned long *)fb_fix.smem_start;
 265        for (y = 0; y < 576; y++) {
 266                for (x = 0; x < 96; x++) *ptr++ = 0xffffff;/* white */
 267                for (x = 0; x < 96; x++) *ptr++ = 0xffff00;/* yellow */
 268                for (x = 0; x < 96; x++) *ptr++ = 0x00ffff;/* cyan */
 269                for (x = 0; x < 96; x++) *ptr++ = 0x00ff00;/* green */
 270                for (x = 0; x < 96; x++) *ptr++ = 0xff00ff;/* magenta */
 271                for (x = 0; x < 96; x++) *ptr++ = 0xff0000;/* red */
 272                for (x = 0; x < 96; x++) *ptr++ = 0x0000ff;/* blue */
 273                for (x = 0; x < 96; x++) *ptr++ = 0x000000;/* black */
 274        }
 275        fm2fb_blank(0, info);
 276
 277        if (fm2fb_mode == -1)
 278                fm2fb_mode = FM2FB_MODE_PAL;
 279
 280        info->fbops = &fm2fb_ops;
 281        info->var = fb_var_modes[fm2fb_mode];
 282        info->pseudo_palette = info->par;
 283        info->par = NULL;
 284        info->fix = fb_fix;
 285        info->flags = FBINFO_DEFAULT;
 286
 287        if (register_framebuffer(info) < 0) {
 288                fb_dealloc_cmap(&info->cmap);
 289                iounmap(info->screen_base);
 290                framebuffer_release(info);
 291                zorro_release_device(z);
 292                return -EINVAL;
 293        }
 294        printk("fb%d: %s frame buffer device\n", info->node, fb_fix.id);
 295        return 0;
 296}
 297
 298int __init fm2fb_setup(char *options)
 299{
 300        char *this_opt;
 301
 302        if (!options || !*options)
 303                return 0;
 304
 305        while ((this_opt = strsep(&options, ",")) != NULL) {
 306                if (!strncmp(this_opt, "pal", 3))
 307                        fm2fb_mode = FM2FB_MODE_PAL;
 308                else if (!strncmp(this_opt, "ntsc", 4))
 309                        fm2fb_mode = FM2FB_MODE_NTSC;
 310        }
 311        return 0;
 312}
 313
 314int __init fm2fb_init(void)
 315{
 316        char *option = NULL;
 317
 318        if (fb_get_options("fm2fb", &option))
 319                return -ENODEV;
 320        fm2fb_setup(option);
 321        return zorro_register_driver(&fm2fb_driver);
 322}
 323
 324module_init(fm2fb_init);
 325MODULE_LICENSE("GPL");
 326
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.