1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <inttypes.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include "byteswap.h"
#include "fbtools.h"
#include "matrox.h"
/* ---------------------------------------------------------------------- */
/* generic */
void (*gfx_scaler_on)(int offscreen, int pitch, int width, int height,
int left, int right, int top, int bottom);
void (*gfx_scaler_off)(void);
static unsigned char *bmmio;
static uint32_t *mmio;
static void
wrio4(int adr, unsigned long val)
{
#if BYTE_ORDER == LITTLE_ENDIAN
mmio[adr] = val;
#else
mmio[adr] = SWAP4(val);
#endif
/* usleep(10); */
}
/* ---------------------------------------------------------------------- */
/* Matrox G200/G400 */
#define BES_BASE 0x3d00
#define BESA1ORG ((BES_BASE+0x00)>>2)
#define BESA2ORG ((BES_BASE+0x04)>>2)
#define BESB1ORG ((BES_BASE+0x08)>>2)
#define BESB2ORG ((BES_BASE+0x0c)>>2)
#define BESA1CORG ((BES_BASE+0x10)>>2)
#define BESA2CORG ((BES_BASE+0x14)>>2)
#define BESB1CORG ((BES_BASE+0x18)>>2)
#define BESB2CORG ((BES_BASE+0x1c)>>2)
#define BESCTL ((BES_BASE+0x20)>>2)
#define BESPITCH ((BES_BASE+0x24)>>2)
#define BESHCOORD ((BES_BASE+0x28)>>2)
#define BESVCOORD ((BES_BASE+0x2c)>>2)
#define BESHISCAL ((BES_BASE+0x30)>>2)
#define BESVISCAL ((BES_BASE+0x34)>>2)
#define BESHSRCST ((BES_BASE+0x38)>>2)
#define BESHSRCEND ((BES_BASE+0x3c)>>2)
#define BESV1WGHT ((BES_BASE+0x48)>>2)
#define BESV2WGHT ((BES_BASE+0x4c)>>2)
#define BESHSRCLST ((BES_BASE+0x50)>>2)
#define BESV1SRCLST ((BES_BASE+0x54)>>2)
#define BESV2SRCLST ((BES_BASE+0x58)>>2)
#define BESGLOBCTL ((BES_BASE+0xc0)>>2)
#define BESSTATUS ((BES_BASE+0xc4)>>2)
#define PALWTADD 0x3c00
#define X_DATAREG 0x3c0a
#define XKEYOPMODE 0x51
static void
matrox_scaler_on(int offscreen, int pitch, int width, int height,
int left, int right, int top, int bottom)
{
/* color keying (turn it off) */
bmmio[PALWTADD] = XKEYOPMODE;
bmmio[X_DATAREG] = 0;
/* src */
wrio4(BESA1ORG, offscreen);
wrio4(BESA2ORG, offscreen);
wrio4(BESB1ORG, offscreen);
wrio4(BESB2ORG, offscreen);
wrio4(BESPITCH, pitch/2);
/* dest */
wrio4(BESHCOORD, (left << 16) | right);
wrio4(BESVCOORD, (top << 16) | bottom);
/* scale horiz */
wrio4(BESHISCAL, width*65536/(right-left) & 0x001ffffc);
wrio4(BESHSRCST, 0 << 16);
wrio4(BESHSRCEND, width << 16);
wrio4(BESHSRCLST, (width-1) << 16);
/* scale vert */
wrio4(BESVISCAL, height*65536/(bottom-top) & 0x001ffffc);
wrio4(BESV1WGHT, 0);
wrio4(BESV2WGHT, 0);
wrio4(BESV1SRCLST, height-1);
wrio4(BESV2SRCLST, height-1);
/* turn on (enable, horizontal+vertical interpolation filters */
wrio4(BESCTL, (1 << 0) | (1 << 10) | (1 << 11));
wrio4(BESGLOBCTL, 0);
}
static void
matrox_scaler_off(void)
{
/* turn off */
wrio4(BESCTL, 0);
}
/* ---------------------------------------------------------------------- */
/* ATI Mach64 VT+GT */
#define OVERLAY_X_Y_START 0x0000
#define OVERLAY_X_Y_END 0x0001
#define OVERLAY_VIDEO_KEY_CLR 0x0002
#define OVERLAY_VIDEO_KEY_MSK 0x0003
#define OVERLAY_GRAPHICS_KEY_CLR 0x0004
#define OVERLAY_GRAPHICS_KEY_MSK 0x0005
#define OVERLAY_KEY_CNTL 0x0006
#define OVERLAY_SCALE_INC 0x0008
#define OVERLAY_SCALE_CNTL 0x0009
#define SCALER_HEIGHT_WIDTH 0x000a
#define SCALER_TEST 0x000b
#define SCALER_BUF0_OFFSET 0x000d
#define SCALER_BUF1_OFFSET 0x000e
#define SCALER_BUF_PITCH 0x000f
#define VIDEO_FORMAT 0x0012
#define CAPTURE_CONFIG 0x0014
#define SCALER_COLOR_CNTL 0x0054
#define SCALER_H_COEFF0 0x0055
#define SCALER_H_COEFF1 0x0056
#define SCALER_H_COEFF2 0x0057
#define SCALER_H_COEFF3 0x0058
#define SCALER_H_COEFF4 0x0059
/* does'nt work for all color depth yet... */
static void
mach64_scaler_on(int offscreen, int pitch, int width, int height,
int left, int right, int top, int bottom)
{
int v,h;
v = (height << 12) / (bottom-top);
h = (width << 12) / (right-left);
wrio4(OVERLAY_SCALE_CNTL, 0);
wrio4(OVERLAY_SCALE_INC, (h << 16) | v);
wrio4(VIDEO_FORMAT, (12 << 16));
wrio4(SCALER_BUF0_OFFSET, offscreen);
wrio4(SCALER_BUF1_OFFSET, offscreen);
wrio4(SCALER_BUF_PITCH, pitch/2);
wrio4(SCALER_HEIGHT_WIDTH, (width << 16) | height);
wrio4(CAPTURE_CONFIG, 0);
#if 1
/* from gatos, don't know what this does, have no specs :-( */
wrio4(SCALER_COLOR_CNTL, 0x00101000);
wrio4(SCALER_H_COEFF0, 0x00002000);
wrio4(SCALER_H_COEFF1, 0x0D06200D);
wrio4(SCALER_H_COEFF2, 0x0D0A1C0D);
wrio4(SCALER_H_COEFF3, 0x0C0E1A0C);
wrio4(SCALER_H_COEFF4, 0x0C14140C);
#endif
wrio4(OVERLAY_X_Y_START, (left << 16) | top);
wrio4(OVERLAY_X_Y_END, ((right-1) << 16) | (bottom-1));
wrio4(OVERLAY_VIDEO_KEY_MSK, 0);
wrio4(OVERLAY_VIDEO_KEY_CLR, 0);
wrio4(OVERLAY_KEY_CNTL, 1);
wrio4(SCALER_TEST, 0); /* 2 == test mode */
wrio4(OVERLAY_SCALE_CNTL, (1<<31) | (1<<30));
}
static void
mach64_scaler_off(void)
{
/* off */
wrio4(OVERLAY_SCALE_CNTL, 0);
}
/* ---------------------------------------------------------------------- */
/* generic */
int
gfx_init(int fd)
{
int off;
switch (fb_fix.accel) {
case FB_ACCEL_MATROX_MGAG200:
#ifdef FB_ACCEL_MATROX_MGAG400
case FB_ACCEL_MATROX_MGAG400:
#endif
gfx_scaler_on = matrox_scaler_on;
gfx_scaler_off = matrox_scaler_off;
break;
case FB_ACCEL_ATI_MACH64VT:
case FB_ACCEL_ATI_MACH64GT:
gfx_scaler_on = mach64_scaler_on;
gfx_scaler_off = mach64_scaler_off;
break;
default:
return -1;
}
fb_var.accel_flags = 0;
if (0 != ioctl(fd,FBIOPUT_VSCREENINFO,&fb_var)) {
perror("FBIOPUT_VSCREENINFO");
return -1;
}
bmmio = mmap(NULL, fb_fix.mmio_len, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, fb_fix.smem_len);
if ((void*)-1 == bmmio) {
perror("mmap");
return -1;
}
off = (unsigned long)fb_fix.mmio_start -
((unsigned long)fb_fix.mmio_start & ~(getpagesize()-1));
bmmio += off;
mmio = (uint32_t*)bmmio;
return 0;
}
|