linux/drivers/video/arkfb.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/video/arkfb.c -- Frame buffer device driver for ARK 2000PV
   3 *  with ICS 5342 dac (it is easy to add support for different dacs).
   4 *
   5 *  Copyright (c) 2007 Ondrej Zajicek <santiago@crfreenet.org>
   6 *
   7 *  This file is subject to the terms and conditions of the GNU General Public
   8 *  License.  See the file COPYING in the main directory of this archive for
   9 *  more details.
  10 *
  11 *  Code is based on s3fb
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/errno.h>
  17#include <linux/string.h>
  18#include <linux/mm.h>
  19#include <linux/tty.h>
  20#include <linux/slab.h>
  21#include <linux/delay.h>
  22#include <linux/fb.h>
  23#include <linux/svga.h>
  24#include <linux/init.h>
  25#include <linux/pci.h>
  26#include <linux/console.h> /* Why should fb driver call console functions? because acquire_console_sem() */
  27#include <video/vga.h>
  28
  29#ifdef CONFIG_MTRR
  30#include <asm/mtrr.h>
  31#endif
  32
  33struct arkfb_info {
  34        int mclk_freq;
  35        int mtrr_reg;
  36
  37        struct dac_info *dac;
  38        struct vgastate state;
  39        struct mutex open_lock;
  40        unsigned int ref_count;
  41        u32 pseudo_palette[16];
  42};
  43
  44
  45/* ------------------------------------------------------------------------- */
  46
  47
  48static const struct svga_fb_format arkfb_formats[] = {
  49        { 0,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
  50                FB_TYPE_TEXT, FB_AUX_TEXT_SVGA_STEP4,   FB_VISUAL_PSEUDOCOLOR, 8, 8},
  51        { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
  52                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 8, 16},
  53        { 4,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 1,
  54                FB_TYPE_INTERLEAVED_PLANES, 1,          FB_VISUAL_PSEUDOCOLOR, 8, 16},
  55        { 8,  {0, 6, 0},  {0, 6, 0},  {0, 6, 0}, {0, 0, 0}, 0,
  56                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_PSEUDOCOLOR, 8, 8},
  57        {16,  {10, 5, 0}, {5, 5, 0},  {0, 5, 0}, {0, 0, 0}, 0,
  58                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},
  59        {16,  {11, 5, 0}, {5, 6, 0},  {0, 5, 0}, {0, 0, 0}, 0,
  60                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 4, 4},
  61        {24,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
  62                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 8, 8},
  63        {32,  {16, 8, 0}, {8, 8, 0},  {0, 8, 0}, {0, 0, 0}, 0,
  64                FB_TYPE_PACKED_PIXELS, 0,               FB_VISUAL_TRUECOLOR, 2, 2},
  65        SVGA_FORMAT_END
  66};
  67
  68
  69/* CRT timing register sets */
  70
  71static const struct vga_regset ark_h_total_regs[]        = {{0x00, 0, 7}, {0x41, 7, 7}, VGA_REGSET_END};
  72static const struct vga_regset ark_h_display_regs[]      = {{0x01, 0, 7}, {0x41, 6, 6}, VGA_REGSET_END};
  73static const struct vga_regset ark_h_blank_start_regs[]  = {{0x02, 0, 7}, {0x41, 5, 5}, VGA_REGSET_END};
  74static const struct vga_regset ark_h_blank_end_regs[]    = {{0x03, 0, 4}, {0x05, 7, 7   }, VGA_REGSET_END};
  75static const struct vga_regset ark_h_sync_start_regs[]   = {{0x04, 0, 7}, {0x41, 4, 4}, VGA_REGSET_END};
  76static const struct vga_regset ark_h_sync_end_regs[]     = {{0x05, 0, 4}, VGA_REGSET_END};
  77
  78static const struct vga_regset ark_v_total_regs[]        = {{0x06, 0, 7}, {0x07, 0, 0}, {0x07, 5, 5}, {0x40, 7, 7}, VGA_REGSET_END};
  79static const struct vga_regset ark_v_display_regs[]      = {{0x12, 0, 7}, {0x07, 1, 1}, {0x07, 6, 6}, {0x40, 6, 6}, VGA_REGSET_END};
  80static const struct vga_regset ark_v_blank_start_regs[]  = {{0x15, 0, 7}, {0x07, 3, 3}, {0x09, 5, 5}, {0x40, 5, 5}, VGA_REGSET_END};
  81// const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 6}, VGA_REGSET_END};
  82static const struct vga_regset ark_v_blank_end_regs[]    = {{0x16, 0, 7}, VGA_REGSET_END};
  83static const struct vga_regset ark_v_sync_start_regs[]   = {{0x10, 0, 7}, {0x07, 2, 2}, {0x07, 7, 7}, {0x40, 4, 4}, VGA_REGSET_END};
  84static const struct vga_regset ark_v_sync_end_regs[]     = {{0x11, 0, 3}, VGA_REGSET_END};
  85
  86static const struct vga_regset ark_line_compare_regs[]   = {{0x18, 0, 7}, {0x07, 4, 4}, {0x09, 6, 6}, VGA_REGSET_END};
  87static const struct vga_regset ark_start_address_regs[]  = {{0x0d, 0, 7}, {0x0c, 0, 7}, {0x40, 0, 2}, VGA_REGSET_END};
  88static const struct vga_regset ark_offset_regs[]         = {{0x13, 0, 7}, {0x41, 3, 3}, VGA_REGSET_END};
  89
  90static const struct svga_timing_regs ark_timing_regs     = {
  91        ark_h_total_regs, ark_h_display_regs, ark_h_blank_start_regs,
  92        ark_h_blank_end_regs, ark_h_sync_start_regs, ark_h_sync_end_regs,
  93        ark_v_total_regs, ark_v_display_regs, ark_v_blank_start_regs,
  94        ark_v_blank_end_regs, ark_v_sync_start_regs, ark_v_sync_end_regs,
  95};
  96
  97
  98/* ------------------------------------------------------------------------- */
  99
 100
 101/* Module parameters */
 102
 103static char *mode_option __devinitdata = "640x480-8@60";
 104
 105#ifdef CONFIG_MTRR
 106static int mtrr = 1;
 107#endif
 108
 109MODULE_AUTHOR("(c) 2007 Ondrej Zajicek <santiago@crfreenet.org>");
 110MODULE_LICENSE("GPL");
 111MODULE_DESCRIPTION("fbdev driver for ARK 2000PV");
 112
 113module_param(mode_option, charp, 0444);
 114MODULE_PARM_DESC(mode_option, "Default video mode ('640x480-8@60', etc)");
 115module_param_named(mode, mode_option, charp, 0444);
 116MODULE_PARM_DESC(mode, "Default video mode ('640x480-8@60', etc) (deprecated)");
 117
 118#ifdef CONFIG_MTRR
 119module_param(mtrr, int, 0444);
 120MODULE_PARM_DESC(mtrr, "Enable write-combining with MTRR (1=enable, 0=disable, default=1)");
 121#endif
 122
 123static int threshold = 4;
 124
 125module_param(threshold, int, 0644);
 126MODULE_PARM_DESC(threshold, "FIFO threshold");
 127
 128
 129/* ------------------------------------------------------------------------- */
 130
 131
 132static void arkfb_settile(struct fb_info *info, struct fb_tilemap *map)
 133{
 134        const u8 *font = map->data;
 135        u8 __iomem *fb = (u8 __iomem *)info->screen_base;
 136        int i, c;
 137
 138        if ((map->width != 8) || (map->height != 16) ||
 139            (map->depth != 1) || (map->length != 256)) {
 140                printk(KERN_ERR "fb%d: unsupported font parameters: width %d, "
 141                       "height %d, depth %d, length %d\n", info->node,
 142                       map->width, map->height, map->depth, map->length);
 143                return;
 144        }
 145
 146        fb += 2;
 147        for (c = 0; c < map->length; c++) {
 148                for (i = 0; i < map->height; i++) {
 149                        fb_writeb(font[i], &fb[i * 4]);
 150                        fb_writeb(font[i], &fb[i * 4 + (128 * 8)]);
 151                }
 152                fb += 128;
 153
 154                if ((c % 8) == 7)
 155                        fb += 128*8;
 156
 157                font += map->height;
 158        }
 159}
 160
 161static struct fb_tile_ops arkfb_tile_ops = {
 162        .fb_settile     = arkfb_settile,
 163        .fb_tilecopy    = svga_tilecopy,
 164        .fb_tilefill    = svga_tilefill,
 165        .fb_tileblit    = svga_tileblit,
 166        .fb_tilecursor  = svga_tilecursor,
 167        .fb_get_tilemax = svga_get_tilemax,
 168};
 169
 170
 171/* ------------------------------------------------------------------------- */
 172
 173
 174/* image data is MSB-first, fb structure is MSB-first too */
 175static inline u32 expand_color(u32 c)
 176{
 177        return ((c & 1) | ((c & 2) << 7) | ((c & 4) << 14) | ((c & 8) << 21)) * 0xFF;
 178}
 179
 180/* arkfb_iplan_imageblit silently assumes that almost everything is 8-pixel aligned */
 181static void arkfb_iplan_imageblit(struct fb_info *info, const struct fb_image *image)
 182{
 183        u32 fg = expand_color(image->fg_color);
 184        u32 bg = expand_color(image->bg_color);
 185        const u8 *src1, *src;
 186        u8 __iomem *dst1;
 187        u32 __iomem *dst;
 188        u32 val;
 189        int x, y;
 190
 191        src1 = image->data;
 192        dst1 = info->screen_base + (image->dy * info->fix.line_length)
 193                 + ((image->dx / 8) * 4);
 194
 195        for (y = 0; y < image->height; y++) {
 196                src = src1;
 197                dst = (u32 __iomem *) dst1;
 198                for (x = 0; x < image->width; x += 8) {
 199                        val = *(src++) * 0x01010101;
 200                        val = (val & fg) | (~val & bg);
 201                        fb_writel(val, dst++);
 202                }
 203                src1 += image->width / 8;
 204                dst1 += info->fix.line_length;
 205        }
 206
 207}
 208
 209/* arkfb_iplan_fillrect silently assumes that almost everything is 8-pixel aligned */
 210static void arkfb_iplan_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 211{
 212        u32 fg = expand_color(rect->color);
 213        u8 __iomem *dst1;
 214        u32 __iomem *dst;
 215        int x, y;
 216
 217        dst1 = info->screen_base + (rect->dy * info->fix.line_length)
 218                 + ((rect->dx / 8) * 4);
 219
 220        for (y = 0; y < rect->height; y++) {
 221                dst = (u32 __iomem *) dst1;
 222                for (x = 0; x < rect->width; x += 8) {
 223                        fb_writel(fg, dst++);
 224                }
 225                dst1 += info->fix.line_length;
 226        }
 227
 228}
 229
 230
 231/* image data is MSB-first, fb structure is high-nibble-in-low-byte-first */
 232static inline u32 expand_pixel(u32 c)
 233{
 234        return (((c &  1) << 24) | ((c &  2) << 27) | ((c &  4) << 14) | ((c &   8) << 17) |
 235                ((c & 16) <<  4) | ((c & 32) <<  7) | ((c & 64) >>  6) | ((c & 128) >>  3)) * 0xF;
 236}
 237
 238/* arkfb_cfb4_imageblit silently assumes that almost everything is 8-pixel aligned */
 239static void arkfb_cfb4_imageblit(struct fb_info *info, const struct fb_image *image)
 240{
 241        u32 fg = image->fg_color * 0x11111111;
 242        u32 bg = image->bg_color * 0x11111111;
 243        const u8 *src1, *src;
 244        u8 __iomem *dst1;
 245        u32 __iomem *dst;
 246        u32 val;
 247        int x, y;
 248
 249        src1 = image->data;
 250        dst1 = info->screen_base + (image->dy * info->fix.line_length)
 251                 + ((image->dx / 8) * 4);
 252
 253        for (y = 0; y < image->height; y++) {
 254                src = src1;
 255                dst = (u32 __iomem *) dst1;
 256                for (x = 0; x < image->width; x += 8) {
 257                        val = expand_pixel(*(src++));
 258                        val = (val & fg) | (~val & bg);
 259                        fb_writel(val, dst++);
 260                }
 261                src1 += image->width / 8;
 262                dst1 += info->fix.line_length;
 263        }
 264
 265}
 266
 267static void arkfb_imageblit(struct fb_info *info, const struct fb_image *image)
 268{
 269        if ((info->var.bits_per_pixel == 4) && (image->depth == 1)
 270            && ((image->width % 8) == 0) && ((image->dx % 8) == 0)) {
 271                if (info->fix.type == FB_TYPE_INTERLEAVED_PLANES)
 272                        arkfb_iplan_imageblit(info, image);
 273                else
 274                        arkfb_cfb4_imageblit(info, image);
 275        } else
 276                cfb_imageblit(info, image);
 277}
 278
 279static void arkfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 280{
 281        if ((info->var.bits_per_pixel == 4)
 282            && ((rect->width % 8) == 0) && ((rect->dx % 8) == 0)
 283            && (info->fix.type == FB_TYPE_INTERLEAVED_PLANES))
 284                arkfb_iplan_fillrect(info, rect);
 285         else
 286                cfb_fillrect(info, rect);
 287}
 288
 289
 290/* ------------------------------------------------------------------------- */
 291
 292
 293enum
 294{
 295        DAC_PSEUDO8_8,
 296        DAC_RGB1555_8,
 297        DAC_RGB0565_8,
 298        DAC_RGB0888_8,
 299        DAC_RGB8888_8,
 300        DAC_PSEUDO8_16,
 301        DAC_RGB1555_16,
 302        DAC_RGB0565_16,
 303        DAC_RGB0888_16,
 304        DAC_RGB8888_16,
 305        DAC_MAX
 306};
 307
 308struct dac_ops {
 309        int (*dac_get_mode)(struct dac_info *info);
 310        int (*dac_set_mode)(struct dac_info *info, int mode);
 311        int (*dac_get_freq)(struct dac_info *info, int channel);
 312        int (*dac_set_freq)(struct dac_info *info, int channel, u32 freq);
 313        void (*dac_release)(struct dac_info *info);
 314};
 315
 316typedef void (*dac_read_regs_t)(void *data, u8 *code, int count);
 317typedef void (*dac_write_regs_t)(void *data, u8 *code, int count);
 318
 319struct dac_info
 320{
 321        struct dac_ops *dacops;
 322        dac_read_regs_t dac_read_regs;
 323        dac_write_regs_t dac_write_regs;
 324        void *data;
 325};
 326
 327
 328static inline u8 dac_read_reg(struct dac_info *info, u8 reg)
 329{
 330        u8 code[2] = {reg, 0};
 331        info->dac_read_regs(info->data, code, 1);
 332        return code[1];
 333}
 334
 335static inline void dac_read_regs(struct dac_info *info, u8 *code, int count)
 336{
 337        info->dac_read_regs(info->data, code, count);
 338}
 339
 340static inline void dac_write_reg(struct dac_info *info, u8 reg, u8 val)
 341{
 342        u8 code[2] = {reg, val};
 343        info->dac_write_regs(info->data, code, 1);
 344}
 345
 346static inline void dac_write_regs(struct dac_info *info, u8 *code, int count)
 347{
 348        info->dac_write_regs(info->data, code, count);
 349}
 350
 351static inline int dac_set_mode(struct dac_info *info, int mode)
 352{
 353        return info->dacops->dac_set_mode(info, mode);
 354}
 355
 356static inline int dac_set_freq(struct dac_info *info, int channel, u32 freq)
 357{
 358        return info->dacops->dac_set_freq(info, channel, freq);
 359}
 360
 361static inline void dac_release(struct dac_info *info)
 362{
 363        info->dacops->dac_release(info);
 364}
 365
 366
 367/* ------------------------------------------------------------------------- */
 368
 369
 370/* ICS5342 DAC */
 371
 372struct ics5342_info
 373{
 374        struct dac_info dac;
 375        u8 mode;
 376};
 377
 378#define DAC_PAR(info) ((struct ics5342_info *) info)
 379
 380/* LSB is set to distinguish unused slots */
 381static const u8 ics5342_mode_table[DAC_MAX] = {
 382        [DAC_PSEUDO8_8]  = 0x01, [DAC_RGB1555_8]  = 0x21, [DAC_RGB0565_8]  = 0x61,
 383        [DAC_RGB0888_8]  = 0x41, [DAC_PSEUDO8_16] = 0x11, [DAC_RGB1555_16] = 0x31,
 384        [DAC_RGB0565_16] = 0x51, [DAC_RGB0888_16] = 0x91, [DAC_RGB8888_16] = 0x71
 385};
 386
 387static int ics5342_set_mode(struct dac_info *info, int mode)
 388{
 389        u8 code;
 390
 391        if (mode >= DAC_MAX)
 392                return -EINVAL;
 393
 394        code = ics5342_mode_table[mode];
 395
 396        if (! code)
 397                return -EINVAL;
 398
 399        dac_write_reg(info, 6, code & 0xF0);
 400        DAC_PAR(info)->mode = mode;
 401
 402        return 0;
 403}
 404
 405static const struct svga_pll ics5342_pll = {3, 129, 3, 33, 0, 3,
 406        60000, 250000, 14318};
 407
 408/* pd4 - allow only posdivider 4 (r=2) */
 409static const struct svga_pll ics5342_pll_pd4 = {3, 129, 3, 33, 2, 2,
 410        60000, 335000, 14318};
 411
 412/* 270 MHz should be upper bound for VCO clock according to specs,
 413   but that is too restrictive in pd4 case */
 414
 415static int ics5342_set_freq(struct dac_info *info, int channel, u32 freq)
 416{
 417        u16 m, n, r;
 418
 419        /* only postdivider 4 (r=2) is valid in mode DAC_PSEUDO8_16 */
 420        int rv = svga_compute_pll((DAC_PAR(info)->mode == DAC_PSEUDO8_16)
 421                                  ? &ics5342_pll_pd4 : &ics5342_pll,
 422                                  freq, &m, &n, &r, 0);
 423
 424        if (rv < 0) {
 425                return -EINVAL;
 426        } else {
 427                u8 code[6] = {4, 3, 5, m-2, 5, (n-2) | (r << 5)};
 428                dac_write_regs(info, code, 3);
 429                return 0;
 430        }
 431}
 432
 433static void ics5342_release(struct dac_info *info)
 434{
 435        ics5342_set_mode(info, DAC_PSEUDO8_8);
 436        kfree(info);
 437}
 438
 439static struct dac_ops ics5342_ops = {
 440        .dac_set_mode   = ics5342_set_mode,
 441        .dac_set_freq   = ics5342_set_freq,
 442        .dac_release    = ics5342_release
 443};
 444
 445
 446static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data)
 447{
 448        struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL);
 449
 450        if (! info)
 451                return NULL;
 452
 453        info->dacops = &ics5342_ops;
 454        info->dac_read_regs = drr;
 455        info->dac_write_regs = dwr;
 456        info->data = data;
 457        DAC_PAR(info)->mode = DAC_PSEUDO8_8; /* estimation */
 458        return info;
 459}
 460
 461
 462/* ------------------------------------------------------------------------- */
 463
 464
 465static unsigned short dac_regs[4] = {0x3c8, 0x3c9, 0x3c6, 0x3c7};
 466
 467static void ark_dac_read_regs(void *data, u8 *code, int count)
 468{
 469        u8 regval = vga_rseq(NULL, 0x1C);
 470
 471        while (count != 0)
 472        {
 473                vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
 474                code[1] = vga_r(NULL, dac_regs[code[0] & 3]);
 475                count--;
 476                code += 2;
 477        }
 478
 479        vga_wseq(NULL, 0x1C, regval);
 480}
 481
 482static void ark_dac_write_regs(void *data, u8 *code, int count)
 483{
 484        u8 regval = vga_rseq(NULL, 0x1C);
 485
 486        while (count != 0)
 487        {
 488                vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0));
 489                vga_w(NULL, dac_regs[code[0] & 3], code[1]);
 490                count--;
 491                code += 2;
 492        }
 493
 494        vga_wseq(NULL, 0x1C, regval);
 495}
 496
 497
 498static void ark_set_pixclock(struct fb_info *info, u32 pixclock)
 499{
 500        struct arkfb_info *par = info->par;
 501        u8 regval;
 502
 503        int rv = dac_set_freq(par->dac, 0, 1000000000 / pixclock);
 504        if (rv < 0) {
 505                printk(KERN_ERR "fb%d: cannot set requested pixclock, keeping old value\n", info->node);
 506                return;
 507        }
 508
 509        /* Set VGA misc register  */
 510        regval = vga_r(NULL, VGA_MIS_R);
 511        vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
 512}
 513
 514
 515/* Open framebuffer */
 516
 517static int arkfb_open(struct fb_info *info, int user)
 518{
 519        struct arkfb_info *par = info->par;
 520
 521        mutex_lock(&(par->open_lock));
 522        if (par->ref_count == 0) {
 523                memset(&(par->state), 0, sizeof(struct vgastate));
 524                par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS | VGA_SAVE_CMAP;
 525                par->state.num_crtc = 0x60;
 526                par->state.num_seq = 0x30;
 527                save_vga(&(par->state));
 528        }
 529
 530        par->ref_count++;
 531        mutex_unlock(&(par->open_lock));
 532
 533        return 0;
 534}
 535
 536/* Close framebuffer */
 537
 538static int arkfb_release(struct fb_info *info, int user)
 539{
 540        struct arkfb_info *par = info->par;
 541
 542        mutex_lock(&(par->open_lock));
 543        if (par->ref_count == 0) {
 544                mutex_unlock(&(par->open_lock));
 545                return -EINVAL;
 546        }
 547
 548        if (par->ref_count == 1) {
 549                restore_vga(&(par->state));
 550                dac_set_mode(par->dac, DAC_PSEUDO8_8);
 551        }
 552
 553        par->ref_count--;
 554        mutex_unlock(&(par->open_lock));
 555
 556        return 0;
 557}
 558
 559/* Validate passed in var */
 560
 561static int arkfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 562{
 563        int rv, mem, step;
 564
 565        /* Find appropriate format */
 566        rv = svga_match_format (arkfb_formats, var, NULL);
 567        if (rv < 0)
 568        {
 569                printk(KERN_ERR "fb%d: unsupported mode requested\n", info->node);
 570                return rv;
 571        }
 572
 573        /* Do not allow to have real resoulution larger than virtual */
 574        if (var->xres > var->xres_virtual)
 575                var->xres_virtual = var->xres;
 576
 577        if (var->yres > var->yres_virtual)
 578                var->yres_virtual = var->yres;
 579
 580        /* Round up xres_virtual to have proper alignment of lines */
 581        step = arkfb_formats[rv].xresstep - 1;
 582        var->xres_virtual = (var->xres_virtual+step) & ~step;
 583
 584
 585        /* Check whether have enough memory */
 586        mem = ((var->bits_per_pixel * var->xres_virtual) >> 3) * var->yres_virtual;
 587        if (mem > info->screen_size)
 588        {
 589                printk(KERN_ERR "fb%d: not enough framebuffer memory (%d kB requested , %d kB available)\n", info->node, mem >> 10, (unsigned int) (info->screen_size >> 10));
 590                return -EINVAL;
 591        }
 592
 593        rv = svga_check_timings (&ark_timing_regs, var, info->node);
 594        if (rv < 0)
 595        {
 596                printk(KERN_ERR "fb%d: invalid timings requested\n", info->node);
 597                return rv;
 598        }
 599
 600        /* Interlaced mode is broken */
 601        if (var->vmode & FB_VMODE_INTERLACED)
 602                return -EINVAL;
 603
 604        return 0;
 605}
 606
 607/* Set video mode from par */
 608
 609static int arkfb_set_par(struct fb_info *info)
 610{
 611        struct arkfb_info *par = info->par;
 612        u32 value, mode, hmul, hdiv, offset_value, screen_size;
 613        u32 bpp = info->var.bits_per_pixel;
 614        u8 regval;
 615
 616        if (bpp != 0) {
 617                info->fix.ypanstep = 1;
 618                info->fix.line_length = (info->var.xres_virtual * bpp) / 8;
 619
 620                info->flags &= ~FBINFO_MISC_TILEBLITTING;
 621                info->tileops = NULL;
 622
 623                /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
 624                info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
 625                info->pixmap.blit_y = ~(u32)0;
 626
 627                offset_value = (info->var.xres_virtual * bpp) / 64;
 628                screen_size = info->var.yres_virtual * info->fix.line_length;
 629        } else {
 630                info->fix.ypanstep = 16;
 631                info->fix.line_length = 0;
 632
 633                info->flags |= FBINFO_MISC_TILEBLITTING;
 634                info->tileops = &arkfb_tile_ops;
 635
 636                /* supports 8x16 tiles only */
 637                info->pixmap.blit_x = 1 << (8 - 1);
 638                info->pixmap.blit_y = 1 << (16 - 1);
 639
 640                offset_value = info->var.xres_virtual / 16;
 641                screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
 642        }
 643
 644        info->var.xoffset = 0;
 645        info->var.yoffset = 0;
 646        info->var.activate = FB_ACTIVATE_NOW;
 647
 648        /* Unlock registers */
 649        svga_wcrt_mask(0x11, 0x00, 0x80);
 650
 651        /* Blank screen and turn off sync */
 652        svga_wseq_mask(0x01, 0x20, 0x20);
 653        svga_wcrt_mask(0x17, 0x00, 0x80);
 654
 655        /* Set default values */
 656        svga_set_default_gfx_regs();
 657        svga_set_default_atc_regs();
 658        svga_set_default_seq_regs();
 659        svga_set_default_crt_regs();
 660        svga_wcrt_multi(ark_line_compare_regs, 0xFFFFFFFF);
 661        svga_wcrt_multi(ark_start_address_regs, 0);
 662
 663        /* ARK specific initialization */
 664        svga_wseq_mask(0x10, 0x1F, 0x1F); /* enable linear framebuffer and full memory access */
 665        svga_wseq_mask(0x12, 0x03, 0x03); /* 4 MB linear framebuffer size */
 666
 667        vga_wseq(NULL, 0x13, info->fix.smem_start >> 16);
 668        vga_wseq(NULL, 0x14, info->fix.smem_start >> 24);
 669        vga_wseq(NULL, 0x15, 0);
 670        vga_wseq(NULL, 0x16, 0);
 671
 672        /* Set the FIFO threshold register */
 673        /* It is fascinating way to store 5-bit value in 8-bit register */
 674        regval = 0x10 | ((threshold & 0x0E) >> 1) | (threshold & 0x01) << 7 | (threshold & 0x10) << 1;
 675        vga_wseq(NULL, 0x18, regval);
 676
 677        /* Set the offset register */
 678        pr_debug("fb%d: offset register       : %d\n", info->node, offset_value);
 679        svga_wcrt_multi(ark_offset_regs, offset_value);
 680
 681        /* fix for hi-res textmode */
 682        svga_wcrt_mask(0x40, 0x08, 0x08);
 683
 684        if (info->var.vmode & FB_VMODE_DOUBLE)
 685                svga_wcrt_mask(0x09, 0x80, 0x80);
 686        else
 687                svga_wcrt_mask(0x09, 0x00, 0x80);
 688
 689        if (info->var.vmode & FB_VMODE_INTERLACED)
 690                svga_wcrt_mask(0x44, 0x04, 0x04);
 691        else
 692                svga_wcrt_mask(0x44, 0x00, 0x04);
 693
 694        hmul = 1;
 695        hdiv = 1;
 696        mode = svga_match_format(arkfb_formats, &(info->var), &(info->fix));
 697
 698        /* Set mode-specific register values */
 699        switch (mode) {
 700        case 0:
 701                pr_debug("fb%d: text mode\n", info->node);
 702                svga_set_textmode_vga_regs();
 703
 704                vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
 705                svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
 706                dac_set_mode(par->dac, DAC_PSEUDO8_8);
 707
 708                break;
 709        case 1:
 710                pr_debug("fb%d: 4 bit pseudocolor\n", info->node);
 711                vga_wgfx(NULL, VGA_GFX_MODE, 0x40);
 712
 713                vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
 714                svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
 715                dac_set_mode(par->dac, DAC_PSEUDO8_8);
 716                break;
 717        case 2:
 718                pr_debug("fb%d: 4 bit pseudocolor, planar\n", info->node);
 719
 720                vga_wseq(NULL, 0x11, 0x10); /* basic VGA mode */
 721                svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
 722                dac_set_mode(par->dac, DAC_PSEUDO8_8);
 723                break;
 724        case 3:
 725                pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
 726
 727                vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode */
 728
 729                if (info->var.pixclock > 20000) {
 730                        pr_debug("fb%d: not using multiplex\n", info->node);
 731                        svga_wcrt_mask(0x46, 0x00, 0x04); /* 8bit pixel path */
 732                        dac_set_mode(par->dac, DAC_PSEUDO8_8);
 733                } else {
 734                        pr_debug("fb%d: using multiplex\n", info->node);
 735                        svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
 736                        dac_set_mode(par->dac, DAC_PSEUDO8_16);
 737                        hdiv = 2;
 738                }
 739                break;
 740        case 4:
 741                pr_debug("fb%d: 5/5/5 truecolor\n", info->node);
 742
 743                vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */
 744                svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
 745                dac_set_mode(par->dac, DAC_RGB1555_16);
 746                break;
 747        case 5:
 748                pr_debug("fb%d: 5/6/5 truecolor\n", info->node);
 749
 750                vga_wseq(NULL, 0x11, 0x1A); /* 16bpp accel mode */
 751                svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
 752                dac_set_mode(par->dac, DAC_RGB0565_16);
 753                break;
 754        case 6:
 755                pr_debug("fb%d: 8/8/8 truecolor\n", info->node);
 756
 757                vga_wseq(NULL, 0x11, 0x16); /* 8bpp accel mode ??? */
 758                svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
 759                dac_set_mode(par->dac, DAC_RGB0888_16);
 760                hmul = 3;
 761                hdiv = 2;
 762                break;
 763        case 7:
 764                pr_debug("fb%d: 8/8/8/8 truecolor\n", info->node);
 765
 766                vga_wseq(NULL, 0x11, 0x1E); /* 32bpp accel mode */
 767                svga_wcrt_mask(0x46, 0x04, 0x04); /* 16bit pixel path */
 768                dac_set_mode(par->dac, DAC_RGB8888_16);
 769                hmul = 2;
 770                break;
 771        default:
 772                printk(KERN_ERR "fb%d: unsupported mode - bug\n", info->node);
 773                return -EINVAL;
 774        }
 775
 776        ark_set_pixclock(info, (hdiv * info->var.pixclock) / hmul);
 777        svga_set_timings(&ark_timing_regs, &(info->var), hmul, hdiv,
 778                         (info->var.vmode & FB_VMODE_DOUBLE)     ? 2 : 1,
 779                         (info->var.vmode & FB_VMODE_INTERLACED) ? 2 : 1,
 780                          hmul, info->node);
 781
 782        /* Set interlaced mode start/end register */
 783        value = info->var.xres + info->var.left_margin + info->var.right_margin + info->var.hsync_len;
 784        value = ((value * hmul / hdiv) / 8) - 5;
 785        vga_wcrt(NULL, 0x42, (value + 1) / 2);
 786
 787        memset_io(info->screen_base, 0x00, screen_size);
 788        /* Device and screen back on */
 789        svga_wcrt_mask(0x17, 0x80, 0x80);
 790        svga_wseq_mask(0x01, 0x00, 0x20);
 791
 792        return 0;
 793}
 794
 795/* Set a colour register */
 796
 797static int arkfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 798                                u_int transp, struct fb_info *fb)
 799{
 800        switch (fb->var.bits_per_pixel) {
 801        case 0:
 802        case 4:
 803                if (regno >= 16)
 804                        return -EINVAL;
 805
 806                if ((fb->var.bits_per_pixel == 4) &&
 807                    (fb->var.nonstd == 0)) {
 808                        outb(0xF0, VGA_PEL_MSK);
 809                        outb(regno*16, VGA_PEL_IW);
 810                } else {
 811                        outb(0x0F, VGA_PEL_MSK);
 812                        outb(regno, VGA_PEL_IW);
 813                }
 814                outb(red >> 10, VGA_PEL_D);
 815                outb(green >> 10, VGA_PEL_D);
 816                outb(blue >> 10, VGA_PEL_D);
 817                break;
 818        case 8:
 819                if (regno >= 256)
 820                        return -EINVAL;
 821
 822                outb(0xFF, VGA_PEL_MSK);
 823                outb(regno, VGA_PEL_IW);
 824                outb(red >> 10, VGA_PEL_D);
 825                outb(green >> 10, VGA_PEL_D);
 826                outb(blue >> 10, VGA_PEL_D);
 827                break;
 828        case 16:
 829                if (regno >= 16)
 830                        return 0;
 831
 832                if (fb->var.green.length == 5)
 833                        ((u32*)fb->pseudo_palette)[regno] = ((red & 0xF800) >> 1) |
 834                                ((green & 0xF800) >> 6) | ((blue & 0xF800) >> 11);
 835                else if (fb->var.green.length == 6)
 836                        ((u32*)fb->pseudo_palette)[regno] = (red & 0xF800) |
 837                                ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
 838                else
 839                        return -EINVAL;
 840                break;
 841        case 24:
 842        case 32:
 843                if (regno >= 16)
 844                        return 0;
 845
 846                ((u32*)fb->pseudo_palette)[regno] = ((red & 0xFF00) << 8) |
 847                        (green & 0xFF00) | ((blue & 0xFF00) >> 8);
 848                break;
 849        default:
 850                return -EINVAL;
 851        }
 852
 853        return 0;
 854}
 855
 856/* Set the display blanking state */
 857
 858static int arkfb_blank(int blank_mode, struct fb_info *info)
 859{
 860        switch (blank_mode) {
 861        case FB_BLANK_UNBLANK:
 862                pr_debug("fb%d: unblank\n", info->node);
 863                svga_wseq_mask(0x01, 0x00, 0x20);
 864                svga_wcrt_mask(0x17, 0x80, 0x80);
 865                break;
 866        case FB_BLANK_NORMAL:
 867                pr_debug("fb%d: blank\n", info->node);
 868                svga_wseq_mask(0x01, 0x20, 0x20);
 869                svga_wcrt_mask(0x17, 0x80, 0x80);
 870                break;
 871        case FB_BLANK_POWERDOWN:
 872        case FB_BLANK_HSYNC_SUSPEND:
 873        case FB_BLANK_VSYNC_SUSPEND:
 874                pr_debug("fb%d: sync down\n", info->node);
 875                svga_wseq_mask(0x01, 0x20, 0x20);
 876                svga_wcrt_mask(0x17, 0x00, 0x80);
 877                break;
 878        }
 879        return 0;
 880}
 881
 882
 883/* Pan the display */
 884
 885static int arkfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 886{
 887        unsigned int offset;
 888
 889        /* Calculate the offset */
 890        if (var->bits_per_pixel == 0) {
 891                offset = (var->yoffset / 16) * (var->xres_virtual / 2) + (var->xoffset / 2);
 892                offset = offset >> 2;
 893        } else {
 894                offset = (var->yoffset * info->fix.line_length) +
 895                         (var->xoffset * var->bits_per_pixel / 8);
 896                offset = offset >> ((var->bits_per_pixel == 4) ? 2 : 3);
 897        }
 898
 899        /* Set the offset */
 900        svga_wcrt_multi(ark_start_address_regs, offset);
 901
 902        return 0;
 903}
 904
 905
 906/* ------------------------------------------------------------------------- */
 907
 908
 909/* Frame buffer operations */
 910
 911static struct fb_ops arkfb_ops = {
 912        .owner          = THIS_MODULE,
 913        .fb_open        = arkfb_open,
 914        .fb_release     = arkfb_release,
 915        .fb_check_var   = arkfb_check_var,
 916        .fb_set_par     = arkfb_set_par,
 917        .fb_setcolreg   = arkfb_setcolreg,
 918        .fb_blank       = arkfb_blank,
 919        .fb_pan_display = arkfb_pan_display,
 920        .fb_fillrect    = arkfb_fillrect,
 921        .fb_copyarea    = cfb_copyarea,
 922        .fb_imageblit   = arkfb_imageblit,
 923        .fb_get_caps    = svga_get_caps,
 924};
 925
 926
 927/* ------------------------------------------------------------------------- */
 928
 929
 930/* PCI probe */
 931static int __devinit ark_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 932{
 933        struct fb_info *info;
 934        struct arkfb_info *par;
 935        int rc;
 936        u8 regval;
 937
 938        /* Ignore secondary VGA device because there is no VGA arbitration */
 939        if (! svga_primary_device(dev)) {
 940                dev_info(&(dev->dev), "ignoring secondary device\n");
 941                return -ENODEV;
 942        }
 943
 944        /* Allocate and fill driver data structure */
 945        info = framebuffer_alloc(sizeof(struct arkfb_info), &(dev->dev));
 946        if (! info) {
 947                dev_err(&(dev->dev), "cannot allocate memory\n");
 948                return -ENOMEM;
 949        }
 950
 951        par = info->par;
 952        mutex_init(&par->open_lock);
 953
 954        info->flags = FBINFO_PARTIAL_PAN_OK | FBINFO_HWACCEL_YPAN;
 955        info->fbops = &arkfb_ops;
 956
 957        /* Prepare PCI device */
 958        rc = pci_enable_device(dev);
 959        if (rc < 0) {
 960                dev_err(info->device, "cannot enable PCI device\n");
 961                goto err_enable_device;
 962        }
 963
 964        rc = pci_request_regions(dev, "arkfb");
 965        if (rc < 0) {
 966                dev_err(info->device, "cannot reserve framebuffer region\n");
 967                goto err_request_regions;
 968        }
 969
 970        par->dac = ics5342_init(ark_dac_read_regs, ark_dac_write_regs, info);
 971        if (! par->dac) {
 972                rc = -ENOMEM;
 973                dev_err(info->device, "RAMDAC initialization failed\n");
 974                goto err_dac;
 975        }
 976
 977        info->fix.smem_start = pci_resource_start(dev, 0);
 978        info->fix.smem_len = pci_resource_len(dev, 0);
 979
 980        /* Map physical IO memory address into kernel space */
 981        info->screen_base = pci_iomap(dev, 0, 0);
 982        if (! info->screen_base) {
 983                rc = -ENOMEM;
 984                dev_err(info->device, "iomap for framebuffer failed\n");
 985                goto err_iomap;
 986        }
 987
 988        /* FIXME get memsize */
 989        regval = vga_rseq(NULL, 0x10);
 990        info->screen_size = (1 << (regval >> 6)) << 20;
 991        info->fix.smem_len = info->screen_size;
 992
 993        strcpy(info->fix.id, "ARK 2000PV");
 994        info->fix.mmio_start = 0;
 995        info->fix.mmio_len = 0;
 996        info->fix.type = FB_TYPE_PACKED_PIXELS;
 997        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 998        info->fix.ypanstep = 0;
 999        info->fix.accel = FB_ACCEL_NONE;
1000        info->pseudo_palette = (void*) (par->pseudo_palette);
1001
1002        /* Prepare startup mode */
1003        rc = fb_find_mode(&(info->var), info, mode_option, NULL, 0, NULL, 8);
1004        if (! ((rc == 1) || (rc == 2))) {
1005                rc = -EINVAL;
1006                dev_err(info->device, "mode %s not found\n", mode_option);
1007                goto err_find_mode;
1008        }
1009
1010        rc = fb_alloc_cmap(&info->cmap, 256, 0);
1011        if (rc < 0) {
1012                dev_err(info->device, "cannot allocate colormap\n");
1013                goto err_alloc_cmap;
1014        }
1015
1016        rc = register_framebuffer(info);
1017        if (rc < 0) {
1018                dev_err(info->device, "cannot register framebugger\n");
1019                goto err_reg_fb;
1020        }
1021
1022        printk(KERN_INFO "fb%d: %s on %s, %d MB RAM\n", info->node, info->fix.id,
1023                 pci_name(dev), info->fix.smem_len >> 20);
1024
1025        /* Record a reference to the driver data */
1026        pci_set_drvdata(dev, info);
1027
1028#ifdef CONFIG_MTRR
1029        if (mtrr) {
1030                par->mtrr_reg = -1;
1031                par->mtrr_reg = mtrr_add(info->fix.smem_start, info->fix.smem_len, MTRR_TYPE_WRCOMB, 1);
1032        }
1033#endif
1034
1035        return 0;
1036
1037        /* Error handling */
1038err_reg_fb:
1039        fb_dealloc_cmap(&info->cmap);
1040err_alloc_cmap:
1041err_find_mode:
1042        pci_iounmap(dev, info->screen_base);
1043err_iomap:
1044        dac_release(par->dac);
1045err_dac:
1046        pci_release_regions(dev);
1047err_request_regions:
1048/*      pci_disable_device(dev); */
1049err_enable_device:
1050        framebuffer_release(info);
1051        return rc;
1052}
1053
1054/* PCI remove */
1055
1056static void __devexit ark_pci_remove(struct pci_dev *dev)
1057{
1058        struct fb_info *info = pci_get_drvdata(dev);
1059
1060        if (info) {
1061                struct arkfb_info *par = info->par;
1062
1063#ifdef CONFIG_MTRR
1064                if (par->mtrr_reg >= 0) {
1065                        mtrr_del(par->mtrr_reg, 0, 0);
1066                        par->mtrr_reg = -1;
1067                }
1068#endif
1069
1070                dac_release(par->dac);
1071                unregister_framebuffer(info);
1072                fb_dealloc_cmap(&info->cmap);
1073
1074                pci_iounmap(dev, info->screen_base);
1075                pci_release_regions(dev);
1076/*              pci_disable_device(dev); */
1077
1078                pci_set_drvdata(dev, NULL);
1079                framebuffer_release(info);
1080        }
1081}
1082
1083
1084#ifdef CONFIG_PM
1085/* PCI suspend */
1086
1087static int ark_pci_suspend (struct pci_dev* dev, pm_message_t state)
1088{
1089        struct fb_info *info = pci_get_drvdata(dev);
1090        struct arkfb_info *par = info->par;
1091
1092        dev_info(info->device, "suspend\n");
1093
1094        acquire_console_sem();
1095        mutex_lock(&(par->open_lock));
1096
1097        if ((state.event == PM_EVENT_FREEZE) || (par->ref_count == 0)) {
1098                mutex_unlock(&(par->open_lock));
1099                release_console_sem();
1100                return 0;
1101        }
1102
1103        fb_set_suspend(info, 1);
1104
1105        pci_save_state(dev);
1106        pci_disable_device(dev);
1107        pci_set_power_state(dev, pci_choose_state(dev, state));
1108
1109        mutex_unlock(&(par->open_lock));
1110        release_console_sem();
1111
1112        return 0;
1113}
1114
1115
1116/* PCI resume */
1117
1118static int ark_pci_resume (struct pci_dev* dev)
1119{
1120        struct fb_info *info = pci_get_drvdata(dev);
1121        struct arkfb_info *par = info->par;
1122
1123        dev_info(info->device, "resume\n");
1124
1125        acquire_console_sem();
1126        mutex_lock(&(par->open_lock));
1127
1128        if (par->ref_count == 0)
1129                goto fail;
1130
1131        pci_set_power_state(dev, PCI_D0);
1132        pci_restore_state(dev);
1133
1134        if (pci_enable_device(dev))
1135                goto fail;
1136
1137        pci_set_master(dev);
1138
1139        arkfb_set_par(info);
1140        fb_set_suspend(info, 0);
1141
1142fail:
1143        mutex_unlock(&(par->open_lock));
1144        release_console_sem();
1145        return 0;
1146}
1147#else
1148#define ark_pci_suspend NULL
1149#define ark_pci_resume NULL
1150#endif /* CONFIG_PM */
1151
1152/* List of boards that we are trying to support */
1153
1154static struct pci_device_id ark_devices[] __devinitdata = {
1155        {PCI_DEVICE(0xEDD8, 0xA099)},
1156        {0, 0, 0, 0, 0, 0, 0}
1157};
1158
1159
1160MODULE_DEVICE_TABLE(pci, ark_devices);
1161
1162static struct pci_driver arkfb_pci_driver = {
1163        .name           = "arkfb",
1164        .id_table       = ark_devices,
1165        .probe          = ark_pci_probe,
1166        .remove         = __devexit_p(ark_pci_remove),
1167        .suspend        = ark_pci_suspend,
1168        .resume         = ark_pci_resume,
1169};
1170
1171/* Cleanup */
1172
1173static void __exit arkfb_cleanup(void)
1174{
1175        pr_debug("arkfb: cleaning up\n");
1176        pci_unregister_driver(&arkfb_pci_driver);
1177}
1178
1179/* Driver Initialisation */
1180
1181static int __init arkfb_init(void)
1182{
1183
1184#ifndef MODULE
1185        char *option = NULL;
1186
1187        if (fb_get_options("arkfb", &option))
1188                return -ENODEV;
1189
1190        if (option && *option)
1191                mode_option = option;
1192#endif
1193
1194        pr_debug("arkfb: initializing\n");
1195        return pci_register_driver(&arkfb_pci_driver);
1196}
1197
1198module_init(arkfb_init);
1199module_exit(arkfb_cleanup);
1200