xref: /haiku/src/add-ons/accelerants/via/engine/bes.c (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /* VIA Unichrome Back End Scaler functions */
2 /* Written by Rudolf Cornelissen 05/2002-2/2016 */
3 
4 #define MODULE_BIT 0x00000200
5 
6 #include "std.h"
7 
8 typedef struct move_overlay_info move_overlay_info;
9 
10 struct move_overlay_info
11 {
12 	uint32 hcoordv;		/* left and right edges of video output window */
13 	uint32 vcoordv;		/* top and bottom edges of video output window */
14 	uint32 hsrcstv;		/* horizontal source start in source buffer (clipping) */
15 	uint32 hsrcendv;	/* horizontal source end in source buffer (clipping) */
16 	uint32 v1srcstv;	/* vertical source start in source buffer (clipping) */
17 	uint32 a1orgv;		/* alternate source clipping via startadress of source buffer */
18 };
19 
20 static void eng_bes_calc_move_overlay(move_overlay_info *moi);
21 static void eng_bes_program_move_overlay(move_overlay_info moi);
22 
23 /* returns true if the current displaymode leaves enough bandwidth for overlay
24  * support, false if not. */
25 bool eng_bes_chk_bandwidth()
26 {
27 	float refresh, bandwidth;
28 	uint8 depth;
29 
30 	switch(si->dm.space)
31 	{
32 	case B_CMAP8:        depth =  8; break;
33 	case B_RGB15_LITTLE: depth = 16; break;
34 	case B_RGB16_LITTLE: depth = 16; break;
35 	case B_RGB32_LITTLE: depth = 32; break;
36 	default:
37 		LOG(8,("Overlay: Invalid colour depth 0x%08x\n", si->dm.space));
38 		return false;
39 	}
40 
41 	refresh =
42 		(si->dm.timing.pixel_clock * 1000) /
43 		(si->dm.timing.h_total * si->dm.timing.v_total);
44 	bandwidth =
45 		si->dm.timing.h_display * si->dm.timing.v_display * refresh * depth;
46 	LOG(8,("Overlay: Current mode's refreshrate is %.2fHz, bandwidth is %.0f\n",
47 		refresh, bandwidth));
48 
49 	switch (((CRTCR(MEMCLK)) & 0x70) >> 4)
50 	{
51 	case 0: /* SDR  66 */
52 		LOG(8,("Overlay: System memory is type SDR 66\n"));
53 		return false;
54 		break;
55 	case 1: /* SDR 100 */
56 		LOG(8,("Overlay: System memory is type SDR 100\n"));
57 		return false;
58 		break;
59 	case 2: /* SDR 133 */
60 		/* memory is too slow, sorry. */
61 		LOG(8,("Overlay: System memory is type SDR 133\n"));
62 		return false;
63 		break;
64 	case 3: /* DDR 100 (PC1600) */
65 		/* DDR100's basic limit... */
66 		LOG(8,("Overlay: System memory is type DDR 100\n"));
67 		if (bandwidth > 921600000.0) return false;
68 		/* ... but we have constraints at higher than 800x600 */
69 		if (si->dm.timing.h_display > 800)
70 		{
71 			if (depth != 8) return false;
72 			if (si->dm.timing.v_display > 768) return false;
73 			if (refresh > 60.2) return false;
74 		}
75 		break;
76 	case 4: /* DDR 133 (PC2100) */
77 		LOG(8,("Overlay: System memory is type DDR 133\n"));
78 		if (bandwidth > 4045440000.0) return false;
79 		break;
80 	case 5: /* DDR 166 (PC2700) */
81 		LOG(8,("Overlay: System memory is type DDR 166\n"));
82 		if (bandwidth > 5210000000.0) return false;//fixme: set more correct limit?
83 		break;
84 	case 6: /* DDR 200 (PC3200) */
85 		LOG(8,("Overlay: System memory is type DDR 200\n"));
86 		if (bandwidth > 6170000000.0) return false;//fixme: set more correct limit?
87 		break;
88 	default: /* not (yet?) used */
89 		LOG(8,("Overlay: System memory is (yet) unknown type!\n"));
90 		return false;
91 		break;
92 	}
93 
94 	return true;
95 }
96 
97 /* move the overlay output window in virtualscreens */
98 /* Note:
99  * si->dm.h_display_start and si->dm.v_display_start determine where the new
100  * output window is located! */
101 void eng_bes_move_overlay()
102 {
103 	move_overlay_info moi;
104 
105 	/* abort if overlay is not active */
106 	if (!si->overlay.active) return;
107 
108 	eng_bes_calc_move_overlay(&moi);
109 	eng_bes_program_move_overlay(moi);
110 }
111 
112 static void eng_bes_calc_move_overlay(move_overlay_info *moi)
113 {
114 	/* misc used variables */
115 	uint16 temp1, temp2;
116 	/* visible screen window in virtual workspaces */
117 	uint16 crtc_hstart, crtc_vstart, crtc_hend, crtc_vend;
118 
119 	/* do 'overlay follow head' in dualhead modes on dualhead cards */
120 	if (si->ps.secondary_head)
121 	{
122 		switch (si->dm.flags & DUALHEAD_BITS)
123 		{
124 		case DUALHEAD_ON:
125 		case DUALHEAD_SWITCH:
126 			if ((si->overlay.ow.h_start + (si->overlay.ow.width / 2)) <
127 					(si->dm.h_display_start + si->dm.timing.h_display))
128 				eng_bes_to_crtc(si->crtc_switch_mode);
129 			else
130 				eng_bes_to_crtc(!si->crtc_switch_mode);
131 			break;
132 		default:
133 				eng_bes_to_crtc(si->crtc_switch_mode);
134 			break;
135 		}
136 	}
137 
138 	/* the BES does not respect virtual_workspaces, but adheres to CRTC
139 	 * constraints only */
140 	crtc_hstart = si->dm.h_display_start;
141 	/* make dualhead stretch and switch mode work while we're at it.. */
142 	if (si->overlay.crtc)
143 	{
144 		crtc_hstart += si->dm.timing.h_display;
145 	}
146 
147 	/* horizontal end is the first position beyond the displayed range on the CRTC */
148 	crtc_hend = crtc_hstart + si->dm.timing.h_display;
149 	crtc_vstart = si->dm.v_display_start;
150 	/* vertical end is the first position beyond the displayed range on the CRTC */
151 	crtc_vend = crtc_vstart + si->dm.timing.v_display;
152 
153 
154 	/****************************************
155 	 *** setup all edges of output window ***
156 	 ****************************************/
157 
158 	/* setup left and right edges of output window */
159 	moi->hcoordv = 0;
160 	/* left edge coordinate of output window, must be inside desktop */
161 	/* clipping on the left side */
162 	if (si->overlay.ow.h_start < crtc_hstart)
163 	{
164 		temp1 = 0;
165 	}
166 	else
167 	{
168 		/* clipping on the right side */
169 		if (si->overlay.ow.h_start >= (crtc_hend - 1))
170 		{
171 			/* width < 2 is not allowed */
172 			temp1 = (crtc_hend - crtc_hstart - 2) & 0x7ff;
173 		}
174 		else
175 		/* no clipping here */
176 		{
177 			temp1 = (si->overlay.ow.h_start - crtc_hstart) & 0x7ff;
178 		}
179 	}
180 	moi->hcoordv |= temp1 << 16;
181 	/* right edge coordinate of output window, must be inside desktop */
182 	/* width < 2 is not allowed */
183 	if (si->overlay.ow.width < 2)
184 	{
185 		temp2 = (temp1 + 1) & 0x7ff;
186 	}
187 	else
188 	{
189 		/* clipping on the right side */
190 		if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) > (crtc_hend - 1))
191 		{
192 			temp2 = (crtc_hend - crtc_hstart - 1) & 0x7ff;
193 		}
194 		else
195 		{
196 			/* clipping on the left side */
197 			if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1))
198 			{
199 				/* width < 2 is not allowed */
200 				temp2 = 1;
201 			}
202 			else
203 			/* no clipping here */
204 			{
205 				temp2 = ((uint16)(si->overlay.ow.h_start + si->overlay.ow.width - crtc_hstart - 1)) & 0x7ff;
206 			}
207 		}
208 	}
209 	moi->hcoordv |= temp2 << 0;
210 	LOG(4,("Overlay: CRTC left-edge output %d, right-edge output %d\n",temp1, temp2));
211 
212 	/* setup top and bottom edges of output window */
213 	moi->vcoordv = 0;
214 	/* top edge coordinate of output window, must be inside desktop */
215 	/* clipping on the top side */
216 	if (si->overlay.ow.v_start < crtc_vstart)
217 	{
218 		temp1 = 0;
219 	}
220 	else
221 	{
222 		/* clipping on the bottom side */
223 		if (si->overlay.ow.v_start >= (crtc_vend - 1))
224 		{
225 			/* height < 2 is not allowed */
226 			temp1 = (crtc_vend - crtc_vstart - 2) & 0x7ff;
227 		}
228 		else
229 		/* no clipping here */
230 		{
231 			temp1 = (si->overlay.ow.v_start - crtc_vstart) & 0x7ff;
232 		}
233 	}
234 	moi->vcoordv |= temp1 << 16;
235 	/* bottom edge coordinate of output window, must be inside desktop */
236 	/* height < 2 is not allowed */
237 	if (si->overlay.ow.height < 2)
238 	{
239 		temp2 = (temp1 + 1) & 0x7ff;
240 	}
241 	else
242 	{
243 		/* clipping on the bottom side */
244 		if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) > (crtc_vend - 1))
245 		{
246 			temp2 = (crtc_vend - crtc_vstart - 1) & 0x7ff;
247 		}
248 		else
249 		{
250 			/* clipping on the top side */
251 			if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1))
252 			{
253 				/* height < 2 is not allowed */
254 				temp2 = 1;
255 			}
256 			else
257 			/* no clipping here */
258 			{
259 				temp2 = ((uint16)(si->overlay.ow.v_start + si->overlay.ow.height - crtc_vstart - 1)) & 0x7ff;
260 			}
261 		}
262 	}
263 	moi->vcoordv |= temp2 << 0;
264 	LOG(4,("Overlay: CRTC top-edge output %d, bottom-edge output %d\n",temp1, temp2));
265 
266 
267 	/*********************************
268 	 *** setup horizontal clipping ***
269 	 *********************************/
270 
271 	/* Setup horizontal source start: first (sub)pixel contributing to output picture */
272 	/* Note:
273 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
274 	 * After this is done, include the scaling factor so you get a value based on the input bitmap.
275 	 * Then add the left starting position of the bitmap's view (zoom function) to get the final value needed.
276 	 * Note: The input bitmaps slopspace is automatically excluded from the calculations this way! */
277 	/* Note also:
278 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
279 	moi->hsrcstv = 0;
280 	/* check for destination horizontal clipping at left side */
281 	if (si->overlay.ow.h_start < crtc_hstart)
282 	{
283 		/* check if entire destination picture is clipping left:
284 		 * (2 pixels will be clamped onscreen at least) */
285 		if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) < (crtc_hstart + 1))
286 		{
287 			/* increase 'first contributing pixel' with 'fixed value': (total dest. width - 2) */
288 			moi->hsrcstv += (si->overlay.ow.width - 2);
289 		}
290 		else
291 		{
292 			/* increase 'first contributing pixel' with actual number of dest. clipping pixels */
293 			moi->hsrcstv += (crtc_hstart - si->overlay.ow.h_start);
294 		}
295 		LOG(4,("Overlay: clipping left...\n"));
296 
297 		/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
298 		 * Note that this also already takes care of aligning the value to the BES register! */
299 		moi->hsrcstv *= si->overlay.h_ifactor;
300 	}
301 	/* take zoom into account */
302 	moi->hsrcstv += ((uint32)si->overlay.my_ov.h_start) << 16;
303 	/* AND below required by hardware */
304 	moi->hsrcstv &= 0x03fffffc;
305 	LOG(4,("Overlay: first hor. (sub)pixel of input bitmap contributing %f\n", moi->hsrcstv / (float)65536));
306 
307 	/* Setup horizontal source end: last (sub)pixel contributing to output picture */
308 	/* Note:
309 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
310 	 * After this is done, include the scaling factor so you get a value based on the input bitmap.
311 	 * Then add the right ending position of the bitmap's view (zoom function) to get the final value needed. */
312 	/* Note also:
313 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source end pos.! */
314 
315 	moi->hsrcendv = 0;
316 	/* check for destination horizontal clipping at right side */
317 	if ((si->overlay.ow.h_start + si->overlay.ow.width - 1) > (crtc_hend - 1))
318 	{
319 		/* check if entire destination picture is clipping right:
320 		 * (2 pixels will be clamped onscreen at least) */
321 		if (si->overlay.ow.h_start > (crtc_hend - 2))
322 		{
323 			/* increase 'number of clipping pixels' with 'fixed value': (total dest. width - 2) */
324 			moi->hsrcendv += (si->overlay.ow.width - 2);
325 		}
326 		else
327 		{
328 			/* increase 'number of clipping pixels' with actual number of dest. clipping pixels */
329 			moi->hsrcendv += ((si->overlay.ow.h_start + si->overlay.ow.width - 1) - (crtc_hend - 1));
330 		}
331 		LOG(4,("Overlay: clipping right...\n"));
332 
333 		/* The calculated value is based on scaling = 1x. So we now compensate for scaling.
334 		 * Note that this also already takes care of aligning the value to the BES register! */
335 		moi->hsrcendv *= si->overlay.h_ifactor;
336 		/* now subtract this value from the last used pixel in (zoomed) inputbuffer, aligned to BES */
337 		moi->hsrcendv = (((uint32)((si->overlay.my_ov.h_start + si->overlay.my_ov.width) - 1)) << 16) - moi->hsrcendv;
338 	}
339 	else
340 	{
341 		/* set last contributing pixel to last used pixel in (zoomed) inputbuffer, aligned to BES */
342 		moi->hsrcendv = (((uint32)((si->overlay.my_ov.h_start + si->overlay.my_ov.width) - 1)) << 16);
343 	}
344 	/* AND below required by hardware */
345 	moi->hsrcendv &= 0x03ffffff;
346 	LOG(4,("Overlay: last horizontal (sub)pixel of input bitmap contributing %f\n", moi->hsrcendv / (float)65536));
347 
348 
349 	/*******************************
350 	 *** setup vertical clipping ***
351 	 *******************************/
352 
353 	/* calculate inputbitmap origin adress */
354 	moi->a1orgv = (uintptr_t)((vuint32 *)si->overlay.ob.buffer);
355 	moi->a1orgv -= (uintptr_t)((vuint32 *)si->framebuffer);
356 	LOG(4,("Overlay: topleft corner of input bitmap (cardRAM offset) $%p\n", moi->a1orgv));
357 
358 	/* Setup vertical source start: first (sub)pixel contributing to output picture. */
359 	/* Note:
360 	 * The method is to calculate, based on 1:1 scaling, based on the output window.
361 	 * 'After' this is done, include the scaling factor so you get a value based on the input bitmap.
362 	 * Then add the top starting position of the bitmap's view (zoom function) to get the final value needed. */
363 	/* Note also:
364 	 * Even if the scaling factor is clamping we instruct the BES to use the correct source start pos.! */
365 
366 	moi->v1srcstv = 0;
367 	/* check for destination vertical clipping at top side */
368 	if (si->overlay.ow.v_start < crtc_vstart)
369 	{
370 		/* check if entire destination picture is clipping at top:
371 		 * (2 pixels will be clamped onscreen at least) */
372 		if ((si->overlay.ow.v_start + si->overlay.ow.height - 1) < (crtc_vstart + 1))
373 		{
374 			/* increase 'number of clipping pixels' with 'fixed value':
375 			 * 'total height - 2' of dest. picture in pixels * inverse scaling factor */
376 			moi->v1srcstv = (si->overlay.ow.height - 2) * si->overlay.v_ifactor;
377 			/* we need to do clipping in the source bitmap because no seperate clipping
378 			 * registers exist... */
379 			moi->a1orgv += ((moi->v1srcstv >> 16) * si->overlay.ob.bytes_per_row);
380 		}
381 		else
382 		{
383 			/* increase 'first contributing pixel' with:
384 			 * number of destination picture clipping pixels * inverse scaling factor */
385 			moi->v1srcstv = (crtc_vstart - si->overlay.ow.v_start) * si->overlay.v_ifactor;
386 			/* we need to do clipping in the source bitmap because no seperate clipping
387 			 * registers exist... */
388 			moi->a1orgv += ((moi->v1srcstv >> 16) * si->overlay.ob.bytes_per_row);
389 		}
390 		LOG(4,("Overlay: clipping at top...\n"));
391 	}
392 	/* take zoom into account */
393 	moi->v1srcstv += (((uint32)si->overlay.my_ov.v_start) << 16);
394 	moi->a1orgv += (si->overlay.my_ov.v_start * si->overlay.ob.bytes_per_row);
395 	LOG(4,("Overlay: 'contributing part of buffer' origin is (cardRAM offset) $%08x\n", moi->a1orgv));
396 	LOG(4,("Overlay: first vert. (sub)pixel of input bitmap contributing %f\n", moi->v1srcstv / (float)65536));
397 
398 	/* AND below is probably required by hardware. */
399 	/* Buffer A topleft corner of field 1 (origin)(field 1 contains our full frames) */
400 	moi->a1orgv &= 0x07fffff0;
401 }
402 
403 static void eng_bes_program_move_overlay(move_overlay_info moi)
404 {
405 	/*************************************
406 	 *** sync to BES (Back End Scaler) ***
407 	 *************************************/
408 
409 	/* Done in card hardware:
410 	 * double buffered registers + trigger during 'BES-'VBI feature. */
411 
412 
413 	/**************************************
414 	 *** actually program the registers ***
415 	 **************************************/
416 
417 	if (si->ps.card_arch < K8M800)
418 	{
419 		/* setup clipped(!) buffer startadress in RAM */
420 		/* VIA bes doesn't have clipping registers, so no subpixelprecise clipping
421 		 * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
422 		/* first include 'pixel precise' left clipping... (top clipping was already included) */
423 		moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
424 		/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
425 		BESW(VID1Y_ADDR0, (moi.a1orgv & 0x07fffffc));
426 
427 		/* horizontal source end does not use subpixelprecision: granularity is 8 pixels */
428 		/* notes:
429 		 * - make absolutely sure the engine can fetch the last pixel needed from
430 		 *   the sourcebitmap even if only to generate a tiny subpixel from it!
431 		 * - the engine uses byte format instead of pixel format;
432 		 * - the engine uses 16 bytes, so 8 pixels granularity. */
433 		BESW(VID1_FETCH, (((((moi.hsrcendv >> 16) + 1 + 0x0007) & ~0x0007) * 2) << (20 - 4)));
434 
435 		/* setup output window position */
436 		BESW(VID1_HVSTART, ((moi.hcoordv & 0xffff0000) | ((moi.vcoordv & 0xffff0000) >> 16)));
437 
438 		/* setup output window size */
439 		BESW(VID1_SIZE, (((moi.hcoordv & 0x0000ffff) << 16) | (moi.vcoordv & 0x0000ffff)));
440 
441 		/* enable colorkeying (b0 = 1), disable chromakeying (b1 = 0), Vid1 on top of Vid3 (b20 = 0),
442 		 * all registers are loaded during the next 'BES-'VBI (b28 = 1), Vid1 cmds fire (b31 = 1) */
443 		BESW(COMPOSE, 0x90000001);//fixme: >>>!<<< don't touch colorkey enable bit!
444 	}
445 	else
446 	{
447 		/* setup clipped(!) buffer startadress in RAM */
448 		/* VIA bes doesn't have clipping registers, so no subpixelprecise clipping
449 		 * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
450 		/* first include 'pixel precise' left clipping... (top clipping was already included) */
451 		moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
452 		/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
453 		BESW(VID3_ADDR0, (moi.a1orgv & 0x07fffffc));
454 
455 		/* horizontal source end does not use subpixelprecision: granularity is 8 pixels */
456 		/* notes:
457 		 * - make absolutely sure the engine can fetch the last pixel needed from
458 		 *   the sourcebitmap even if only to generate a tiny subpixel from it!
459 		 * - the engine uses byte format instead of pixel format;
460 		 * - the engine uses 16 bytes, so 8 pixels granularity. */
461 		BESW(V3A_FETCH, (((((moi.hsrcendv >> 16) + 1 + 0x0007) & ~0x0007) * 2) << (20 - 4)));
462 
463 		/* setup output window position */
464 		BESW(VID3_HVSTART, ((moi.hcoordv & 0xffff0000) | ((moi.vcoordv & 0xffff0000) >> 16)));
465 
466 		/* setup output window size */
467 		BESW(VID3_SIZE, (((moi.hcoordv & 0x0000ffff) << 16) | (moi.vcoordv & 0x0000ffff)));
468 
469 		/* enable colorkeying (b0 = 1), disable chromakeying (b1 = 0), Vid3 on top of Vid1 (b20 = 1),
470 		 * all registers are loaded during the next 'BES-'VBI (b8 = 1), Vid3 cmds fire (b30 = 1) */
471 		BESW(COMPOSE, 0x40100101);//fixme: >>>!<<< don't touch colorkey enable bit!
472 	}
473 }
474 
475 status_t eng_bes_to_crtc(bool crtc)
476 {
477 	if (si->ps.secondary_head)
478 	{
479 		if (crtc)
480 		{
481 			LOG(4,("Overlay: switching overlay to CRTC2\n"));
482 			/* switch overlay engine to CRTC2 */
483 //			ENG_REG32(RG32_FUNCSEL) &= ~0x00001000;
484 //			ENG_REG32(RG32_2FUNCSEL) |= 0x00001000;
485 			si->overlay.crtc = !si->crtc_switch_mode;
486 		}
487 		else
488 		{
489 			LOG(4,("Overlay: switching overlay to CRTC1\n"));
490 			/* switch overlay engine to CRTC1 */
491 //			ENG_REG32(RG32_2FUNCSEL) &= ~0x00001000;
492 //			ENG_REG32(RG32_FUNCSEL) |= 0x00001000;
493 			si->overlay.crtc = si->crtc_switch_mode;
494 		}
495 		return B_OK;
496 	}
497 	else
498 	{
499 		return B_ERROR;
500 	}
501 }
502 
503 status_t eng_bes_init()
504 {
505 	if (si->ps.card_arch < K8M800)
506 	{
507 		if (si->ps.chip_rev < 0x10)
508 		{
509 			/* setup brightness, contrast and saturation to be 'neutral' */
510 			BESW(VID1_COLSPAC1, 0x140020f2);
511 			BESW(VID1_COLSPAC2, 0x0a0a2c00);
512 			/* fifo depth is $20 (b0-5), threshold $10 (b8-13), prethreshold $1d (b24-29) */
513 			BESW(VID1_FIFO, 0x1d00101f);
514 		}
515 		else
516 		{
517 			/* setup brightness, contrast and saturation to be 'neutral' */
518 			BESW(VID1_COLSPAC1, 0x13000ded);
519 			BESW(VID1_COLSPAC2, 0x13171000);
520 			/* fifo depth is $40 (b0-5), threshold $38 (b8-13), prethreshold $38 (b24-29) */
521 			BESW(VID1_FIFO, 0x3800383f);
522 		}
523 	}
524 	else
525 	{
526 		/* setup brightness, contrast and saturation to be 'neutral' */
527 		BESW(VID3_COLSPAC1, 0x13000ded);
528 		BESW(VID3_COLSPAC2, 0x13171000);
529 
530 		/* fifo prethreshold 60 (b0-6) */
531 		BESW(V3A_PREFIFO, (60 & 0x7f));
532 		/* fifo depth-1 is 63 (b0-7), threshold 60 (b8-15) */
533 		BESW(V3A_FIFO, ((63 & 0xff) | ((60 & 0xff) << 8)));
534 	}
535 
536 	return B_OK;
537 }
538 
539 status_t eng_configure_bes
540 	(const overlay_buffer *ob, const overlay_window *ow, const overlay_view *ov, int offset)
541 {
542 	/* yuy2 (4:2:2) colorspace calculations */
543 
544 	/* Note:
545 	 * in BeOS R5.0.3 and DANO:
546 	 * 'ow->offset_xxx' is always 0, so not used;
547 	 * 'ow->width' and 'ow->height' are the output window size: does not change
548 	 * if window is clipping;
549 	 * 'ow->h_start' and 'ow->v_start' are the left-top position of the output
550 	 * window. These values can be negative: this means the window is clipping
551 	 * at the left or the top of the display, respectively. */
552 
553 	/* 'ov' is the view in the source bitmap, so which part of the bitmap is actually
554 	 * displayed on screen. This is used for the 'hardware zoom' function. */
555 
556 	/* output window position and clipping info for source buffer */
557 	move_overlay_info moi;
558 	/* calculated BES register values */
559 	uint32 	hiscalv, viscalv;
560 	/* interval representation, used for scaling calculations */
561 	uint16 intrep;
562 	/* inverse scaling factor, used for source positioning */
563 	uint32 ifactor;
564 	/* copy of overlay view which has checked valid values */
565 	overlay_view my_ov;
566 	/* true if scaling needed */
567 	bool scale_x, scale_y;
568 	/* for computing scaling register value */
569 	uint32 scaleval;
570 	/* for computing 'pre-scaling' on downscaling */
571 	uint32 minictrl;
572 
573 	/**************************************************************************************
574 	 *** copy, check and limit if needed the user-specified view into the intput bitmap ***
575 	 **************************************************************************************/
576 	my_ov = *ov;
577 	/* check for valid 'coordinates' */
578 	if (my_ov.width == 0) my_ov.width++;
579 	if (my_ov.height == 0) my_ov.height++;
580 	if (my_ov.h_start > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
581 		my_ov.h_start = ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1);
582 	if (((my_ov.h_start + my_ov.width) - 1) > ((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1))
583 		my_ov.width = ((((ob->width - si->overlay.myBufInfo[offset].slopspace) - 1) - my_ov.h_start) + 1);
584 	if (my_ov.v_start > (ob->height - 1))
585 		my_ov.v_start = (ob->height - 1);
586 	if (((my_ov.v_start + my_ov.height) - 1) > (ob->height - 1))
587 		my_ov.height = (((ob->height - 1) - my_ov.v_start) + 1);
588 
589 	LOG(4,("Overlay: inputbuffer view (zoom) left %d, top %d, width %d, height %d\n",
590 		my_ov.h_start, my_ov.v_start, my_ov.width, my_ov.height));
591 
592 	/* save for eng_bes_calc_move_overlay() */
593 	si->overlay.ow = *ow;
594 	si->overlay.ob = *ob;
595 	si->overlay.my_ov = my_ov;
596 
597 
598 	/********************************
599 	 *** setup horizontal scaling ***
600 	 ********************************/
601 	LOG(4,("Overlay: total input picture width = %d, height = %d\n",
602 			(ob->width - si->overlay.myBufInfo[offset].slopspace), ob->height));
603 	LOG(4,("Overlay: output picture width = %d, height = %d\n", ow->width, ow->height));
604 
605 	/* preset X and Y prescaling to be 1x */
606 	minictrl = 0x00000000;
607 	/* determine interval representation value, taking zoom into account */
608 	if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
609 	{
610 		/* horizontal filtering is ON */
611 		if ((my_ov.width == ow->width) | (ow->width < 2))
612 		{
613 			/* no horizontal scaling used, OR destination width < 2 */
614 			intrep = 0;
615 		}
616 		else
617 		{
618 			intrep = 1;
619 		}
620 	}
621 	else
622 	{
623 		/* horizontal filtering is OFF */
624 		if ((ow->width < my_ov.width) & (ow->width >= 2))
625 		{
626 			/* horizontal downscaling used AND destination width >= 2 */
627 			intrep = 1;
628 		}
629 		else
630 		{
631 			intrep = 0;
632 		}
633 	}
634 	LOG(4,("Overlay: horizontal interval representation value is %d\n",intrep));
635 
636 	/* calculate inverse horizontal scaling factor, taking zoom into account */
637 	/* standard scaling formula: */
638 	ifactor = (((uint32)(my_ov.width - intrep)) << 16) / (ow->width - intrep);
639 
640 	/* correct factor to prevent most-right visible 'line' from distorting */
641 	ifactor -= (1 << 5);
642 	hiscalv = ifactor;
643 	/* save for eng_bes_calc_move_overlay() */
644 	si->overlay.h_ifactor = ifactor;
645 	LOG(4,("Overlay: horizontal scaling factor is %f\n", (float)65536 / ifactor));
646 
647 	/* check scaling factor (and modify if needed) to be within scaling limits */
648 	//fixme: checkout...
649 	if (hiscalv < 0x00002000)
650 	{
651 		/* (non-inverse) factor too large, set factor to max. valid value */
652 		hiscalv = 0x00002000;
653 		LOG(4,("Overlay: horizontal scaling factor too large, clamping at %f\n", (float)65536 / hiscalv));
654 	}
655 	/* VIA has a 'downscaling' limit of 1.0, but seperate prescaling to 1/16th can be done.
656 	 * (X-scaler has 11bit register with 0.11 format value, with special 1.0 scaling factor setting;
657 	 *  prescaler has fixed 1x, 1/2x, 1/4x, 1/8x and 1/16x settings.) */
658 	if (hiscalv > 0x00100000)
659 	{
660 		/* (non-inverse) factor too small, set factor to min. valid value */
661 		hiscalv = 0x00100000;
662 		LOG(4,("Overlay: horizontal scaling factor too small, clamping at %f\n", (float)2048 / (hiscalv >> 5)));
663 	}
664 
665 	/* setup pre-downscaling if 'requested' */
666 	if ((hiscalv > 0x00010000) && (hiscalv <= 0x00020000))
667 	{
668 		/* instruct BES to horizontal prescale 0.5x */
669 		minictrl |= 0x01000000;
670 		/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
671 		hiscalv >>= 1;
672 	}
673 	else
674 		if ((hiscalv > 0x00020000) && (hiscalv <= 0x00040000))
675 		{
676 			/* instruct BES to horizontal prescale 0.25x */
677 			minictrl |= 0x03000000;
678 			/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
679 			hiscalv >>= 2;
680 		}
681 		else
682 			if ((hiscalv > 0x00040000) && (hiscalv <= 0x00080000))
683 			{
684 				/* instruct BES to horizontal prescale 0.125x */
685 				minictrl |= 0x05000000;
686 				/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
687 				hiscalv >>= 3;
688 			}
689 			else
690 				if ((hiscalv > 0x00080000) && (hiscalv <= 0x00100000))
691 				{
692 					/* instruct BES to horizontal prescale 0.125x */
693 					minictrl |= 0x07000000;
694 					/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
695 					hiscalv >>= 4;
696 				}
697 
698 	/* only instruct normal scaler to scale if it must do so */
699 	scale_x = true;
700 	if (hiscalv == 0x00010000) scale_x = false;
701 
702 	/* AND below is required by hardware */
703 	hiscalv &= 0x0000ffe0;
704 
705 
706 	/******************************
707 	 *** setup vertical scaling ***
708 	 ******************************/
709 
710 	/* determine interval representation value, taking zoom into account */
711 	if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
712 	{
713 		/* vertical filtering is ON */
714 		if ((my_ov.height == ow->height) | (ow->height < 2))
715 		{
716 			/* no vertical scaling used, OR destination height < 2 */
717 			intrep = 0;
718 		}
719 		else
720 		{
721 			intrep = 1;
722 		}
723 	}
724 	else
725 	{
726 		/* vertical filtering is OFF */
727 		if ((ow->height < my_ov.height) & (ow->height >= 2))
728 		{
729 			/* vertical downscaling used AND destination height >= 2 */
730 			intrep = 1;
731 		}
732 		else
733 		{
734 			intrep = 0;
735 		}
736 	}
737 	LOG(4,("Overlay: vertical interval representation value is %d\n",intrep));
738 
739 	/* calculate inverse vertical scaling factor, taking zoom into account */
740 	/* standard scaling formula: */
741 	ifactor = (((uint32)(my_ov.height - intrep)) << 16) / (ow->height - intrep);
742 
743 	/* correct factor to prevent lowest visible line from distorting */
744 	ifactor -= (1 << 6);
745 	LOG(4,("Overlay: vertical scaling factor is %f\n", (float)65536 / ifactor));
746 
747 	/* preserve ifactor for source positioning calculations later on */
748 	viscalv = ifactor;
749 	/* save for eng_bes_calc_move_overlay() */
750 	si->overlay.v_ifactor = ifactor;
751 
752 	/* check scaling factor (and modify if needed) to be within scaling limits */
753 	//fixme: checkout...
754 	if (viscalv < 0x00002000)
755 	{
756 		/* (non-inverse) factor too large, set factor to max. valid value */
757 		viscalv = 0x00002000;
758 		LOG(4,("Overlay: vertical scaling factor too large, clamping at %f\n", (float)65536 / viscalv));
759 	}
760 	/* VIA has a 'downscaling' limit of 1.0, but seperate prescaling to 1/16th can be done.
761 	 * (Y-scaler has 10bit register with 0.10 format value, with special 1.0 scaling factor setting;
762 	 *  prescaler has fixed 1x, 1/2x, 1/4x, 1/8x and 1/16x settings.) */
763 	if (viscalv > 0x00100000)
764 	{
765 		/* (non-inverse) factor too small, set factor to min. valid value */
766 		viscalv = 0x00100000;
767 		LOG(4,("Overlay: vertical scaling factor too small, clamping at %f\n", (float)1024 / (viscalv >> 6)));
768 	}
769 
770 	/* setup pre-downscaling if 'requested' */
771 	if ((viscalv > 0x00010000) && (viscalv <= 0x00020000))
772 	{
773 		/* instruct BES to horizontal prescale 0.5x */
774 		minictrl |= 0x00010000;
775 		/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
776 		viscalv >>= 1;
777 	}
778 	else
779 		if ((viscalv > 0x00020000) && (viscalv <= 0x00040000))
780 		{
781 			/* instruct BES to horizontal prescale 0.25x */
782 			minictrl |= 0x00030000;
783 			/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
784 			viscalv >>= 2;
785 		}
786 		else
787 			if ((viscalv > 0x00040000) && (viscalv <= 0x00080000))
788 			{
789 				/* instruct BES to horizontal prescale 0.125x */
790 				minictrl |= 0x00050000;
791 				/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
792 				viscalv >>= 3;
793 			}
794 			else
795 				if ((viscalv > 0x00080000) && (viscalv <= 0x00100000))
796 				{
797 					/* instruct BES to horizontal prescale 0.125x */
798 					minictrl |= 0x00070000;
799 					/* correct normal scalingfactor so total scaling is 0.5 <= factor < 1.0x */
800 					viscalv >>= 4;
801 				}
802 
803 	/* only instruct normal scaler to scale if it must do so */
804 	scale_y = true;
805 	if (viscalv == 0x00010000) scale_y = false;
806 
807 	/* AND below is required by hardware */
808 	viscalv &= 0x0000ffc0;
809 
810 
811 	/********************************************************************************
812 	 *** setup all edges of output window, setup horizontal and vertical clipping ***
813 	 ********************************************************************************/
814 	eng_bes_calc_move_overlay(&moi);
815 
816 
817 	/*****************************
818 	 *** log color keying info ***
819 	 *****************************/
820 
821 	LOG(4,("Overlay: key_red %d, key_green %d, key_blue %d, key_alpha %d\n",
822 		ow->red.value, ow->green.value, ow->blue.value, ow->alpha.value));
823 	LOG(4,("Overlay: mask_red %d, mask_green %d, mask_blue %d, mask_alpha %d\n",
824 		ow->red.mask, ow->green.mask, ow->blue.mask, ow->alpha.mask));
825 
826 
827 	/*****************
828 	 *** log flags ***
829 	 *****************/
830 
831 	LOG(4,("Overlay: ow->flags is $%08x\n",ow->flags));
832 	/* BTW: horizontal and vertical filtering are fixed and turned on for GeForce overlay. */
833 
834 
835 	/*************************************
836 	 *** sync to BES (Back End Scaler) ***
837 	 *************************************/
838 
839 	/* Done in card hardware:
840 	 * double buffered registers + trigger during 'BES-'VBI feature. */
841 
842 
843 	/**************************************
844 	 *** actually program the registers ***
845 	 **************************************/
846 
847 	if (si->ps.card_arch < K8M800)
848 	{
849 		/* setup clipped(!) buffer startadress in RAM */
850 		/* VIA bes doesn't have clipping registers, so no subpixelprecise clipping
851 		 * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
852 		/* first include 'pixel precise' left clipping... (top clipping was already included) */
853 		moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
854 		/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
855 		BESW(VID1Y_ADDR0, (moi.a1orgv & 0x07fffffc));
856 
857 		/* horizontal source end does not use subpixelprecision: granularity is 8 pixels */
858 		/* notes:
859 		 * - make absolutely sure the engine can fetch the last pixel needed from
860 		 *   the sourcebitmap even if only to generate a tiny subpixel from it!
861 		 * - the engine uses byte format instead of pixel format;
862 		 * - the engine uses 16 bytes, so 8 pixels granularity. */
863 		BESW(VID1_FETCH, (((((moi.hsrcendv >> 16) + 1 + 0x0007) & ~0x0007) * 2) << (20 - 4)));
864 
865 		/* enable horizontal filtering if asked for */
866 		if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
867 		{
868 			minictrl |= (1 << 1);
869 			LOG(4,("Overlay: using horizontal interpolation on scaling\n"));
870 		}
871 		/* enable vertical filtering if asked for */
872 		if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
873 		{
874 			/* vertical interpolation b0, interpolation on Y, Cb and Cr all (b2) */
875 			minictrl |= ((1 << 2) | (1 << 0));
876 			LOG(4,("Overlay: using vertical interpolation on scaling\n"));
877 		}
878 		/* and program horizontal and vertical 'prescaling' for downscaling */
879 		BESW(VID1_MINI_CTL, minictrl);
880 
881 		/* setup buffersize */
882 		BESW(V1_SOURCE_WH, ((ob->height << 16) | (ob->width)));
883 
884 		/* setup buffer source pitch including slopspace (in bytes) */
885 		BESW(VID1_STRIDE, (ob->width * 2));
886 
887 		/* setup output window position */
888 		BESW(VID1_HVSTART, ((moi.hcoordv & 0xffff0000) | ((moi.vcoordv & 0xffff0000) >> 16)));
889 
890 		/* setup output window size */
891 		BESW(VID1_SIZE, (((moi.hcoordv & 0x0000ffff) << 16) | (moi.vcoordv & 0x0000ffff)));
892 
893 		/* setup horizontal and vertical scaling:
894 		 * setup horizontal scaling enable (b31), setup vertical scaling enable (b15).
895 		 * Note:
896 		 * Vertical scaling has a different resolution than horizontal scaling(!).  */
897 		scaleval = 0x00000000;
898 		if (scale_x) scaleval |= 0x80000000;
899 		if (scale_y) scaleval |= 0x00008000;
900 		BESW(VID1_ZOOM, (scaleval | ((hiscalv << 16) >> 5) | (viscalv >> 6)));
901 
902 		if (si->ps.chip_rev < 0x10)
903 		{
904 			/* enable BES (b0), format yuv422 (b2-4 = %000), set colorspace sign (b7 = 1),
905 			 * input is frame (not field) picture (b9 = 0), expire = $5 (b16-19),
906 			 * select field (not frame)(!) base (b24 = 0) */
907 			BESW(VID1_CTL, 0x00050081);
908 		}
909 		else
910 		{
911 			/* enable BES (b0), format yuv422 (b2-4 = %000), set colorspace sign (b7 = 1),
912 			 * input is frame (not field) picture (b9 = 0), expire = $f (b16-19),
913 			 * select field (not frame)(!) base (b24 = 0) */
914 			BESW(VID1_CTL, 0x000f0081);
915 		}
916 	}
917 	else
918 	{
919 		/* setup clipped(!) buffer startadress in RAM */
920 		/* VIA bes doesn't have clipping registers, so no subpixelprecise clipping
921 		 * either. We do pixelprecise vertical and 'two pixel' precise horizontal clipping here. */
922 		/* first include 'pixel precise' left clipping... (top clipping was already included) */
923 		moi.a1orgv += ((moi.hsrcstv >> 16) * 2);
924 		/* we need to step in 4-byte (2 pixel) granularity due to the nature of yuy2 */
925 		BESW(VID3_ADDR0, (moi.a1orgv & 0x07fffffc));
926 
927 		/* horizontal source end does not use subpixelprecision: granularity is 8 pixels */
928 		/* notes:
929 		 * - make absolutely sure the engine can fetch the last pixel needed from
930 		 *   the sourcebitmap even if only to generate a tiny subpixel from it!
931 		 * - the engine uses byte format instead of pixel format;
932 		 * - the engine uses 16 bytes, so 8 pixels granularity. */
933 		BESW(V3A_FETCH, (((((moi.hsrcendv >> 16) + 1 + 0x0007) & ~0x0007) * 2) << (20 - 4)));
934 
935 		/* enable horizontal filtering if asked for */
936 		if (ow->flags & B_OVERLAY_HORIZONTAL_FILTERING)
937 		{
938 			minictrl |= (1 << 1);
939 			LOG(4,("Overlay: using horizontal interpolation on scaling\n"));
940 		}
941 		/* enable vertical filtering if asked for */
942 		if (ow->flags & B_OVERLAY_VERTICAL_FILTERING)
943 		{
944 			/* vertical interpolation b0, interpolation on Y, Cb and Cr all (b2) */
945 			minictrl |= ((1 << 2) | (1 << 0));
946 			LOG(4,("Overlay: using vertical interpolation on scaling\n"));
947 		}
948 		/* and program horizontal and vertical 'prescaling' for downscaling */
949 		BESW(VID3_MINI_CTL, minictrl);
950 
951 		/* setup buffersize (V3 does not need ob->height(?)) */
952 		BESW(V3_SRC_WIDTH, (ob->width));
953 
954 		/* setup buffer source pitch including slopspace (in bytes) */
955 		BESW(VID3_STRIDE, (ob->width * 2));
956 
957 		/* setup output window position */
958 		BESW(VID3_HVSTART, ((moi.hcoordv & 0xffff0000) | ((moi.vcoordv & 0xffff0000) >> 16)));
959 
960 		/* setup output window size */
961 		BESW(VID3_SIZE, (((moi.hcoordv & 0x0000ffff) << 16) | (moi.vcoordv & 0x0000ffff)));
962 
963 		/* setup horizontal and vertical scaling:
964 		 * setup horizontal scaling enable (b31), setup vertical scaling enable (b15).
965 		 * Note:
966 		 * Vertical scaling has a different resolution than horizontal scaling(!).  */
967 		scaleval = 0x00000000;
968 		if (scale_x) scaleval |= 0x80000000;
969 		if (scale_y) scaleval |= 0x00008000;
970 		BESW(VID3_ZOOM, (scaleval | ((hiscalv << 16) >> 5) | (viscalv >> 6)));
971 
972 		/* enable BES (b0), format yuv422 (b2-3 = %00), set colorspace sign (b7 = 1),
973 		 * expire = $8 (b16-19), select field (not frame)(!) base (b24 = 0),
974 		 * enable prefetch (b30 = 1) */
975 		BESW(VID3_CTL, 0x40080081);
976 	}
977 
978 
979 	/**************************
980 	 *** setup color keying ***
981 	 **************************/
982 
983 	/* setup colorkeying */
984 	switch(si->dm.space)
985 	{
986 	case B_CMAP8:
987 		{
988 			/* do color palette index lookup for current colorkey */
989 			/* note:
990 			 * since apparantly some hardware works with color indexes instead of colors,
991 			 * it might be a good idea(!!) to include the colorindex in the system's
992 			 * overlay_window struct. */
993 			static uint8 *r,*g,*b;
994 			static uint32 idx;
995 			r = si->color_data;
996 			g = r + 256;
997 			b = g + 256;
998 			/* if index 1 doesn't help us, we assume 0 will (got to program something anyway) */
999 			//fixme, note, tweakalert:
1000 			//I'm counting down for a reason:
1001 			//BeOS assigns the color white (0x00ffffff) to two indexes in the palette:
1002 			//index 0x3f and 0xff. In the framebuffer index 0xff is used (apparantly).
1003 			//The hardware compares framebuffer to given key, so the BES must receive 0xff.
1004 			for (idx = 255; idx > 0; idx--)
1005 			{
1006 				if ((r[idx] == ow->red.value) &&
1007 					(g[idx] == ow->green.value) &&
1008 					(b[idx] == ow->blue.value))
1009 						break;
1010 			}
1011 			LOG(4,("Overlay: colorkey's palette index is $%02x\n", idx));
1012 			/* program color palette index into BES engine */
1013 			BESW(COLKEY, idx);
1014 		}
1015 		break;
1016 	case B_RGB15_LITTLE:
1017 		BESW(COLKEY, (
1018 			((ow->blue.value & ow->blue.mask) << 0)   |
1019 			((ow->green.value & ow->green.mask) << 5) |
1020 			((ow->red.value & ow->red.mask) << 10)
1021 			/* alpha keying is not supported here */
1022 			));
1023 		break;
1024 	case B_RGB16_LITTLE:
1025 		BESW(COLKEY, (
1026 			((ow->blue.value & ow->blue.mask) << 0)   |
1027 			((ow->green.value & ow->green.mask) << 5) |
1028 			((ow->red.value & ow->red.mask) << 11)
1029 			/* this space has no alpha bits */
1030 			));
1031 		break;
1032 	case B_RGB32_LITTLE:
1033 	default:
1034 		BESW(COLKEY, (
1035 			((ow->blue.value & ow->blue.mask) << 0)   |
1036 			((ow->green.value & ow->green.mask) << 8) |
1037 			((ow->red.value & ow->red.mask) << 16)
1038 			/* alpha keying is not supported here */
1039 			));
1040 		break;
1041 	}
1042 
1043 	if (si->ps.card_arch < K8M800)
1044 	{
1045 		/* disable chromakeying (b1 = 0), Vid1 on top of Vid3 (b20 = 0),
1046 		 * all registers are loaded during the next 'BES-'VBI (b28 = 1), Vid1 cmds fire (b31 = 1) */
1047 		if (ow->flags & B_OVERLAY_COLOR_KEY)
1048 		{
1049 			/* enable colorkeying (b0 = 1) */
1050 			BESW(COMPOSE, 0x90000001);
1051 		}
1052 		else
1053 		{
1054 			/* disable colorkeying (b0 = 0) */
1055 			BESW(COMPOSE, 0x90000000);
1056 		}
1057 	}
1058 	else
1059 	{
1060 		/* disable chromakeying (b1 = 0), Vid3 on top of Vid1 (b20 = 1),
1061 		 * all registers are loaded during the next 'BES-'VBI (b8 = 1), Vid3 cmds fire (b30 = 1) */
1062 		if (ow->flags & B_OVERLAY_COLOR_KEY)
1063 		{
1064 			/* enable colorkeying (b0 = 1) */
1065 			BESW(COMPOSE, 0x40100101);
1066 		}
1067 		else
1068 		{
1069 			/* disable colorkeying (b0 = 0) */
1070 			BESW(COMPOSE, 0x40100100);
1071 		}
1072 	}
1073 
1074 	/* note that overlay is in use (for eng_bes_move_overlay()) */
1075 	si->overlay.active = true;
1076 
1077 	return B_OK;
1078 }
1079 
1080 status_t eng_release_bes()
1081 {
1082 	if (si->ps.card_arch < K8M800)
1083 	{
1084 		/* setup BES control: disable scaler (b0 = 0) */
1085 		BESW(VID1_CTL, 0x00000000);
1086 
1087 		/* make sure the 'disable' command really gets executed: (no 'VBI' anymore if BES disabled) */
1088 		/* all registers are loaded immediately (b29 = 1), Vid1 cmds fire (b31 = 1) */
1089 		BESW(COMPOSE, 0xa0000000);
1090 	}
1091 	else
1092 	{
1093 		/* setup BES control: disable scaler (b0 = 0) */
1094 		BESW(VID3_CTL, 0x00000000);
1095 
1096 		/* make sure the 'disable' command really gets executed: (no 'VBI' anymore if BES disabled) */
1097 		/* all registers are loaded immediately (b29 = 1), Vid3 cmds fire (b30 = 1) */
1098 		BESW(COMPOSE, 0x60000000);//fixme >>>!<<< test b29, should that be b27??
1099 	}
1100 
1101 	/* note that overlay is not in use (for eng_bes_move_overlay()) */
1102 	si->overlay.active = false;
1103 
1104 	return B_OK;
1105 }
1106