aboutsummaryrefslogtreecommitdiffstats
path: root/console/matrox.c
blob: 73387a6c4aab677741c4c970f36140b742ae8608 (plain)
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;
}

Privacy Policy