3 * \brief Hardware Acceleration for S3 Savage cards (backend scaler)
6 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
8 * (c) 2002-2009 Technische Universität Dresden
9 * This file is part of TUD:OS and distributed under the terms of the
10 * GNU General Public License 2.
11 * Please see the COPYING-GPL-2 file for details.
14 /* Programming of backend scaler for "new" savage chips
15 * (Savage/MX{-MV}, Savage/IX{-MV}, SuperSavage, Savage 2000) */
17 #include <l4/sys/types.h>
21 #include "savage_regs.h"
25 /* Stream Processor 1 */
27 #define PRI_STREAM_FBUF_ADDR0 0x81c0
28 #define PRI_STREAM_FBUF_ADDR1 0x81c4
29 #define PRI_STREAM_STRIDE 0x81c8
30 #define PRI_STREAM_BUFFERSIZE 0x8214
32 #define SEC_STREAM_CKEY_LOW 0x8184
33 #define SEC_STREAM_CKEY_UPPER 0x8194
34 #define BLEND_CONTROL 0x8190
35 #define SEC_STREAM_COLOR_CONVERT1 0x8198
36 #define SEC_STREAM_COLOR_CONVERT2 0x819c
37 #define SEC_STREAM_COLOR_CONVERT3 0x81e4
38 #define SEC_STREAM_HSCALING 0x81a0
39 #define SEC_STREAM_BUFFERSIZE 0x81a8
40 #define SEC_STREAM_HSCALE_NORMALIZE 0x81ac
41 #define SEC_STREAM_VSCALING 0x81e8
42 #define SEC_STREAM_FBUF_ADDR0 0x81d0
43 #define SEC_STREAM_FBUF_ADDR1 0x81d4
44 #define SEC_STREAM_FBUF_ADDR2 0x81ec
45 #define SEC_STREAM_STRIDE 0x81d8
46 #define SEC_STREAM_WINDOW_START 0x81f8
47 #define SEC_STREAM_WINDOW_SZ 0x81fc
48 #define SEC_STREAM_TILE_OFF 0x821c
49 #define SEC_STREAM_OPAQUE_OVERLAY 0x81dc
52 /* Stream Processor 2 */
54 #define PRI_STREAM2_FBUF_ADDR0 0x81b0
55 #define PRI_STREAM2_FBUF_ADDR1 0x81b4
56 #define PRI_STREAM2_STRIDE 0x81b8
57 #define PRI_STREAM2_BUFFERSIZE 0x8218
59 #define SEC_STREAM2_CKEY_LOW 0x8188
60 #define SEC_STREAM2_CKEY_UPPER 0x818c
61 #define SEC_STREAM2_HSCALING 0x81a4
62 #define SEC_STREAM2_VSCALING 0x8204
63 #define SEC_STREAM2_BUFFERSIZE 0x81ac
64 #define SEC_STREAM2_FBUF_ADDR0 0x81bc
65 #define SEC_STREAM2_FBUF_ADDR1 0x81e0
66 #define SEC_STREAM2_FBUF_ADDR2 0x8208
67 #define SEC_STREAM2_STRIDE_LPB 0x81cc
68 #define SEC_STREAM2_COLOR_CONVERT1 0x81f0
69 #define SEC_STREAM2_COLOR_CONVERT2 0x81f4
70 #define SEC_STREAM2_COLOR_CONVERT3 0x8200
71 #define SEC_STREAM2_WINDOW_START 0x820c
72 #define SEC_STREAM2_WINDOW_SZ 0x8210
73 #define SEC_STREAM2_OPAQUE_OVERLAY 0x8180
75 static unsigned int savage_blendBase;
76 static int ck_lo, ck_hi, ck_active = 0;
79 savage_set_colorkey(void)
83 /* disable colorkey */
84 savage_out32(SEC_STREAM_CKEY_LOW, 0);
85 savage_out32(SEC_STREAM_CKEY_UPPER, 0);
89 savage_out32(SEC_STREAM_CKEY_LOW, ck_lo);
90 savage_out32(SEC_STREAM_CKEY_UPPER, ck_hi);
93 savage_out32(BLEND_CONTROL, savage_blendBase);
97 savage_set_grkey(const vidix_grkey_t *grkey)
99 if (grkey->ckey.op == CKEY_TRUE)
104 ck_lo = ck_hi = ((grkey->ckey.red & 0xF8)<<16)
105 | ((grkey->ckey.green & 0xF8)<< 8)
106 | ((grkey->ckey.blue & 0xF8) );
111 ck_lo = ck_hi = ((grkey->ckey.red & 0xF8)<<16)
112 | ((grkey->ckey.green & 0xFC)<< 8)
113 | ((grkey->ckey.blue & 0xF8) );
119 ck_lo = ck_hi = ((grkey->ckey.red & 0xFF)<<16)
120 | ((grkey->ckey.green & 0xFF)<< 8)
121 | ((grkey->ckey.blue & 0xFF) );
127 savage_set_colorkey();
133 #define EXT_MISC_CTRL2 0x67
134 #define ENABLE_STREAM1 0x04
137 savage_get_blend_fourcc(unsigned int fourcc)
141 case IMGFMT_YUY2: /* packed */
142 case IMGFMT_YV12: /* planar: translate into YUY2 */
143 case IMGFMT_I420: /* planar: translate into YUY2 */
145 case IMGFMT_Y211: /* packed */
147 case IMGFMT_RGB15: /* packed */
149 case IMGFMT_RGB16: /* packed */
157 savage_streams_on(vidix_playback_t *config)
159 /* Unlock extended registers. */
160 vga_out16(0x3d4, 0x4838);
161 vga_out16(0x3d4, 0xa039);
162 vga_out16(0x3c4, 0x0608);
164 vga_out8(0x3d4, EXT_MISC_CTRL2);
166 if (S3_SAVAGEMOB_SERIES(savage_chip)
167 || (savage_chip == S3_SUPERSAVAGE)
168 || (savage_chip == S3_SAVAGE2000))
170 unsigned char jStreamsControl = vga_in8(0x3d5) | ENABLE_STREAM1;
172 /* Wait for VBLANK. */
173 savage_vertical_retrace_wait();
175 /* Fire up streams! */
176 vga_out16(0x3d4, (jStreamsControl << 8) | EXT_MISC_CTRL2);
178 savage_blendBase = savage_get_blend_fourcc(config->fourcc)<<9;
179 savage_out32(BLEND_CONTROL, savage_blendBase);
181 /* These values specify brightness, contrast, saturation and hue. */
182 savage_out32(SEC_STREAM_COLOR_CONVERT1, 0x0000C892);
183 savage_out32(SEC_STREAM_COLOR_CONVERT2, 0x00039F9A);
184 savage_out32(SEC_STREAM_COLOR_CONVERT3, 0x01F1547E);
188 /* old engine not supported */
191 /* Wait for VBLANK. */
192 savage_vertical_retrace_wait();
196 savage_compute_framesize(vidix_playback_t *info)
202 case IMGFMT_I420: /* translate into YUY2 */
203 case IMGFMT_YV12: /* translate into YV12 */
205 awidth = ((info->src.w<<1)+15)&~15;
206 info->frame_size = awidth*info->src.h;
209 awidth = (((info->src.w<<1)+15)&~15)/2;
210 info->frame_size = awidth*info->src.h;
214 // align to 1MB boundary */
215 info->frame_size = (info->frame_size + 1024*1024 - 1) & ~(1024*1024-1);
219 savage_init_video_new(vidix_playback_t *config)
221 int src_h = config->src.h;
222 int src_w = config->src.w;
223 int drw_w = config->dest.w;
224 int drw_h = config->dest.h;
227 pitch = ((src_w<<1)+15) & ~15;
229 savage_compute_framesize(config);
231 config->offsets[0] = 0;
232 config->offset.y = config->offset.u = config->offset.v = 0;
234 if ( config->fourcc == IMGFMT_IYUV
235 || config->fourcc == IMGFMT_YV12
236 || config->fourcc == IMGFMT_I420)
238 config->offset.y = 0;
239 config->offset.u = (pitch*src_h + 15)&~15;
240 config->offset.v = (config->offset.u + (pitch*src_h>>2) + 15)&~15;
242 if (config->fourcc == IMGFMT_I420 || config->fourcc == IMGFMT_IYUV)
246 tmp = config->offset.u;
247 config->offset.u = config->offset.v;
248 config->offset.v = tmp;
252 else if (config->fourcc == IMGFMT_YVU9)
254 config->offset.y = 0;
255 config->offset.u = (pitch*src_h + 15)&~15;
256 config->offset.v = (config->offset.u + (pitch*src_h>>4) + 15)&~15;
260 (hw_vid_mem_size - config->frame_size * config->num_frames) & 0xfff00000;
261 config->dga_addr = (char *)hw_map_vid_mem_addr + offset;
263 /* Calculate horizontal and vertical scale factors. */
264 if (savage_chip == S3_SAVAGE2000)
266 savage_out32(SEC_STREAM_HSCALING, (65536 * src_w / drw_w) & 0x1FFFFF );
268 savage_out32(SEC_STREAM_HSCALE_NORMALIZE,
269 ((2048 * src_w / drw_w) & 0x7ff) << 16);
271 savage_out32(SEC_STREAM_HSCALE_NORMALIZE, 2048 << 16);
272 savage_out32(SEC_STREAM_VSCALING, (65536 * src_h / drw_h) & 0x1FFFFF);
276 savage_out32(SEC_STREAM_HSCALING,
277 ((src_w & 0xfff)<<20) | ((65536 * src_w / drw_w) & 0x1FFFF));
278 /* XXX need to add 00040000 if src stride > 2048 */
279 savage_out32(SEC_STREAM_VSCALING,
280 ((src_h & 0xfff)<<20) | ((65536 * src_h / drw_h) & 0x1FFFF));
283 /* Set surface location and stride. We use x1>>15 because all surfaces
284 * are 2 bytes/pixel. */
285 savage_out32(SEC_STREAM_FBUF_ADDR0,
286 (offset+(config->src.x>>15)) & 0x7ffff0);
287 savage_out32(SEC_STREAM_STRIDE, pitch & 0xfff);
288 savage_out32(SEC_STREAM_WINDOW_START,
289 ((config->dest.x+1)<<16) | (config->dest.y+1));
290 savage_out32(SEC_STREAM_WINDOW_SZ, ((drw_w) << 16) | drw_h);
292 /* Set color key on primary. */
293 savage_set_colorkey();
295 /* Set FIFO L2 on second stream. */
297 pitch = (pitch+7)/8 - 4;
298 vga_out8(0x3d4, 0x92);
299 vga_out8(0x3d5, (vga_in8(0x3d5) & 0x40) | (pitch >> 8) | 0x80);
300 vga_out8(0x3d4, 0x93);
301 vga_out8(0x3d5, pitch);
308 savage_start_video(void)
310 savage_blendBase |= 0x08;
311 savage_out32(BLEND_CONTROL, savage_blendBase);
315 savage_stop_video(void)
317 savage_blendBase &= ~0x08;
318 savage_out32(BLEND_CONTROL, savage_blendBase);
322 savage_init_video(vidix_playback_t *config)
324 savage_streams_on(config);
325 savage_init_video_new(config);
331 savage_vid_init(con_accel_t *accel)
333 if (S3_SAVAGEMOB_SERIES(savage_chip)
334 || (savage_chip == S3_SUPERSAVAGE)
335 || (savage_chip == S3_SAVAGE2000))
337 accel->cscs_init = savage_init_video;
338 accel->cscs_start = savage_start_video;
339 accel->cscs_stop = savage_stop_video;
340 accel->cscs_grkey = savage_set_grkey;
341 accel->caps |= ACCEL_FAST_CSCS_YUY2 | ACCEL_COLOR_KEY;
343 /* old Savage chips not supported */