]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/con_hw/savage_vid.c
393f804c378b3449cb969416a4c4546bb2e99ddd
[l4.git] / l4 / pkg / l4con / server / src / con_hw / savage_vid.c
1 /*!
2  * \file        savage_vid.c
3  * \brief       Hardware Acceleration for S3 Savage cards (backend scaler)
4  *
5  * \date        07/2002
6  * \author      Frank Mehnert <fm3@os.inf.tu-dresden.de> */
7 /*
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.
12  */
13
14 /* Programming of backend scaler for "new" savage chips
15  * (Savage/MX{-MV}, Savage/IX{-MV}, SuperSavage, Savage 2000) */
16
17 #include <l4/sys/types.h>
18
19 #include "init.h"
20 #include "savage.h"
21 #include "savage_regs.h"
22 #include "vidix.h"
23 #include "fourcc.h"
24
25 /* Stream Processor 1 */
26
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
31
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
50
51
52 /* Stream Processor 2 */
53
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
58
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
74
75 static unsigned int savage_blendBase;
76 static int ck_lo, ck_hi, ck_active = 0;
77
78 static void
79 savage_set_colorkey(void)
80 {
81   if (!ck_active)
82     {
83       /* disable colorkey */
84       savage_out32(SEC_STREAM_CKEY_LOW, 0);
85       savage_out32(SEC_STREAM_CKEY_UPPER, 0);
86     }
87   else
88     {
89       savage_out32(SEC_STREAM_CKEY_LOW, ck_lo);
90       savage_out32(SEC_STREAM_CKEY_UPPER, ck_hi);
91     }
92
93   savage_out32(BLEND_CONTROL, savage_blendBase);
94 }
95
96 static void
97 savage_set_grkey(const vidix_grkey_t *grkey)
98 {
99   if (grkey->ckey.op == CKEY_TRUE)
100     {
101       switch (hw_bits)
102         {
103         case 15:
104           ck_lo = ck_hi = ((grkey->ckey.red   & 0xF8)<<16)
105                         | ((grkey->ckey.green & 0xF8)<< 8)
106                         | ((grkey->ckey.blue  & 0xF8)    );
107           ck_lo |= 0x45000000;
108           ck_hi |= 0x45000000;
109           break;
110         case 16:
111           ck_lo = ck_hi = ((grkey->ckey.red   & 0xF8)<<16)
112                         | ((grkey->ckey.green & 0xFC)<< 8)
113                         | ((grkey->ckey.blue  & 0xF8)    );
114           ck_lo |= 0x46000000;
115           ck_hi |= 0x46020002;
116           break;
117         case 24:
118         default:
119           ck_lo = ck_hi = ((grkey->ckey.red   & 0xFF)<<16)
120                         | ((grkey->ckey.green & 0xFF)<< 8)
121                         | ((grkey->ckey.blue  & 0xFF)    );
122           ck_lo |= 0x47000000;
123           ck_hi |= 0x47000000;
124           break;
125         }
126       ck_active = 1;
127       savage_set_colorkey();
128     }
129   else
130     ck_active = 0;
131 }
132
133 #define EXT_MISC_CTRL2              0x67
134 #define ENABLE_STREAM1              0x04
135
136 static unsigned int
137 savage_get_blend_fourcc(unsigned int fourcc)
138 {
139   switch (fourcc)
140     {
141     case IMGFMT_YUY2:   /* packed */
142     case IMGFMT_YV12:   /* planar: translate into YUY2 */
143     case IMGFMT_I420:   /* planar: translate into YUY2 */
144       return 1;
145     case IMGFMT_Y211:   /* packed */
146       return 4;
147     case IMGFMT_RGB15:  /* packed */
148       return 3;
149     case IMGFMT_RGB16:  /* packed */
150       return 5;
151     default:
152       return 0;
153     }
154 }
155
156 static void
157 savage_streams_on(vidix_playback_t *config)
158 {
159   /* Unlock extended registers. */
160   vga_out16(0x3d4, 0x4838);
161   vga_out16(0x3d4, 0xa039);
162   vga_out16(0x3c4, 0x0608);
163
164   vga_out8(0x3d4, EXT_MISC_CTRL2);
165
166   if (S3_SAVAGEMOB_SERIES(savage_chip)
167       || (savage_chip == S3_SUPERSAVAGE)
168       || (savage_chip == S3_SAVAGE2000))
169     {
170       unsigned char jStreamsControl = vga_in8(0x3d5) | ENABLE_STREAM1;
171
172       /* Wait for VBLANK. */
173       savage_vertical_retrace_wait();
174
175       /* Fire up streams! */
176       vga_out16(0x3d4, (jStreamsControl << 8) | EXT_MISC_CTRL2);
177
178       savage_blendBase = savage_get_blend_fourcc(config->fourcc)<<9;
179       savage_out32(BLEND_CONTROL, savage_blendBase);
180
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);
185     }
186   else
187     {
188       /* old engine not supported */
189     }
190
191   /* Wait for VBLANK. */ 
192   savage_vertical_retrace_wait();
193 }
194
195 static void
196 savage_compute_framesize(vidix_playback_t *info)
197 {
198   unsigned awidth;
199
200   switch(info->fourcc)
201     {
202     case IMGFMT_I420: /* translate into YUY2 */
203     case IMGFMT_YV12: /* translate into YV12 */
204     case IMGFMT_YUY2:
205       awidth = ((info->src.w<<1)+15)&~15;
206       info->frame_size = awidth*info->src.h;
207       break;
208     case IMGFMT_Y211:
209       awidth = (((info->src.w<<1)+15)&~15)/2;
210       info->frame_size = awidth*info->src.h;
211       break;
212     }
213
214   // align to 1MB boundary */
215   info->frame_size = (info->frame_size + 1024*1024 - 1) & ~(1024*1024-1);
216 }
217
218 static int
219 savage_init_video_new(vidix_playback_t *config)
220 {
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;
225   int pitch, offset;
226
227   pitch = ((src_w<<1)+15) & ~15;
228
229   savage_compute_framesize(config);
230
231   config->offsets[0] = 0;
232   config->offset.y = config->offset.u = config->offset.v = 0;
233
234   if (   config->fourcc == IMGFMT_IYUV
235       || config->fourcc == IMGFMT_YV12
236       || config->fourcc == IMGFMT_I420)
237     {
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;
241
242       if (config->fourcc == IMGFMT_I420 || config->fourcc == IMGFMT_IYUV)
243         {
244 #if 0
245           l4_uint32_t tmp;
246           tmp = config->offset.u;
247           config->offset.u = config->offset.v;
248           config->offset.v = tmp;
249 #endif
250         }
251     }
252   else if (config->fourcc == IMGFMT_YVU9)
253     {
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;
257     }
258
259   offset =
260     (hw_vid_mem_size - config->frame_size * config->num_frames) & 0xfff00000;
261   config->dga_addr = (char *)hw_map_vid_mem_addr + offset;
262
263   /* Calculate horizontal and vertical scale factors. */
264   if (savage_chip == S3_SAVAGE2000)
265     {
266       savage_out32(SEC_STREAM_HSCALING, (65536 * src_w / drw_w) & 0x1FFFFF );
267       if (src_w < drw_w)
268         savage_out32(SEC_STREAM_HSCALE_NORMALIZE,
269                      ((2048 * src_w / drw_w) & 0x7ff) << 16);
270       else
271         savage_out32(SEC_STREAM_HSCALE_NORMALIZE, 2048 << 16);
272       savage_out32(SEC_STREAM_VSCALING, (65536 * src_h / drw_h) & 0x1FFFFF);
273     }
274   else
275     {
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));
281     }
282
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);
291
292   /* Set color key on primary. */
293   savage_set_colorkey();
294
295   /* Set FIFO L2 on second stream. */
296     {
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);
302     }
303
304   return 0;
305 }
306
307 static void
308 savage_start_video(void)
309 {
310   savage_blendBase |= 0x08;
311   savage_out32(BLEND_CONTROL, savage_blendBase);
312 }
313
314 static void
315 savage_stop_video(void)
316 {
317   savage_blendBase &= ~0x08;
318   savage_out32(BLEND_CONTROL, savage_blendBase);
319 }
320
321 static int
322 savage_init_video(vidix_playback_t *config)
323 {
324   savage_streams_on(config);
325   savage_init_video_new(config);
326
327   return 0;
328 }
329
330 void
331 savage_vid_init(con_accel_t *accel)
332 {
333   if (S3_SAVAGEMOB_SERIES(savage_chip)
334       || (savage_chip == S3_SUPERSAVAGE)
335       || (savage_chip == S3_SAVAGE2000))
336     {
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;
342     }
343   /* old Savage chips not supported */
344 }
345