linux/drivers/video/fbdev/geode/display_gx.c
<<
>>
Prefs
   1/*
   2 * Geode GX display controller.
   3 *
   4 *   Copyright (C) 2005 Arcom Control Systems Ltd.
   5 *
   6 *   Portions from AMD's original 2.4 driver:
   7 *     Copyright (C) 2004 Advanced Micro Devices, Inc.
   8 *
   9 *   This program is free software; you can redistribute it and/or modify it
  10 *   under the terms of the GNU General Public License as published by * the
  11 *   Free Software Foundation; either version 2 of the License, or * (at your
  12 *   option) any later version.
  13 */
  14#include <linux/spinlock.h>
  15#include <linux/fb.h>
  16#include <linux/delay.h>
  17#include <asm/io.h>
  18#include <asm/div64.h>
  19#include <asm/delay.h>
  20#include <linux/cs5535.h>
  21
  22#include "gxfb.h"
  23
  24unsigned int gx_frame_buffer_size(void)
  25{
  26        unsigned int val;
  27
  28        if (!cs5535_has_vsa2()) {
  29                uint32_t hi, lo;
  30
  31                /* The number of pages is (PMAX - PMIN)+1 */
  32                rdmsr(MSR_GLIU_P2D_RO0, lo, hi);
  33
  34                /* PMAX */
  35                val = ((hi & 0xff) << 12) | ((lo & 0xfff00000) >> 20);
  36                /* PMIN */
  37                val -= (lo & 0x000fffff);
  38                val += 1;
  39
  40                /* The page size is 4k */
  41                return (val << 12);
  42        }
  43
  44        /* FB size can be obtained from the VSA II */
  45        /* Virtual register class = 0x02 */
  46        /* VG_MEM_SIZE(512Kb units) = 0x00 */
  47
  48        outw(VSA_VR_UNLOCK, VSA_VRC_INDEX);
  49        outw(VSA_VR_MEM_SIZE, VSA_VRC_INDEX);
  50
  51        val = (unsigned int)(inw(VSA_VRC_DATA)) & 0xFFl;
  52        return (val << 19);
  53}
  54
  55int gx_line_delta(int xres, int bpp)
  56{
  57        /* Must be a multiple of 8 bytes. */
  58        return (xres * (bpp >> 3) + 7) & ~0x7;
  59}
  60
  61void gx_set_mode(struct fb_info *info)
  62{
  63        struct gxfb_par *par = info->par;
  64        u32 gcfg, dcfg;
  65        int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
  66        int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
  67
  68        /* Unlock the display controller registers. */
  69        write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK);
  70
  71        gcfg = read_dc(par, DC_GENERAL_CFG);
  72        dcfg = read_dc(par, DC_DISPLAY_CFG);
  73
  74        /* Disable the timing generator. */
  75        dcfg &= ~DC_DISPLAY_CFG_TGEN;
  76        write_dc(par, DC_DISPLAY_CFG, dcfg);
  77
  78        /* Wait for pending memory requests before disabling the FIFO load. */
  79        udelay(100);
  80
  81        /* Disable FIFO load and compression. */
  82        gcfg &= ~(DC_GENERAL_CFG_DFLE | DC_GENERAL_CFG_CMPE |
  83                        DC_GENERAL_CFG_DECE);
  84        write_dc(par, DC_GENERAL_CFG, gcfg);
  85
  86        /* Setup DCLK and its divisor. */
  87        gx_set_dclk_frequency(info);
  88
  89        /*
  90         * Setup new mode.
  91         */
  92
  93        /* Clear all unused feature bits. */
  94        gcfg &= DC_GENERAL_CFG_YUVM | DC_GENERAL_CFG_VDSE;
  95        dcfg = 0;
  96
  97        /* Set FIFO priority (default 6/5) and enable. */
  98        /* FIXME: increase fifo priority for 1280x1024 and higher modes? */
  99        gcfg |= (6 << DC_GENERAL_CFG_DFHPEL_SHIFT) |
 100                (5 << DC_GENERAL_CFG_DFHPSL_SHIFT) | DC_GENERAL_CFG_DFLE;
 101
 102        /* Framebuffer start offset. */
 103        write_dc(par, DC_FB_ST_OFFSET, 0);
 104
 105        /* Line delta and line buffer length. */
 106        write_dc(par, DC_GFX_PITCH, info->fix.line_length >> 3);
 107        write_dc(par, DC_LINE_SIZE,
 108                ((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2);
 109
 110
 111        /* Enable graphics and video data and unmask address lines. */
 112        dcfg |= DC_DISPLAY_CFG_GDEN | DC_DISPLAY_CFG_VDEN |
 113                DC_DISPLAY_CFG_A20M | DC_DISPLAY_CFG_A18M;
 114
 115        /* Set pixel format. */
 116        switch (info->var.bits_per_pixel) {
 117        case 8:
 118                dcfg |= DC_DISPLAY_CFG_DISP_MODE_8BPP;
 119                break;
 120        case 16:
 121                dcfg |= DC_DISPLAY_CFG_DISP_MODE_16BPP;
 122                break;
 123        case 32:
 124                dcfg |= DC_DISPLAY_CFG_DISP_MODE_24BPP;
 125                dcfg |= DC_DISPLAY_CFG_PALB;
 126                break;
 127        }
 128
 129        /* Enable timing generator. */
 130        dcfg |= DC_DISPLAY_CFG_TGEN;
 131
 132        /* Horizontal and vertical timings. */
 133        hactive = info->var.xres;
 134        hblankstart = hactive;
 135        hsyncstart = hblankstart + info->var.right_margin;
 136        hsyncend =  hsyncstart + info->var.hsync_len;
 137        hblankend = hsyncend + info->var.left_margin;
 138        htotal = hblankend;
 139
 140        vactive = info->var.yres;
 141        vblankstart = vactive;
 142        vsyncstart = vblankstart + info->var.lower_margin;
 143        vsyncend =  vsyncstart + info->var.vsync_len;
 144        vblankend = vsyncend + info->var.upper_margin;
 145        vtotal = vblankend;
 146
 147        write_dc(par, DC_H_ACTIVE_TIMING, (hactive - 1)    |
 148                        ((htotal - 1) << 16));
 149        write_dc(par, DC_H_BLANK_TIMING, (hblankstart - 1) |
 150                        ((hblankend - 1) << 16));
 151        write_dc(par, DC_H_SYNC_TIMING, (hsyncstart - 1)   |
 152                        ((hsyncend - 1) << 16));
 153
 154        write_dc(par, DC_V_ACTIVE_TIMING, (vactive - 1)    |
 155                        ((vtotal - 1) << 16));
 156        write_dc(par, DC_V_BLANK_TIMING, (vblankstart - 1) |
 157                        ((vblankend - 1) << 16));
 158        write_dc(par, DC_V_SYNC_TIMING, (vsyncstart - 1)   |
 159                        ((vsyncend - 1) << 16));
 160
 161        /* Write final register values. */
 162        write_dc(par, DC_DISPLAY_CFG, dcfg);
 163        write_dc(par, DC_GENERAL_CFG, gcfg);
 164
 165        gx_configure_display(info);
 166
 167        /* Relock display controller registers */
 168        write_dc(par, DC_UNLOCK, DC_UNLOCK_LOCK);
 169}
 170
 171void gx_set_hw_palette_reg(struct fb_info *info, unsigned regno,
 172                unsigned red, unsigned green, unsigned blue)
 173{
 174        struct gxfb_par *par = info->par;
 175        int val;
 176
 177        /* Hardware palette is in RGB 8-8-8 format. */
 178        val  = (red   << 8) & 0xff0000;
 179        val |= (green)      & 0x00ff00;
 180        val |= (blue  >> 8) & 0x0000ff;
 181
 182        write_dc(par, DC_PAL_ADDRESS, regno);
 183        write_dc(par, DC_PAL_DATA, val);
 184}
 185