Comment out the correct #endif directive.
[mplayer/greg.git] / vidix / radeon_vid.c
blob628e90fceca2c291d1d96b354045c5753848380e
1 /*
2 * VIDIX driver for ATI Rage128 and Radeon chipsets.
3 * Copyright (C) 2002 Nick Kurshev
5 * This file is part of MPlayer.
7 * MPlayer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * MPlayer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with MPlayer; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * This file is based on sources from
22 * GATOS (gatos.sf.net) and X11 (www.xfree86.org)
24 * Changes:
25 * - 31.12.2002
26 * added support for fglrx drivers by Marcel Naziri (zwobbl@zwobbl.de)
27 * - 6.04.2004
28 * fixes to allow compiling vidix without X11 (broken in original patch)
29 * - PowerPC support by Alex Beregszaszi
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37 #include <inttypes.h>
39 #include "config.h"
40 #include "libavutil/common.h"
41 #include "mpbswap.h"
42 #include "pci_ids.h"
43 #include "pci_names.h"
44 #include "vidix.h"
45 #include "vidixlib.h"
46 #include "fourcc.h"
47 #include "dha.h"
48 #include "radeon.h"
50 #if !defined(RAGE128) && defined(HAVE_X11)
51 #include <X11/Xlib.h>
52 static uint32_t firegl_shift = 0;
53 #endif
55 #ifdef RAGE128
56 #define RADEON_MSG "[rage128]"
57 #define X_ADJUST 0
58 #else
59 #define RADEON_MSG "[radeon]"
60 #define X_ADJUST (((besr.chip_flags&R_OVL_SHIFT)==R_OVL_SHIFT)?8:0)
61 #ifndef RADEON
62 #define RADEON
63 #endif
64 #endif
66 #define RADEON_ASSERT(msg) printf(RADEON_MSG"################# FATAL:"msg);
68 #define VERBOSE_LEVEL 0
69 static int __verbose = 0;
70 typedef struct bes_registers_s
72 /* base address of yuv framebuffer */
73 uint32_t yuv_base;
74 uint32_t fourcc;
75 uint32_t surf_id;
76 int load_prg_start;
77 int horz_pick_nearest;
78 int vert_pick_nearest;
79 int swap_uv; /* for direct support of bgr fourccs */
80 uint32_t dest_bpp;
81 /* YUV BES registers */
82 uint32_t reg_load_cntl;
83 uint32_t h_inc;
84 uint32_t step_by;
85 uint32_t y_x_start;
86 uint32_t y_x_end;
87 uint32_t v_inc;
88 uint32_t p1_blank_lines_at_top;
89 uint32_t p23_blank_lines_at_top;
90 uint32_t vid_buf_pitch0_value;
91 uint32_t vid_buf_pitch1_value;
92 uint32_t p1_x_start_end;
93 uint32_t p2_x_start_end;
94 uint32_t p3_x_start_end;
95 uint32_t base_addr;
96 uint32_t vid_buf_base_adrs_y[VID_PLAY_MAXFRAMES];
97 uint32_t vid_buf_base_adrs_u[VID_PLAY_MAXFRAMES];
98 uint32_t vid_buf_base_adrs_v[VID_PLAY_MAXFRAMES];
99 uint32_t vid_nbufs;
101 uint32_t p1_v_accum_init;
102 uint32_t p1_h_accum_init;
103 uint32_t p23_v_accum_init;
104 uint32_t p23_h_accum_init;
105 uint32_t scale_cntl;
106 uint32_t exclusive_horz;
107 uint32_t auto_flip_cntl;
108 uint32_t filter_cntl;
109 uint32_t four_tap_coeff[5];
110 uint32_t key_cntl;
111 uint32_t test;
112 /* Configurable stuff */
113 int double_buff;
115 int brightness;
116 int saturation;
118 int ckey_on;
119 uint32_t graphics_key_clr;
120 uint32_t graphics_key_msk;
121 uint32_t ckey_cntl;
122 uint32_t merge_cntl;
124 int deinterlace_on;
125 uint32_t deinterlace_pattern;
127 unsigned chip_flags;
128 } bes_registers_t;
130 typedef struct video_registers_s
132 const char * sname;
133 uint32_t name;
134 uint32_t value;
135 }video_registers_t;
137 static bes_registers_t besr;
138 #define DECLARE_VREG(name) { #name, name, 0 }
139 static video_registers_t vregs[] =
141 DECLARE_VREG(VIDEOMUX_CNTL),
142 DECLARE_VREG(VIPPAD_MASK),
143 DECLARE_VREG(VIPPAD1_A),
144 DECLARE_VREG(VIPPAD1_EN),
145 DECLARE_VREG(VIPPAD1_Y),
146 DECLARE_VREG(OV0_Y_X_START),
147 DECLARE_VREG(OV0_Y_X_END),
148 DECLARE_VREG(OV1_Y_X_START),
149 DECLARE_VREG(OV1_Y_X_END),
150 DECLARE_VREG(OV0_PIPELINE_CNTL),
151 DECLARE_VREG(OV0_EXCLUSIVE_HORZ),
152 DECLARE_VREG(OV0_EXCLUSIVE_VERT),
153 DECLARE_VREG(OV0_REG_LOAD_CNTL),
154 DECLARE_VREG(OV0_SCALE_CNTL),
155 DECLARE_VREG(OV0_V_INC),
156 DECLARE_VREG(OV0_P1_V_ACCUM_INIT),
157 DECLARE_VREG(OV0_P23_V_ACCUM_INIT),
158 DECLARE_VREG(OV0_P1_BLANK_LINES_AT_TOP),
159 DECLARE_VREG(OV0_P23_BLANK_LINES_AT_TOP),
160 #ifdef RADEON
161 DECLARE_VREG(OV0_BASE_ADDR),
162 #endif
163 DECLARE_VREG(OV0_VID_BUF0_BASE_ADRS),
164 DECLARE_VREG(OV0_VID_BUF1_BASE_ADRS),
165 DECLARE_VREG(OV0_VID_BUF2_BASE_ADRS),
166 DECLARE_VREG(OV0_VID_BUF3_BASE_ADRS),
167 DECLARE_VREG(OV0_VID_BUF4_BASE_ADRS),
168 DECLARE_VREG(OV0_VID_BUF5_BASE_ADRS),
169 DECLARE_VREG(OV0_VID_BUF_PITCH0_VALUE),
170 DECLARE_VREG(OV0_VID_BUF_PITCH1_VALUE),
171 DECLARE_VREG(OV0_AUTO_FLIP_CNTL),
172 DECLARE_VREG(OV0_DEINTERLACE_PATTERN),
173 DECLARE_VREG(OV0_SUBMIT_HISTORY),
174 DECLARE_VREG(OV0_H_INC),
175 DECLARE_VREG(OV0_STEP_BY),
176 DECLARE_VREG(OV0_P1_H_ACCUM_INIT),
177 DECLARE_VREG(OV0_P23_H_ACCUM_INIT),
178 DECLARE_VREG(OV0_P1_X_START_END),
179 DECLARE_VREG(OV0_P2_X_START_END),
180 DECLARE_VREG(OV0_P3_X_START_END),
181 DECLARE_VREG(OV0_FILTER_CNTL),
182 DECLARE_VREG(OV0_FOUR_TAP_COEF_0),
183 DECLARE_VREG(OV0_FOUR_TAP_COEF_1),
184 DECLARE_VREG(OV0_FOUR_TAP_COEF_2),
185 DECLARE_VREG(OV0_FOUR_TAP_COEF_3),
186 DECLARE_VREG(OV0_FOUR_TAP_COEF_4),
187 DECLARE_VREG(OV0_FLAG_CNTL),
188 #ifdef RAGE128
189 DECLARE_VREG(OV0_COLOUR_CNTL),
190 #else
191 DECLARE_VREG(OV0_SLICE_CNTL),
192 #endif
193 DECLARE_VREG(OV0_VID_KEY_CLR),
194 DECLARE_VREG(OV0_VID_KEY_MSK),
195 DECLARE_VREG(OV0_GRAPHICS_KEY_CLR),
196 DECLARE_VREG(OV0_GRAPHICS_KEY_MSK),
197 DECLARE_VREG(OV0_KEY_CNTL),
198 DECLARE_VREG(OV0_TEST),
199 DECLARE_VREG(OV0_LIN_TRANS_A),
200 DECLARE_VREG(OV0_LIN_TRANS_B),
201 DECLARE_VREG(OV0_LIN_TRANS_C),
202 DECLARE_VREG(OV0_LIN_TRANS_D),
203 DECLARE_VREG(OV0_LIN_TRANS_E),
204 DECLARE_VREG(OV0_LIN_TRANS_F),
205 DECLARE_VREG(OV0_GAMMA_0_F),
206 DECLARE_VREG(OV0_GAMMA_10_1F),
207 DECLARE_VREG(OV0_GAMMA_20_3F),
208 DECLARE_VREG(OV0_GAMMA_40_7F),
209 DECLARE_VREG(OV0_GAMMA_380_3BF),
210 DECLARE_VREG(OV0_GAMMA_3C0_3FF),
211 DECLARE_VREG(SUBPIC_CNTL),
212 DECLARE_VREG(SUBPIC_DEFCOLCON),
213 DECLARE_VREG(SUBPIC_Y_X_START),
214 DECLARE_VREG(SUBPIC_Y_X_END),
215 DECLARE_VREG(SUBPIC_V_INC),
216 DECLARE_VREG(SUBPIC_H_INC),
217 DECLARE_VREG(SUBPIC_BUF0_OFFSET),
218 DECLARE_VREG(SUBPIC_BUF1_OFFSET),
219 DECLARE_VREG(SUBPIC_LC0_OFFSET),
220 DECLARE_VREG(SUBPIC_LC1_OFFSET),
221 DECLARE_VREG(SUBPIC_PITCH),
222 DECLARE_VREG(SUBPIC_BTN_HLI_COLCON),
223 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_START),
224 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_END),
225 DECLARE_VREG(SUBPIC_PALETTE_INDEX),
226 DECLARE_VREG(SUBPIC_PALETTE_DATA),
227 DECLARE_VREG(SUBPIC_H_ACCUM_INIT),
228 DECLARE_VREG(SUBPIC_V_ACCUM_INIT),
229 DECLARE_VREG(IDCT_RUNS),
230 DECLARE_VREG(IDCT_LEVELS),
231 DECLARE_VREG(IDCT_AUTH_CONTROL),
232 DECLARE_VREG(IDCT_AUTH),
233 DECLARE_VREG(IDCT_CONTROL),
234 #ifdef RAGE128
235 DECLARE_VREG(BM_FRAME_BUF_OFFSET),
236 DECLARE_VREG(BM_SYSTEM_MEM_ADDR),
237 DECLARE_VREG(BM_COMMAND),
238 DECLARE_VREG(BM_STATUS),
239 DECLARE_VREG(BM_QUEUE_STATUS),
240 DECLARE_VREG(BM_QUEUE_FREE_STATUS),
241 DECLARE_VREG(BM_CHUNK_0_VAL),
242 DECLARE_VREG(BM_CHUNK_1_VAL),
243 DECLARE_VREG(BM_VIP0_BUF),
244 DECLARE_VREG(BM_VIP0_ACTIVE),
245 DECLARE_VREG(BM_VIP1_BUF),
246 DECLARE_VREG(BM_VIP1_ACTIVE),
247 DECLARE_VREG(BM_VIP2_BUF),
248 DECLARE_VREG(BM_VIP2_ACTIVE),
249 DECLARE_VREG(BM_VIP3_BUF),
250 DECLARE_VREG(BM_VIP3_ACTIVE),
251 DECLARE_VREG(BM_VIDCAP_BUF0),
252 DECLARE_VREG(BM_VIDCAP_BUF1),
253 DECLARE_VREG(BM_VIDCAP_BUF2),
254 DECLARE_VREG(BM_VIDCAP_ACTIVE),
255 DECLARE_VREG(BM_GUI),
256 DECLARE_VREG(BM_ABORT)
257 #else
258 DECLARE_VREG(DISP_MERGE_CNTL),
259 DECLARE_VREG(DMA_GUI_TABLE_ADDR),
260 DECLARE_VREG(DMA_GUI_SRC_ADDR),
261 DECLARE_VREG(DMA_GUI_DST_ADDR),
262 DECLARE_VREG(DMA_GUI_COMMAND),
263 DECLARE_VREG(DMA_GUI_STATUS),
264 DECLARE_VREG(DMA_GUI_ACT_DSCRPTR),
265 DECLARE_VREG(DMA_VID_SRC_ADDR),
266 DECLARE_VREG(DMA_VID_DST_ADDR),
267 DECLARE_VREG(DMA_VID_COMMAND),
268 DECLARE_VREG(DMA_VID_STATUS),
269 DECLARE_VREG(DMA_VID_ACT_DSCRPTR),
270 #endif
273 #define R_FAMILY 0x000000FF
274 #define R_100 0x00000001
275 #define R_120 0x00000002
276 #define R_150 0x00000004
277 #define R_200 0x00000008
278 #define R_250 0x00000010
279 #define R_280 0x00000020
280 #define R_300 0x00000040
281 #define R_350 0x00000080
282 #define R_370 0x00000100
283 #define R_380 0x00000200
284 #define R_420 0x00000400
285 #define R_430 0x00000800
286 #define R_480 0x00001000
287 #define R_OVL_SHIFT 0x01000000
288 #define R_INTEGRATED 0x02000000
289 #define R_PCIE 0x04000000
291 typedef struct ati_card_ids_s
293 unsigned short id;
294 unsigned flags;
295 }ati_card_ids_t;
297 static const ati_card_ids_t ati_card_ids[] =
299 #ifdef RAGE128
301 This driver should be compatible with Rage128 (pro) chips.
302 (include adaptive deinterlacing!!!).
303 Moreover: the same logic can be used with Mach64 chips.
304 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
305 but they are incompatible by i/o ports. So if enthusiasts will want
306 then they can redefine OUTREG and INREG macros and redefine OV0_*
307 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
308 fourccs (422 and 420 formats only).
310 /* Rage128 Pro GL */
311 { DEVICE_ATI_RAGE_128_PA_PRO, 0 },
312 { DEVICE_ATI_RAGE_128_PB_PRO, 0 },
313 { DEVICE_ATI_RAGE_128_PC_PRO, 0 },
314 { DEVICE_ATI_RAGE_128_PD_PRO, 0 },
315 { DEVICE_ATI_RAGE_128_PE_PRO, 0 },
316 { DEVICE_ATI_RAGE_128_PF_PRO, 0 },
317 /* Rage128 Pro VR */
318 { DEVICE_ATI_RAGE_128_PG_PRO, 0 },
319 { DEVICE_ATI_RAGE_128_PH_PRO, 0 },
320 { DEVICE_ATI_RAGE_128_PI_PRO, 0 },
321 { DEVICE_ATI_RAGE_128_PJ_PRO, 0 },
322 { DEVICE_ATI_RAGE_128_PK_PRO, 0 },
323 { DEVICE_ATI_RAGE_128_PL_PRO, 0 },
324 { DEVICE_ATI_RAGE_128_PM_PRO, 0 },
325 { DEVICE_ATI_RAGE_128_PN_PRO, 0 },
326 { DEVICE_ATI_RAGE_128_PO_PRO, 0 },
327 { DEVICE_ATI_RAGE_128_PP_PRO, 0 },
328 { DEVICE_ATI_RAGE_128_PQ_PRO, 0 },
329 { DEVICE_ATI_RAGE_128_PR_PRO, 0 },
330 { DEVICE_ATI_RAGE_128_PS_PRO, 0 },
331 { DEVICE_ATI_RAGE_128_PT_PRO, 0 },
332 { DEVICE_ATI_RAGE_128_PU_PRO, 0 },
333 { DEVICE_ATI_RAGE_128_PV_PRO, 0 },
334 { DEVICE_ATI_RAGE_128_PW_PRO, 0 },
335 { DEVICE_ATI_RAGE_128_PX_PRO, 0 },
336 /* Rage128 GL */
337 { DEVICE_ATI_RAGE_128_RE_SG, 0 },
338 { DEVICE_ATI_RAGE_128_RF_SG, 0 },
339 { DEVICE_ATI_RAGE_128_RG, 0 },
340 { DEVICE_ATI_RAGE_128_RK_VR, 0 },
341 { DEVICE_ATI_RAGE_128_RL_VR, 0 },
342 { DEVICE_ATI_RAGE_128_SE_4X, 0 },
343 { DEVICE_ATI_RAGE_128_SF_4X, 0 },
344 { DEVICE_ATI_RAGE_128_SG_4X, 0 },
345 { DEVICE_ATI_RAGE_128_SH, 0 },
346 { DEVICE_ATI_RAGE_128_SK_4X, 0 },
347 { DEVICE_ATI_RAGE_128_SL_4X, 0 },
348 { DEVICE_ATI_RAGE_128_SM_4X, 0 },
349 { DEVICE_ATI_RAGE_128_4X, 0 },
350 { DEVICE_ATI_RAGE_128_PRO, 0 },
351 { DEVICE_ATI_RAGE_128_PRO2, 0 },
352 { DEVICE_ATI_RAGE_128_PRO3, 0 },
353 /* these seem to be based on rage 128 instead of mach64 */
354 { DEVICE_ATI_RAGE_MOBILITY_M3, 0 },
355 { DEVICE_ATI_RAGE_MOBILITY_M32, 0 },
356 #else
357 /* Radeon1 (indeed: Rage 256 Pro ;) */
358 { DEVICE_ATI_RADEON_R100_QD, R_100|R_OVL_SHIFT },
359 { DEVICE_ATI_RADEON_R100_QE, R_100|R_OVL_SHIFT },
360 { DEVICE_ATI_RADEON_R100_QF, R_100|R_OVL_SHIFT },
361 { DEVICE_ATI_RADEON_R100_QG, R_100|R_OVL_SHIFT },
362 { DEVICE_ATI_RADEON_IGP_320, R_150|R_OVL_SHIFT|R_INTEGRATED },
363 { DEVICE_ATI_RADEON_MOBILITY_U1, R_150|R_OVL_SHIFT|R_INTEGRATED },
364 { DEVICE_ATI_RADEON_RV100_QY, R_120|R_OVL_SHIFT },
365 { DEVICE_ATI_RADEON_RV100_QZ, R_120|R_OVL_SHIFT },
366 { DEVICE_ATI_RADEON_MOBILITY_M7, R_150|R_OVL_SHIFT },
367 { DEVICE_ATI_RADEON_RV200_LX, R_150|R_OVL_SHIFT },
368 { DEVICE_ATI_RADEON_MOBILITY_M6, R_120|R_OVL_SHIFT },
369 { DEVICE_ATI_RADEON_MOBILITY_M62, R_120|R_OVL_SHIFT },
370 /* Radeon2 (indeed: Rage 512 Pro ;) */
371 { DEVICE_ATI_R200_BB_RADEON, R_200 },
372 { DEVICE_ATI_R200_BC_RADEON, R_200 },
373 { DEVICE_ATI_RADEON_R200_QH, R_200 },
374 { DEVICE_ATI_RADEON_R200_QI, R_200 },
375 { DEVICE_ATI_RADEON_R200_QJ, R_200 },
376 { DEVICE_ATI_RADEON_R200_QK, R_200 },
377 { DEVICE_ATI_RADEON_R200_QL, R_200 },
378 { DEVICE_ATI_RADEON_R200_QM, R_200 },
379 { DEVICE_ATI_RADEON_R200_QN, R_200 },
380 { DEVICE_ATI_RADEON_R200_QO, R_200 },
381 { DEVICE_ATI_RADEON_R200_QH2, R_200 },
382 { DEVICE_ATI_RADEON_R200_QI2, R_200 },
383 { DEVICE_ATI_RADEON_R200_QJ2, R_200 },
384 { DEVICE_ATI_RADEON_R200_QK2, R_200 },
385 { DEVICE_ATI_RADEON_R200_QL2, R_200 },
386 { DEVICE_ATI_RADEON_RV200_QW, R_150|R_OVL_SHIFT },
387 { DEVICE_ATI_RADEON_RV200_QX, R_150|R_OVL_SHIFT },
388 { DEVICE_ATI_RADEON_IGP330_340_350,R_200|R_INTEGRATED },
389 { DEVICE_ATI_RADEON_IGP_330M_340M_350M,R_200|R_INTEGRATED },
390 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
391 { DEVICE_ATI_RADEON_7000_IGP, R_250|R_OVL_SHIFT|R_INTEGRATED },
392 { DEVICE_ATI_RADEON_MOBILITY_7000, R_250|R_OVL_SHIFT|R_INTEGRATED },
393 { DEVICE_ATI_RADEON_RV250_ID, R_250|R_OVL_SHIFT },
394 { DEVICE_ATI_RADEON_RV250_IE, R_250|R_OVL_SHIFT },
395 { DEVICE_ATI_RADEON_RV250_IF, R_250|R_OVL_SHIFT },
396 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
397 { DEVICE_ATI_RADEON_R250_LD, R_250|R_OVL_SHIFT },
398 { DEVICE_ATI_RADEON_R250_LE, R_250|R_OVL_SHIFT },
399 { DEVICE_ATI_RADEON_R250_MOBILITY, R_250|R_OVL_SHIFT },
400 { DEVICE_ATI_RADEON_R250_LG, R_250|R_OVL_SHIFT },
401 { DEVICE_ATI_RV250_RADEON_9000, R_250|R_OVL_SHIFT },
402 { DEVICE_ATI_RADEON_RV250_RADEON2, R_250|R_OVL_SHIFT },
403 { DEVICE_ATI_RV280_RADEON_9200, R_280 },
404 { DEVICE_ATI_RV280_RADEON_92002, R_280 },
405 { DEVICE_ATI_RV280_RADEON_92003, R_280 },
406 { DEVICE_ATI_RV280_RADEON_92004, R_280 },
407 { DEVICE_ATI_RV280_RADEON_92005, R_280 },
408 { DEVICE_ATI_RV280_RADEON_92006, R_280 },
409 { DEVICE_ATI_RV280_RADEON_92007, R_280 },
410 { DEVICE_ATI_M9_5C61_RADEON, R_280 },
411 { DEVICE_ATI_M9_5C63_RADEON, R_280 },
412 /* Radeon3 (indeed: Rage 1024 Pro ;) */
413 { DEVICE_ATI_R300_AG_FIREGL, R_300 },
414 { DEVICE_ATI_RADEON_R300_ND, R_300 },
415 { DEVICE_ATI_RADEON_R300_NE, R_300 },
416 { DEVICE_ATI_RADEON_R300_NG, R_300 },
417 { DEVICE_ATI_R300_AD_RADEON, R_300 },
418 { DEVICE_ATI_R300_AE_RADEON, R_300 },
419 { DEVICE_ATI_R300_AF_RADEON, R_300 },
420 { DEVICE_ATI_RADEON_9100_IGP2, R_300|R_OVL_SHIFT|R_INTEGRATED },
421 { DEVICE_ATI_RS300M_AGP_RADEON, R_300|R_INTEGRATED },
422 { DEVICE_ATI_RS482_RADEON_XPRESS, R_350|R_INTEGRATED },
423 { DEVICE_ATI_R350_AH_RADEON, R_350 },
424 { DEVICE_ATI_R350_AI_RADEON, R_350 },
425 { DEVICE_ATI_R350_AJ_RADEON, R_350 },
426 { DEVICE_ATI_R350_AK_FIRE, R_350 },
427 { DEVICE_ATI_RADEON_R350_RADEON2, R_350 },
428 { DEVICE_ATI_RADEON_R350_RADEON3, R_350 },
429 { DEVICE_ATI_RV350_NJ_RADEON, R_350 },
430 { DEVICE_ATI_R350_NK_FIRE, R_350 },
431 { DEVICE_ATI_RV350_AP_RADEON, R_350 },
432 { DEVICE_ATI_RV350_AQ_RADEON, R_350 },
433 { DEVICE_ATI_RV350_AR_RADEON, R_350 },
434 { DEVICE_ATI_RV350_AS_RADEON, R_350 },
435 { DEVICE_ATI_RV350_AT_FIRE, R_350 },
436 { DEVICE_ATI_RV350_AU_FIRE, R_350 },
437 { DEVICE_ATI_RV350_AV_FIRE, R_350 },
438 { DEVICE_ATI_RV350_AW_FIRE, R_350 },
439 { DEVICE_ATI_RV350_MOBILITY_RADEON, R_350 },
440 { DEVICE_ATI_RV350_NF_RADEON, R_300 },
441 { DEVICE_ATI_RV350_NJ_RADEON, R_300 },
442 { DEVICE_ATI_RV350_AS_RADEON2, R_350 },
443 { DEVICE_ATI_M10_NQ_RADEON, R_350 },
444 { DEVICE_ATI_M10_NQ_RADEON2, R_350 },
445 { DEVICE_ATI_RV350_MOBILITY_RADEON2, R_350 },
446 { DEVICE_ATI_M10_NS_RADEON, R_350 },
447 { DEVICE_ATI_M10_NT_FIREGL, R_350 },
448 { DEVICE_ATI_M11_NV_FIREGL, R_350 },
449 { DEVICE_ATI_RV370_5B60_RADEON, R_370|R_PCIE },
450 { DEVICE_ATI_RV370_SAPPHIRE_X550, R_370 },
451 { DEVICE_ATI_RV370_5B64_FIREGL, R_370|R_PCIE },
452 { DEVICE_ATI_RV370_5B65_FIREGL, R_370|R_PCIE },
453 { DEVICE_ATI_M24_1P_RADEON, R_370 },
454 { DEVICE_ATI_M22_RADEON_MOBILITY, R_370 },
455 { DEVICE_ATI_M24_1T_FIREGL, R_370 },
456 { DEVICE_ATI_M24_RADEON_MOBILITY, R_370 },
457 { DEVICE_ATI_RV370_RADEON_X300SE, R_370 },
458 { DEVICE_ATI_RV370_SECONDARY_SAPPHIRE, R_370 },
459 { DEVICE_ATI_RV370_5B64_FIREGL2, R_370 },
460 { DEVICE_ATI_RV380_0X3E50_RADEON, R_380|R_PCIE },
461 { DEVICE_ATI_RV380_0X3E54_FIREGL, R_380|R_PCIE },
462 { DEVICE_ATI_RV380_RADEON_X600, R_380|R_PCIE },
463 { DEVICE_ATI_RV380_RADEON_X6002, R_380 },
464 { DEVICE_ATI_RV380_RADEON_X6003, R_380 },
465 { DEVICE_ATI_RV410_FIREGL_V5000, R_420 },
466 { DEVICE_ATI_RV410_FIREGL_V3300, R_420 },
467 { DEVICE_ATI_RV410_RADEON_X700XT, R_420 },
468 { DEVICE_ATI_RV410_RADEON_X700, R_420|R_PCIE },
469 { DEVICE_ATI_RV410_RADEON_X700SE, R_420 },
470 { DEVICE_ATI_RV410_RADEON_X7002, R_420|R_PCIE },
471 { DEVICE_ATI_RV410_RADEON_X7003, R_420 },
472 { DEVICE_ATI_RV410_RADEON_X7004, R_420|R_PCIE },
473 { DEVICE_ATI_RV410_RADEON_X7005, R_420|R_PCIE },
474 { DEVICE_ATI_M26_MOBILITY_FIREGL, R_420 },
475 { DEVICE_ATI_M26_MOBILITY_FIREGL2, R_420 },
476 { DEVICE_ATI_M26_RADEON_MOBILITY, R_420 },
477 { DEVICE_ATI_M26_RADEON_MOBILITY2, R_420 },
478 { DEVICE_ATI_RADEON_MOBILITY_X700, R_420 },
479 { DEVICE_ATI_R420_JH_RADEON, R_420|R_PCIE },
480 { DEVICE_ATI_R420_JI_RADEON, R_420|R_PCIE },
481 { DEVICE_ATI_R420_JJ_RADEON, R_420|R_PCIE },
482 { DEVICE_ATI_R420_JK_RADEON, R_420|R_PCIE },
483 { DEVICE_ATI_R420_JL_RADEON, R_420|R_PCIE },
484 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
485 { DEVICE_ATI_M18_JN_RADEON, R_420|R_PCIE },
486 { DEVICE_ATI_R420_JP_RADEON, R_420|R_PCIE },
487 { DEVICE_ATI_R420_RADEON_X800, R_420|R_PCIE },
488 { DEVICE_ATI_R420_RADEON_X8002, R_420|R_PCIE },
489 { DEVICE_ATI_R420_RADEON_X8003, R_420|R_PCIE },
490 { DEVICE_ATI_R420_RADEON_X8004, R_420|R_PCIE },
491 { DEVICE_ATI_R420_RADEON_X8005, R_420|R_PCIE },
492 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
493 { DEVICE_ATI_R423_5F57_RADEON, R_420|R_PCIE },
494 { DEVICE_ATI_R423_5F57_RADEON2, R_420|R_PCIE },
495 { DEVICE_ATI_R423_UH_RADEON, R_420|R_PCIE },
496 { DEVICE_ATI_R423_UI_RADEON, R_420|R_PCIE },
497 { DEVICE_ATI_R423_UJ_RADEON, R_420|R_PCIE },
498 { DEVICE_ATI_R423_UK_RADEON, R_420|R_PCIE },
499 { DEVICE_ATI_R423_FIRE_GL, R_420|R_PCIE },
500 { DEVICE_ATI_R423_UQ_FIREGL, R_420|R_PCIE },
501 { DEVICE_ATI_R423_UR_FIREGL, R_420|R_PCIE },
502 { DEVICE_ATI_R423_UT_FIREGL, R_420|R_PCIE },
503 { DEVICE_ATI_R423_UI_RADEON2, R_420|R_PCIE },
504 { DEVICE_ATI_R423GL_SE_ATI_FIREGL, R_420|R_PCIE },
505 { DEVICE_ATI_R423_RADEON_X800XT, R_420|R_PCIE },
506 { DEVICE_ATI_RADEON_R423_UK, R_420|R_PCIE },
507 { DEVICE_ATI_M28_RADEON_MOBILITY, R_420 },
508 { DEVICE_ATI_M28_MOBILITY_FIREGL, R_420 },
509 { DEVICE_ATI_MOBILITY_RADEON_X800, R_420 },
510 { DEVICE_ATI_R430_RADEON_X800, R_430|R_PCIE },
511 { DEVICE_ATI_R430_RADEON_X8002, R_430|R_PCIE },
512 { DEVICE_ATI_R430_RADEON_X8003, R_430|R_PCIE },
513 { DEVICE_ATI_R430_RADEON_X8004, R_430|R_PCIE },
514 { DEVICE_ATI_R480_RADEON_X800, R_480 },
515 { DEVICE_ATI_R480_RADEON_X8002, R_480 },
516 { DEVICE_ATI_R480_RADEON_X850XT, R_480 },
517 { DEVICE_ATI_R480_RADEON_X850PRO, R_480 },
518 { DEVICE_ATI_R481_RADEON_X850XT_PE, R_480|R_PCIE },
519 { DEVICE_ATI_R480_RADEON_X850XT2, R_480 },
520 { DEVICE_ATI_R480_RADEON_X850PRO2, R_480 },
521 { DEVICE_ATI_R481_RADEON_X850XT_PE2, R_480|R_PCIE },
522 { DEVICE_ATI_R480_RADEON_X850XT3, R_480|R_PCIE },
523 { DEVICE_ATI_R480_RADEON_X850XT4, R_480|R_PCIE },
524 { DEVICE_ATI_R480_RADEON_X850XT5, R_480|R_PCIE },
525 { DEVICE_ATI_R480_RADEON_X850XT6, R_480|R_PCIE },
526 #endif
530 static void * radeon_mmio_base = 0;
531 static void * radeon_mem_base = 0;
532 static int32_t radeon_overlay_off = 0;
533 static uint32_t radeon_ram_size = 0;
535 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
536 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
538 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr)
539 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr,val)
540 static inline uint32_t INREG (uint32_t addr) {
541 uint32_t tmp = GETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr);
542 return le2me_32(tmp);
544 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr,le2me_32(val))
545 #define OUTREGP(addr,val,mask) \
546 do { \
547 unsigned int _tmp = INREG(addr); \
548 _tmp &= (mask); \
549 _tmp |= (val); \
550 OUTREG(addr, _tmp); \
551 } while (0)
553 static __inline__ uint32_t INPLL(uint32_t addr)
555 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f);
556 return (INREG(CLOCK_CNTL_DATA));
559 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \
560 OUTREG(CLOCK_CNTL_DATA, val)
561 #define OUTPLLP(addr,val,mask) \
562 do { \
563 unsigned int _tmp = INPLL(addr); \
564 _tmp &= (mask); \
565 _tmp |= (val); \
566 OUTPLL(addr, _tmp); \
567 } while (0)
569 #ifndef RAGE128
570 enum radeon_montype
572 MT_NONE,
573 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */
574 MT_LCD, /* Liquid Crystal Display */
575 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */
576 MT_CTV, /* Composite TV out (not in VE) */
577 MT_STV /* S-Video TV out (probably in VE only) */
580 typedef struct radeon_info_s
582 int hasCRTC2;
583 int crtDispType;
584 int dviDispType;
585 }rinfo_t;
587 static rinfo_t rinfo;
589 static char * GET_MON_NAME(int type)
591 char *pret;
592 switch(type)
594 case MT_NONE: pret = "no"; break;
595 case MT_CRT: pret = "CRT"; break;
596 case MT_DFP: pret = "DFP"; break;
597 case MT_LCD: pret = "LCD"; break;
598 case MT_CTV: pret = "CTV"; break;
599 case MT_STV: pret = "STV"; break;
600 default: pret = "Unknown";
602 return pret;
605 static void radeon_get_moninfo (rinfo_t *rinfo)
607 unsigned int tmp;
609 tmp = INREG(RADEON_BIOS_4_SCRATCH);
611 if (rinfo->hasCRTC2) {
612 /* primary DVI port */
613 if (tmp & 0x08)
614 rinfo->dviDispType = MT_DFP;
615 else if (tmp & 0x4)
616 rinfo->dviDispType = MT_LCD;
617 else if (tmp & 0x200)
618 rinfo->dviDispType = MT_CRT;
619 else if (tmp & 0x10)
620 rinfo->dviDispType = MT_CTV;
621 else if (tmp & 0x20)
622 rinfo->dviDispType = MT_STV;
624 /* secondary CRT port */
625 if (tmp & 0x2)
626 rinfo->crtDispType = MT_CRT;
627 else if (tmp & 0x800)
628 rinfo->crtDispType = MT_DFP;
629 else if (tmp & 0x400)
630 rinfo->crtDispType = MT_LCD;
631 else if (tmp & 0x1000)
632 rinfo->crtDispType = MT_CTV;
633 else if (tmp & 0x2000)
634 rinfo->crtDispType = MT_STV;
635 } else {
636 rinfo->dviDispType = MT_NONE;
638 tmp = INREG(FP_GEN_CNTL);
640 if (tmp & FP_EN_TMDS)
641 rinfo->crtDispType = MT_DFP;
642 else
643 rinfo->crtDispType = MT_CRT;
646 #endif
648 static uint32_t radeon_vid_get_dbpp( void )
650 uint32_t dbpp,retval;
651 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF;
652 switch(dbpp)
654 case DST_8BPP: retval = 8; break;
655 case DST_15BPP: retval = 15; break;
656 case DST_16BPP: retval = 16; break;
657 case DST_24BPP: retval = 24; break;
658 default: retval=32; break;
660 return retval;
663 static int radeon_is_dbl_scan( void )
665 return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN;
668 static int radeon_is_interlace( void )
670 return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN;
673 static uint32_t radeon_get_xres( void )
675 uint32_t xres,h_total;
676 #ifndef RAGE128
677 if(rinfo.hasCRTC2 &&
678 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
679 h_total = INREG(CRTC2_H_TOTAL_DISP);
680 else
681 #endif
682 h_total = INREG(CRTC_H_TOTAL_DISP);
683 xres = (h_total >> 16) & 0xffff;
684 return (xres + 1)*8;
687 static uint32_t radeon_get_yres( void )
689 uint32_t yres,v_total;
690 #ifndef RAGE128
691 if(rinfo.hasCRTC2 &&
692 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
693 v_total = INREG(CRTC2_V_TOTAL_DISP);
694 else
695 #endif
696 v_total = INREG(CRTC_V_TOTAL_DISP);
697 yres = (v_total >> 16) & 0xffff;
698 return yres + 1;
701 static void radeon_wait_vsync(void)
703 int i;
705 OUTREG(GEN_INT_STATUS, VSYNC_INT_AK);
706 for (i = 0; i < 2000000; i++)
708 if (INREG(GEN_INT_STATUS) & VSYNC_INT) break;
712 #ifdef RAGE128
713 static void _radeon_engine_idle(void);
714 static void _radeon_fifo_wait(unsigned);
715 #define radeon_engine_idle() _radeon_engine_idle()
716 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
717 /* Flush all dirty data in the Pixel Cache to memory. */
718 static __inline__ void radeon_engine_flush ( void )
720 unsigned i;
722 OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL);
723 for (i = 0; i < 2000000; i++) {
724 if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break;
728 /* Reset graphics card to known state. */
729 static void radeon_engine_reset( void )
731 uint32_t clock_cntl_index;
732 uint32_t mclk_cntl;
733 uint32_t gen_reset_cntl;
735 radeon_engine_flush();
737 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
738 mclk_cntl = INPLL(MCLK_CNTL);
740 OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP);
742 gen_reset_cntl = INREG(GEN_RESET_CNTL);
744 OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
745 INREG(GEN_RESET_CNTL);
746 OUTREG(GEN_RESET_CNTL,
747 gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI));
748 INREG(GEN_RESET_CNTL);
750 OUTPLL(MCLK_CNTL, mclk_cntl);
751 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
752 OUTREG(GEN_RESET_CNTL, gen_reset_cntl);
754 #else
756 static __inline__ void radeon_engine_flush ( void )
758 int i;
760 /* initiate flush */
761 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
762 ~RB2D_DC_FLUSH_ALL);
764 for (i=0; i < 2000000; i++) {
765 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
766 break;
770 static void _radeon_engine_idle(void);
771 static void _radeon_fifo_wait(unsigned);
772 #define radeon_engine_idle() _radeon_engine_idle()
773 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
775 static void radeon_engine_reset( void )
777 uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
779 radeon_engine_flush ();
781 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
782 mclk_cntl = INPLL(MCLK_CNTL);
784 OUTPLL(MCLK_CNTL, (mclk_cntl |
785 FORCEON_MCLKA |
786 FORCEON_MCLKB |
787 FORCEON_YCLKA |
788 FORCEON_YCLKB |
789 FORCEON_MC |
790 FORCEON_AIC));
791 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
793 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
794 SOFT_RESET_CP |
795 SOFT_RESET_HI |
796 SOFT_RESET_SE |
797 SOFT_RESET_RE |
798 SOFT_RESET_PP |
799 SOFT_RESET_E2 |
800 SOFT_RESET_RB |
801 SOFT_RESET_HDP);
802 INREG(RBBM_SOFT_RESET);
803 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t)
804 ~(SOFT_RESET_CP |
805 SOFT_RESET_HI |
806 SOFT_RESET_SE |
807 SOFT_RESET_RE |
808 SOFT_RESET_PP |
809 SOFT_RESET_E2 |
810 SOFT_RESET_RB |
811 SOFT_RESET_HDP));
812 INREG(RBBM_SOFT_RESET);
814 OUTPLL(MCLK_CNTL, mclk_cntl);
815 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
816 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
818 return;
820 #endif
821 static void radeon_engine_restore( void )
823 #ifndef RAGE128
824 int pitch64;
825 uint32_t xres,yres,bpp;
826 radeon_fifo_wait(1);
827 xres = radeon_get_xres();
828 yres = radeon_get_yres();
829 bpp = radeon_vid_get_dbpp();
830 /* turn of all automatic flushing - we'll do it all */
831 OUTREG(RB2D_DSTCACHE_MODE, 0);
833 pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6;
835 radeon_fifo_wait(1);
836 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) |
837 (pitch64 << 22));
839 radeon_fifo_wait(1);
840 #if defined(WORDS_BIGENDIAN)
841 OUTREGP(DP_DATATYPE,
842 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
843 #else
844 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
845 #endif
847 radeon_fifo_wait(1);
848 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX
849 | DEFAULT_SC_BOTTOM_MAX));
850 radeon_fifo_wait(1);
851 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL)
852 | GMC_BRUSH_SOLID_COLOR
853 | GMC_SRC_DATATYPE_COLOR));
855 radeon_fifo_wait(7);
856 OUTREG(DST_LINE_START, 0);
857 OUTREG(DST_LINE_END, 0);
858 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
859 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
860 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
861 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
862 OUTREG(DP_WRITE_MASK, 0xffffffff);
864 radeon_engine_idle();
865 #endif
867 #ifdef RAGE128
868 static void _radeon_fifo_wait (unsigned entries)
870 unsigned i;
872 for(;;)
874 for (i=0; i<2000000; i++)
875 if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries)
876 return;
877 radeon_engine_reset();
878 radeon_engine_restore();
882 static void _radeon_engine_idle ( void )
884 unsigned i;
886 /* ensure FIFO is empty before waiting for idle */
887 radeon_fifo_wait (64);
888 for(;;)
890 for (i=0; i<2000000; i++) {
891 if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) {
892 radeon_engine_flush ();
893 return;
896 radeon_engine_reset();
897 radeon_engine_restore();
900 #else
901 static void _radeon_fifo_wait (unsigned entries)
903 unsigned i;
905 for(;;)
907 for (i=0; i<2000000; i++)
908 if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries)
909 return;
910 radeon_engine_reset();
911 radeon_engine_restore();
914 static void _radeon_engine_idle ( void )
916 int i;
918 /* ensure FIFO is empty before waiting for idle */
919 radeon_fifo_wait (64);
920 for(;;)
922 for (i=0; i<2000000; i++) {
923 if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) {
924 radeon_engine_flush ();
925 return;
928 radeon_engine_reset();
929 radeon_engine_restore();
932 #endif
934 #ifndef RAGE128
935 /* Reference color space transform data */
936 typedef struct tagREF_TRANSFORM
938 float RefLuma;
939 float RefRCb;
940 float RefRCr;
941 float RefGCb;
942 float RefGCr;
943 float RefBCb;
944 float RefBCr;
945 } REF_TRANSFORM;
947 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
948 REF_TRANSFORM trans[2] =
950 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
951 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
953 /****************************************************************************
954 * SetTransform *
955 * Function: Calculates and sets color space transform from supplied *
956 * reference transform, gamma, brightness, contrast, hue and *
957 * saturation. *
958 * Inputs: bright - brightness *
959 * cont - contrast *
960 * sat - saturation *
961 * hue - hue *
962 * red_intensity - intense of red component *
963 * green_intensity - intense of green component *
964 * blue_intensity - intense of blue component *
965 * ref - index to the table of refernce transforms *
966 * Outputs: NONE *
967 ****************************************************************************/
969 static void radeon_set_transform(float bright, float cont, float sat,
970 float hue, float red_intensity,
971 float green_intensity,float blue_intensity,
972 unsigned ref)
974 float OvHueSin, OvHueCos;
975 float CAdjLuma, CAdjOff;
976 float RedAdj,GreenAdj,BlueAdj;
977 float CAdjRCb, CAdjRCr;
978 float CAdjGCb, CAdjGCr;
979 float CAdjBCb, CAdjBCr;
980 float OvLuma, OvROff, OvGOff, OvBOff;
981 float OvRCb, OvRCr;
982 float OvGCb, OvGCr;
983 float OvBCb, OvBCr;
984 float Loff = 64.0;
985 float Coff = 512.0f;
987 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
988 uint32_t dwOvRCb, dwOvRCr;
989 uint32_t dwOvGCb, dwOvGCr;
990 uint32_t dwOvBCb, dwOvBCr;
992 if (ref >= 2) return;
994 OvHueSin = sin((double)hue);
995 OvHueCos = cos((double)hue);
997 CAdjLuma = cont * trans[ref].RefLuma;
998 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
999 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
1000 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
1001 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
1003 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
1004 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
1005 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1006 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1007 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1008 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1010 OvLuma = CAdjLuma;
1011 OvRCb = CAdjRCb;
1012 OvRCr = CAdjRCr;
1013 OvGCb = CAdjGCb;
1014 OvGCr = CAdjGCr;
1015 OvBCb = CAdjBCb;
1016 OvBCr = CAdjBCr;
1017 OvROff = RedAdj + CAdjOff -
1018 OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1019 OvGOff = GreenAdj + CAdjOff -
1020 OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1021 OvBOff = BlueAdj + CAdjOff -
1022 OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1024 dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff;
1025 dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff;
1026 dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff;
1027 /* Whatever docs say about R200 having 3.8 format instead of 3.11
1028 as in Radeon is a lie */
1030 dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17;
1031 dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1;
1032 dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17;
1033 dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1;
1034 dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17;
1035 dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1;
1036 dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17;
1038 OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1039 OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1040 OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1041 OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1042 OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1043 OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1046 /* Gamma curve definition */
1047 typedef struct
1049 unsigned int gammaReg;
1050 unsigned int gammaSlope;
1051 unsigned int gammaOffset;
1052 }GAMMA_SETTINGS;
1054 /* Recommended gamma curve parameters */
1055 GAMMA_SETTINGS r200_def_gamma[18] =
1057 {OV0_GAMMA_0_F, 0x100, 0x0000},
1058 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1059 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1060 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1061 {OV0_GAMMA_80_BF, 0x100, 0x0100},
1062 {OV0_GAMMA_C0_FF, 0x100, 0x0100},
1063 {OV0_GAMMA_100_13F, 0x100, 0x0200},
1064 {OV0_GAMMA_140_17F, 0x100, 0x0200},
1065 {OV0_GAMMA_180_1BF, 0x100, 0x0300},
1066 {OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
1067 {OV0_GAMMA_200_23F, 0x100, 0x0400},
1068 {OV0_GAMMA_240_27F, 0x100, 0x0400},
1069 {OV0_GAMMA_280_2BF, 0x100, 0x0500},
1070 {OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
1071 {OV0_GAMMA_300_33F, 0x100, 0x0600},
1072 {OV0_GAMMA_340_37F, 0x100, 0x0600},
1073 {OV0_GAMMA_380_3BF, 0x100, 0x0700},
1074 {OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
1077 GAMMA_SETTINGS r100_def_gamma[6] =
1079 {OV0_GAMMA_0_F, 0x100, 0x0000},
1080 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1081 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1082 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1083 {OV0_GAMMA_380_3BF, 0x100, 0x0100},
1084 {OV0_GAMMA_3C0_3FF, 0x100, 0x0100}
1087 static void make_default_gamma_correction( void )
1089 size_t i;
1090 if((besr.chip_flags & R_100)==R_100||
1091 (besr.chip_flags & R_120)==R_120||
1092 (besr.chip_flags & R_150)==R_150){
1093 OUTREG(OV0_LIN_TRANS_A, 0x12A00000);
1094 OUTREG(OV0_LIN_TRANS_B, 0x199018FE);
1095 OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0);
1096 OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B);
1097 OUTREG(OV0_LIN_TRANS_E, 0x12A02050);
1098 OUTREG(OV0_LIN_TRANS_F, 0x0000174E);
1099 for(i=0; i<6; i++){
1100 OUTREG(r100_def_gamma[i].gammaReg,
1101 (r100_def_gamma[i].gammaSlope<<16) |
1102 r100_def_gamma[i].gammaOffset);
1105 else{
1106 OUTREG(OV0_LIN_TRANS_A, 0x12a20000);
1107 OUTREG(OV0_LIN_TRANS_B, 0x198a190e);
1108 OUTREG(OV0_LIN_TRANS_C, 0x12a2f9da);
1109 OUTREG(OV0_LIN_TRANS_D, 0xf2fe0442);
1110 OUTREG(OV0_LIN_TRANS_E, 0x12a22046);
1111 OUTREG(OV0_LIN_TRANS_F, 0x175f);
1112 /* Default Gamma,
1113 Of 18 segments for gamma cure, all segments in R200 are programmable,
1114 while only lower 4 and upper 2 segments are programmable in Radeon*/
1115 for(i=0; i<18; i++){
1116 OUTREG(r200_def_gamma[i].gammaReg,
1117 (r200_def_gamma[i].gammaSlope<<16) |
1118 r200_def_gamma[i].gammaOffset);
1122 #endif
1124 static void radeon_vid_make_default(void)
1126 #ifdef RAGE128
1127 besr.saturation = 0x0F;
1128 besr.brightness = 0;
1129 OUTREG(OV0_COLOUR_CNTL,0x000F0F00UL); /* Default brihgtness and saturation for Rage128 */
1130 #else
1131 make_default_gamma_correction();
1132 #endif
1133 besr.deinterlace_pattern = 0x900AAAAA;
1134 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1135 besr.deinterlace_on=1;
1136 besr.double_buff=1;
1137 besr.ckey_on=0;
1138 besr.graphics_key_msk=0;
1139 besr.graphics_key_clr=0;
1140 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
1143 static int find_chip(unsigned chip_id)
1145 unsigned i;
1146 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1148 if(chip_id == ati_card_ids[i].id) return i;
1150 return -1;
1153 static pciinfo_t pci_info;
1154 static int probed=0;
1156 static vidix_capability_t def_cap =
1158 #ifdef RAGE128
1159 "BES driver for Rage128 cards",
1160 #else
1161 "BES driver for Radeon cards",
1162 #endif
1163 "Nick Kurshev",
1164 TYPE_OUTPUT | TYPE_FX,
1165 { 0, 0, 0, 0 },
1166 2048,
1167 2048,
1171 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1172 VENDOR_ATI,
1174 { 0, 0, 0, 0}
1177 #if !defined(RAGE128) && defined(HAVE_X11)
1178 static void probe_fireGL_driver(void) {
1179 Display *dp = XOpenDisplay ((void*)0);
1180 int n = 0;
1181 char **extlist;
1182 if (dp==NULL) {
1183 return;
1185 extlist = XListExtensions (dp, &n);
1186 XCloseDisplay (dp);
1187 if (extlist) {
1188 int i;
1189 int ext_fgl = 0, ext_fglrx = 0;
1190 for (i = 0; i < n; i++) {
1191 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1192 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1194 if (ext_fgl) {
1195 printf(RADEON_MSG" ATI FireGl driver detected");
1196 firegl_shift = 0x500000;
1197 if (!ext_fglrx) {
1198 printf(", but DRI seems not to be activated\n");
1199 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1201 printf("\n");
1205 #endif
1207 static int radeon_probe(int verbose, int force)
1209 pciinfo_t lst[MAX_PCI_DEVICES];
1210 unsigned i,num_pci;
1211 int err;
1212 __verbose = verbose;
1213 err = pci_scan(lst,&num_pci);
1214 if(err)
1216 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1217 return err;
1219 else
1221 err = ENXIO;
1222 for(i=0;i<num_pci;i++)
1224 if(lst[i].vendor == VENDOR_ATI)
1226 int idx;
1227 const char *dname;
1228 idx = find_chip(lst[i].device);
1229 if(idx == -1 && force == PROBE_NORMAL) continue;
1230 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1231 dname = dname ? dname : "Unknown chip";
1232 printf(RADEON_MSG" Found chip: %s\n",dname);
1233 #if 0
1234 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1236 printf("[radeon] Device is disabled, ignoring\n");
1237 continue;
1239 #endif
1240 memset(&besr,0,sizeof(bes_registers_t));
1241 if(force > PROBE_NORMAL)
1243 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1244 if(idx == -1)
1245 #ifdef RAGE128
1246 printf(RADEON_MSG" Assuming it as Rage128\n");
1247 #else
1248 printf(RADEON_MSG" Assuming it as Radeon1\n");
1249 #endif
1250 besr.chip_flags=R_100|R_OVL_SHIFT;
1252 #if !defined(RAGE128) && defined(HAVE_X11)
1253 probe_fireGL_driver();
1254 #endif
1255 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1256 def_cap.device_id = lst[i].device;
1257 err = 0;
1258 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1259 probed=1;
1260 break;
1264 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1265 return err;
1268 typedef struct saved_regs_s
1270 uint32_t ov0_vid_key_clr;
1271 uint32_t ov0_vid_key_msk;
1272 uint32_t ov0_graphics_key_clr;
1273 uint32_t ov0_graphics_key_msk;
1274 uint32_t ov0_key_cntl;
1275 uint32_t disp_merge_cntl;
1276 }saved_regs_t;
1277 static saved_regs_t savreg;
1279 static void save_regs( void )
1281 radeon_fifo_wait(6);
1282 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1283 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1284 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1285 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1286 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1287 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1290 static void restore_regs( void )
1292 radeon_fifo_wait(6);
1293 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1294 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1295 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1296 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1297 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1298 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1301 static int radeon_init(void)
1303 int err;
1305 if(__verbose>0) printf("[radeon_vid] version %d\n", VIDIX_VERSION);
1307 if(!probed)
1309 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1310 return EINTR;
1312 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1313 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1314 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1315 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1316 #ifdef RADEON
1317 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1318 if (radeon_ram_size == 0 &&
1319 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1320 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1322 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1323 radeon_ram_size = 8192*1024;
1325 else if (radeon_ram_size == 0 &&
1326 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1328 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1329 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1330 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1332 #else
1333 /* Rage Mobility (rage128) also has memsize bug */
1334 if (radeon_ram_size == 0 &&
1335 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1336 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1338 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1339 radeon_ram_size = 8192*1024;
1341 #endif
1342 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1343 radeon_vid_make_default();
1344 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1345 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1346 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1347 #ifndef RAGE128
1349 memset(&rinfo,0,sizeof(rinfo_t));
1350 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1352 radeon_get_moninfo(&rinfo);
1353 if(rinfo.hasCRTC2) {
1354 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1355 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1357 else
1358 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1360 #endif
1361 save_regs();
1362 return 0;
1365 static void radeon_destroy(void)
1367 restore_regs();
1368 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1369 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1372 static int radeon_get_caps(vidix_capability_t *to)
1374 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1375 return 0;
1379 Full list of fourcc which are supported by Win2K radeon driver:
1380 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1381 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1383 typedef struct fourcc_desc_s
1385 uint32_t fourcc;
1386 unsigned max_srcw;
1387 }fourcc_desc_t;
1389 static fourcc_desc_t supported_fourcc[] =
1391 { IMGFMT_Y800, 1567 },
1392 { IMGFMT_YVU9, 1567 },
1393 { IMGFMT_IF09, 1567 },
1394 { IMGFMT_YV12, 1567 },
1395 { IMGFMT_I420, 1567 },
1396 { IMGFMT_IYUV, 1567 },
1397 { IMGFMT_UYVY, 1551 },
1398 { IMGFMT_YUY2, 1551 },
1399 { IMGFMT_YVYU, 1551 },
1400 { IMGFMT_RGB15, 1551 },
1401 { IMGFMT_BGR15, 1551 },
1402 { IMGFMT_RGB16, 1551 },
1403 { IMGFMT_BGR16, 1551 },
1404 { IMGFMT_RGB32, 775 },
1405 { IMGFMT_BGR32, 775 }
1408 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1410 unsigned i;
1411 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1413 if(fourcc==supported_fourcc[i].fourcc)
1414 return 1;
1416 return 0;
1419 static int radeon_query_fourcc(vidix_fourcc_t *to)
1421 if(is_supported_fourcc(to->fourcc))
1423 to->depth = VID_DEPTH_ALL;
1424 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1425 VID_CAP_BLEND;
1426 return 0;
1428 else to->depth = to->flags = 0;
1429 return ENOSYS;
1432 static double H_scale_ratio;
1433 static void radeon_vid_dump_regs( void )
1435 size_t i;
1436 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1437 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1438 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1439 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1440 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1441 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1442 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1443 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1444 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1445 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1446 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1449 static void radeon_vid_stop_video( void )
1451 radeon_engine_idle();
1452 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1453 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1454 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1455 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1456 #ifdef RAGE128
1457 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1458 #else
1459 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1460 #endif
1461 OUTREG(OV0_TEST, 0);
1464 static void radeon_vid_display_video( void )
1466 int bes_flags,force_second;
1467 radeon_fifo_wait(2);
1468 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1469 radeon_engine_idle();
1470 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1471 radeon_fifo_wait(15);
1473 force_second=0;
1475 /* Shutdown capturing */
1476 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1477 OUTREG(CAP0_TRIG_CNTL, 0);
1479 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1480 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1482 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1484 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1485 #ifdef RAGE128
1486 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1487 (besr.saturation << 8) |
1488 (besr.saturation << 16));
1489 #endif
1490 radeon_fifo_wait(2);
1491 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1492 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1493 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1495 OUTREG(OV0_H_INC, besr.h_inc);
1496 OUTREG(OV0_STEP_BY, besr.step_by);
1497 if(force_second)
1499 OUTREG(OV1_Y_X_START, besr.y_x_start);
1500 OUTREG(OV1_Y_X_END, besr.y_x_end);
1502 else
1504 OUTREG(OV0_Y_X_START, besr.y_x_start);
1505 OUTREG(OV0_Y_X_END, besr.y_x_end);
1507 OUTREG(OV0_V_INC, besr.v_inc);
1508 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1509 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1510 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1511 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1512 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1513 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1514 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1515 #ifdef RADEON
1516 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1517 #endif
1518 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1519 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1520 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1521 radeon_fifo_wait(9);
1522 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1523 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1524 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1525 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1526 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1527 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1528 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1530 bes_flags = SCALER_ENABLE |
1531 SCALER_SMART_SWITCH |
1532 SCALER_Y2R_TEMP |
1533 SCALER_PIX_EXPAND;
1534 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1535 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1536 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1537 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1538 #ifdef RAGE128
1539 bes_flags |= SCALER_BURST_PER_PLANE;
1540 #endif
1541 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1542 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1543 if(force_second) bes_flags |= SCALER_USE_OV1;
1544 else bes_flags &= ~SCALER_USE_OV1;
1545 OUTREG(OV0_SCALE_CNTL, bes_flags);
1546 radeon_fifo_wait(6);
1547 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1548 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1549 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1550 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1551 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1552 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1553 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1554 OUTREG(OV0_REG_LOAD_CNTL, 0);
1555 if(__verbose > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1556 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
1559 /* Goal of this function: hide RGB background and provide black screen around movie.
1560 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1561 Reverse effect to colorkey */
1562 #ifdef RAGE128
1563 static void radeon_vid_exclusive( void )
1565 /* this function works only with Rage128.
1566 Radeon should has something the same */
1567 unsigned screenw,screenh;
1568 screenw = radeon_get_xres();
1569 screenh = radeon_get_yres();
1570 radeon_fifo_wait(2);
1571 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1572 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1575 static void radeon_vid_non_exclusive( void )
1577 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1579 #endif
1581 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1583 unsigned pitch,spy,spv,spu;
1584 spy = spv = spu = 0;
1585 switch(spitch->y)
1587 case 16:
1588 case 32:
1589 case 64:
1590 case 128:
1591 case 256: spy = spitch->y; break;
1592 default: break;
1594 switch(spitch->u)
1596 case 16:
1597 case 32:
1598 case 64:
1599 case 128:
1600 case 256: spu = spitch->u; break;
1601 default: break;
1603 switch(spitch->v)
1605 case 16:
1606 case 32:
1607 case 64:
1608 case 128:
1609 case 256: spv = spitch->v; break;
1610 default: break;
1612 switch(fourcc)
1614 /* 4:2:0 */
1615 case IMGFMT_IYUV:
1616 case IMGFMT_YV12:
1617 case IMGFMT_I420:
1618 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1619 else pitch = 32;
1620 break;
1621 case IMGFMT_IF09:
1622 case IMGFMT_YVU9:
1623 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1624 else pitch = 64;
1625 break;
1626 default:
1627 if(spy >= 16) pitch = spy;
1628 else pitch = 16;
1629 break;
1631 return pitch;
1634 static void Calc_H_INC_STEP_BY (
1635 int fieldvalue_OV0_SURFACE_FORMAT,
1636 double H_scale_ratio,
1637 int DisallowFourTapVertFiltering,
1638 int DisallowFourTapUVVertFiltering,
1639 uint32_t *val_OV0_P1_H_INC,
1640 uint32_t *val_OV0_P1_H_STEP_BY,
1641 uint32_t *val_OV0_P23_H_INC,
1642 uint32_t *val_OV0_P23_H_STEP_BY,
1643 int *P1GroupSize,
1644 int *P1StepSize,
1645 int *P23StepSize )
1648 double ClocksNeededFor16Pixels;
1650 switch (fieldvalue_OV0_SURFACE_FORMAT)
1652 case 3:
1653 case 4: /*16BPP (ARGB1555 and RGB565) */
1654 /* All colour components are fetched in pairs */
1655 *P1GroupSize = 2;
1656 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1657 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1658 if (H_scale_ratio>=.5)
1660 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1661 /* until we reach .5. P1 and P23 are the same. */
1662 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1663 *val_OV0_P1_H_STEP_BY = 1;
1664 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1665 *val_OV0_P23_H_STEP_BY = 1;
1666 *P1StepSize = 1;
1667 *P23StepSize = 1;
1669 else if (H_scale_ratio>=.25)
1671 /* Step by two */
1672 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1673 *val_OV0_P1_H_STEP_BY = 2;
1674 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1675 *val_OV0_P23_H_STEP_BY = 2;
1676 *P1StepSize = 2;
1677 *P23StepSize = 2;
1679 else if (H_scale_ratio>=.125)
1681 /* Step by four */
1682 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1683 *val_OV0_P1_H_STEP_BY = 3;
1684 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1685 *val_OV0_P23_H_STEP_BY = 3;
1686 *P1StepSize = 4;
1687 *P23StepSize = 4;
1689 else if (H_scale_ratio>=.0625)
1691 /* Step by eight */
1692 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1693 *val_OV0_P1_H_STEP_BY = 4;
1694 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1695 *val_OV0_P23_H_STEP_BY = 4;
1696 *P1StepSize = 8;
1697 *P23StepSize = 8;
1699 else if (H_scale_ratio>=0.03125)
1701 /* Step by sixteen */
1702 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1703 *val_OV0_P1_H_STEP_BY = 5;
1704 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1705 *val_OV0_P23_H_STEP_BY = 5;
1706 *P1StepSize = 16;
1707 *P23StepSize = 16;
1709 else
1711 H_scale_ratio=0.03125;
1712 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1713 *val_OV0_P1_H_STEP_BY = 5;
1714 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1715 *val_OV0_P23_H_STEP_BY = 5;
1716 *P1StepSize = 16;
1717 *P23StepSize = 16;
1719 break;
1720 case 6: /*32BPP RGB */
1721 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1723 /* All colour components are fetched in pairs */
1724 *P1GroupSize = 2;
1725 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1726 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1727 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1728 *val_OV0_P1_H_STEP_BY = 0;
1729 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1730 *val_OV0_P23_H_STEP_BY = 0;
1731 *P1StepSize = 1;
1732 *P23StepSize = 1;
1734 else if (H_scale_ratio>=0.75)
1736 /* Four G colour components are fetched at once */
1737 *P1GroupSize = 4;
1738 /* R and B colour components are fetched in pairs */
1739 /* With two tap filtering, we can generate four colour components every clock. */
1740 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1741 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1742 *val_OV0_P1_H_STEP_BY = 1;
1743 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1744 *val_OV0_P23_H_STEP_BY = 1;
1745 *P1StepSize = 1;
1746 *P23StepSize = 1;
1748 else if (H_scale_ratio>=0.375)
1750 /* Step by two. */
1751 /* Four G colour components are fetched at once */
1752 *P1GroupSize = 4;
1753 /* R and B colour components are fetched in pairs */
1754 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1755 *val_OV0_P1_H_STEP_BY = 2;
1756 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1757 *val_OV0_P23_H_STEP_BY = 2;
1758 *P1StepSize = 2;
1759 *P23StepSize = 2;
1761 else if (H_scale_ratio>=0.25)
1763 /* Step by two. */
1764 /* Four G colour components are fetched at once */
1765 *P1GroupSize = 4;
1766 /* R and B colour components are fetched in pairs */
1767 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1768 *val_OV0_P1_H_STEP_BY = 2;
1769 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1770 *val_OV0_P23_H_STEP_BY = 3;
1771 *P1StepSize = 2;
1772 *P23StepSize = 4;
1774 else if (H_scale_ratio>=0.1875)
1776 /* Step by four */
1777 /* Four G colour components are fetched at once */
1778 *P1GroupSize = 4;
1779 /* R and B colour components are fetched in pairs */
1780 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1781 *val_OV0_P1_H_STEP_BY = 3;
1782 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1783 *val_OV0_P23_H_STEP_BY = 3;
1784 *P1StepSize = 4;
1785 *P23StepSize = 4;
1787 else if (H_scale_ratio>=0.125)
1789 /* Step by four */
1790 /* Four G colour components are fetched at once */
1791 *P1GroupSize = 4;
1792 /* R and B colour components are fetched in pairs */
1793 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1794 *val_OV0_P1_H_STEP_BY = 3;
1795 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1796 *val_OV0_P23_H_STEP_BY = 4;
1797 *P1StepSize = 4;
1798 *P23StepSize = 8;
1800 else if (H_scale_ratio>=0.09375)
1802 /* Step by eight */
1803 /* Four G colour components are fetched at once */
1804 *P1GroupSize = 4;
1805 /* R and B colour components are fetched in pairs */
1806 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1807 *val_OV0_P1_H_STEP_BY = 4;
1808 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1809 *val_OV0_P23_H_STEP_BY = 4;
1810 *P1StepSize = 8;
1811 *P23StepSize = 8;
1813 else if (H_scale_ratio>=0.0625)
1815 /* Step by eight */
1816 /* Four G colour components are fetched at once */
1817 *P1GroupSize = 4;
1818 /* R and B colour components are fetched in pairs */
1819 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1820 *val_OV0_P1_H_STEP_BY = 5;
1821 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1822 *val_OV0_P23_H_STEP_BY = 5;
1823 *P1StepSize = 16;
1824 *P23StepSize = 16;
1826 else
1828 H_scale_ratio=0.0625;
1829 *P1GroupSize = 4;
1830 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1831 *val_OV0_P1_H_STEP_BY = 5;
1832 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1833 *val_OV0_P23_H_STEP_BY = 5;
1834 *P1StepSize = 16;
1835 *P23StepSize = 16;
1837 break;
1838 case 9:
1839 /*ToDo_Active: In mode 9 there is a possibility that HScale ratio may be set to an illegal value, so we have extra conditions in the if statement. For consistancy, these conditions be added to the other modes as well. */
1840 /* four tap on both (unless Y is too wide) */
1841 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1842 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1843 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1844 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1845 { /*0.75 */
1846 /* Colour components are fetched in pairs */
1847 *P1GroupSize = 2;
1848 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1849 *val_OV0_P1_H_STEP_BY = 0;
1850 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1851 *val_OV0_P23_H_STEP_BY = 0;
1852 *P1StepSize = 1;
1853 *P23StepSize = 1;
1855 /* two tap on Y (because it is too big for four tap), four tap on UV */
1856 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1857 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1858 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1859 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1860 { /*0.75 */
1861 *P1GroupSize = 4;
1862 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1863 *val_OV0_P1_H_STEP_BY = 1;
1864 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1865 *val_OV0_P23_H_STEP_BY = 0;
1866 *P1StepSize = 1;
1867 *P23StepSize = 1;
1869 /* We scale the Y with the four tap filters, but UV's are generated
1870 with dual two tap configuration. */
1871 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1872 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1873 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1874 !DisallowFourTapVertFiltering)
1875 { /*0.625 */
1876 *P1GroupSize = 2;
1877 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1878 *val_OV0_P1_H_STEP_BY = 0;
1879 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1880 *val_OV0_P23_H_STEP_BY = 1;
1881 *P1StepSize = 1;
1882 *P23StepSize = 1;
1884 /* We scale the Y, U, and V with the two tap filters */
1885 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1886 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1887 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1888 { /*0.375 */
1889 *P1GroupSize = 4;
1890 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1891 *val_OV0_P1_H_STEP_BY = 1;
1892 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1893 *val_OV0_P23_H_STEP_BY = 1;
1894 *P1StepSize = 1;
1895 *P23StepSize = 1;
1897 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1898 thus we won't drop Y's yet. */
1899 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1900 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1901 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1902 { /*>=0.3125 and >.333333~ */
1903 *P1GroupSize = 4;
1904 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1905 *val_OV0_P1_H_STEP_BY = 1;
1906 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1907 *val_OV0_P23_H_STEP_BY = 2;
1908 *P1StepSize = 1;
1909 *P23StepSize = 2;
1911 /* We step the Y, U, and V by two. */
1912 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1913 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1914 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1916 *P1GroupSize = 4;
1917 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1918 *val_OV0_P1_H_STEP_BY = 2;
1919 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1920 *val_OV0_P23_H_STEP_BY = 2;
1921 *P1StepSize = 2;
1922 *P23StepSize = 2;
1924 /* We step the Y by two and the U and V by four. */
1925 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1926 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1927 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1929 *P1GroupSize = 4;
1930 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1931 *val_OV0_P1_H_STEP_BY = 2;
1932 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1933 *val_OV0_P23_H_STEP_BY = 3;
1934 *P1StepSize = 2;
1935 *P23StepSize = 4;
1937 /* We step the Y, U, and V by four. */
1938 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
1939 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
1940 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1942 *P1GroupSize = 4;
1943 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1944 *val_OV0_P1_H_STEP_BY = 3;
1945 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1946 *val_OV0_P23_H_STEP_BY = 3;
1947 *P1StepSize = 4;
1948 *P23StepSize = 4;
1950 /* We would like to step the Y by four and the U and V by eight, but we can't mix step by 3 and step by 4 for packed modes */
1952 /* We step the Y, U, and V by eight. */
1953 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
1954 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1955 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
1957 *P1GroupSize = 4;
1958 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1959 *val_OV0_P1_H_STEP_BY = 4;
1960 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
1961 *val_OV0_P23_H_STEP_BY = 4;
1962 *P1StepSize = 8;
1963 *P23StepSize = 8;
1965 /* We step the Y by eight and the U and V by sixteen. */
1966 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
1967 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1968 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1970 *P1GroupSize = 4;
1971 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1972 *val_OV0_P1_H_STEP_BY = 4;
1973 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1974 *val_OV0_P23_H_STEP_BY = 5;
1975 *P1StepSize = 8;
1976 *P23StepSize = 16;
1978 /* We step the Y, U, and V by sixteen. */
1979 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
1980 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
1981 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1983 *P1GroupSize = 4;
1984 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1985 *val_OV0_P1_H_STEP_BY = 5;
1986 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1987 *val_OV0_P23_H_STEP_BY = 5;
1988 *P1StepSize = 16;
1989 *P23StepSize = 16;
1991 else
1993 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
1994 *P1GroupSize = 4;
1995 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1996 *val_OV0_P1_H_STEP_BY = 5;
1997 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1998 *val_OV0_P23_H_STEP_BY = 5;
1999 *P1StepSize = 16;
2000 *P23StepSize = 16;
2002 break;
2003 case 10:
2004 case 11:
2005 case 12:
2006 case 13:
2007 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2008 /* We scale the Y, U, and V with the four tap filters */
2009 /* four tap on both (unless Y is too wide) */
2010 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2011 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2012 { /*0.75 */
2013 *P1GroupSize = 2;
2014 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2015 *val_OV0_P1_H_STEP_BY = 0;
2016 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2017 *val_OV0_P23_H_STEP_BY = 0;
2018 *P1StepSize = 1;
2019 *P23StepSize = 1;
2021 /* two tap on Y (because it is too big for four tap), four tap on UV */
2022 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2023 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2024 { /*0.75 */
2025 *P1GroupSize = 4;
2026 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2027 *val_OV0_P1_H_STEP_BY = 1;
2028 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2029 *val_OV0_P23_H_STEP_BY = 0;
2030 *P1StepSize = 1;
2031 *P23StepSize = 1;
2033 /* We scale the Y with the four tap filters, but UV's are generated
2034 with dual two tap configuration. */
2035 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2036 !DisallowFourTapVertFiltering)
2037 { /*0.625 */
2038 *P1GroupSize = 2;
2039 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2040 *val_OV0_P1_H_STEP_BY = 0;
2041 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2042 *val_OV0_P23_H_STEP_BY = 1;
2043 *P1StepSize = 1;
2044 *P23StepSize = 1;
2046 /* We scale the Y, U, and V with the two tap filters */
2047 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2048 { /*0.375 */
2049 *P1GroupSize = 4;
2050 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2051 *val_OV0_P1_H_STEP_BY = 1;
2052 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2053 *val_OV0_P23_H_STEP_BY = 1;
2054 *P1StepSize = 1;
2055 *P23StepSize = 1;
2057 /* We scale step the U and V by two to allow more bandwidth for
2058 fetching Y's, thus we won't drop Y's yet. */
2059 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2060 { /*0.312 */
2061 *P1GroupSize = 4;
2062 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2063 *val_OV0_P1_H_STEP_BY = 1;
2064 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2065 *val_OV0_P23_H_STEP_BY = 2;
2066 *P1StepSize = 1;
2067 *P23StepSize = 2;
2069 /* We step the Y, U, and V by two. */
2070 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2072 *P1GroupSize = 4;
2073 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2074 *val_OV0_P1_H_STEP_BY = 2;
2075 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2076 *val_OV0_P23_H_STEP_BY = 2;
2077 *P1StepSize = 2;
2078 *P23StepSize = 2;
2080 /* We step the Y by two and the U and V by four. */
2081 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2083 *P1GroupSize = 4;
2084 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2085 *val_OV0_P1_H_STEP_BY = 2;
2086 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2087 *val_OV0_P23_H_STEP_BY = 3;
2088 *P1StepSize = 2;
2089 *P23StepSize = 4;
2091 /* We step the Y, U, and V by four. */
2092 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2094 *P1GroupSize = 4;
2095 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2096 *val_OV0_P1_H_STEP_BY = 3;
2097 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2098 *val_OV0_P23_H_STEP_BY = 3;
2099 *P1StepSize = 4;
2100 *P23StepSize = 4;
2102 /* We step the Y by four and the U and V by eight. */
2103 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2104 (fieldvalue_OV0_SURFACE_FORMAT==10))
2106 *P1GroupSize = 4;
2107 /* Can't mix step by 3 and step by 4 for packed modes */
2108 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2109 *val_OV0_P1_H_STEP_BY = 3;
2110 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2111 *val_OV0_P23_H_STEP_BY = 4;
2112 *P1StepSize = 4;
2113 *P23StepSize = 8;
2115 /* We step the Y, U, and V by eight. */
2116 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2118 *P1GroupSize = 4;
2119 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2120 *val_OV0_P1_H_STEP_BY = 4;
2121 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2122 *val_OV0_P23_H_STEP_BY = 4;
2123 *P1StepSize = 8;
2124 *P23StepSize = 8;
2126 /* We step the Y by eight and the U and V by sixteen. */
2127 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2129 *P1GroupSize = 4;
2130 /* Step by 5 not supported for packed modes */
2131 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2132 *val_OV0_P1_H_STEP_BY = 4;
2133 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2134 *val_OV0_P23_H_STEP_BY = 5;
2135 *P1StepSize = 8;
2136 *P23StepSize = 16;
2138 /* We step the Y, U, and V by sixteen. */
2139 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2140 (fieldvalue_OV0_SURFACE_FORMAT==10))
2142 *P1GroupSize = 4;
2143 /* Step by 5 not supported for packed modes */
2144 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2145 *val_OV0_P1_H_STEP_BY = 5;
2146 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2147 *val_OV0_P23_H_STEP_BY = 5;
2148 *P1StepSize = 16;
2149 *P23StepSize = 16;
2151 else
2153 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2155 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2156 *P1GroupSize = 4;
2157 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2158 *val_OV0_P1_H_STEP_BY = 5;
2159 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2160 *val_OV0_P23_H_STEP_BY = 5;
2161 *P1StepSize = 16;
2162 *P23StepSize = 16;
2164 else
2166 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2167 *P1GroupSize = 4;
2168 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2169 *val_OV0_P1_H_STEP_BY = 4;
2170 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2171 *val_OV0_P23_H_STEP_BY = 4;
2172 *P1StepSize = 8;
2173 *P23StepSize = 8;
2176 break;
2177 default: break;
2180 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2181 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2184 /* ********************************************************* */
2185 /* ** Setup Black Bordering */
2186 /* ********************************************************* */
2188 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2190 double tempBLANK_LINES_AT_TOP;
2191 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2192 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2193 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2195 if (floor(config->src.y)<0) {
2196 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2197 TopLine = 0;
2199 else {
2200 tempBLANK_LINES_AT_TOP = 0;
2201 TopLine = (int)floor(config->src.y);
2203 /* Round rSrcBottom up and subtract one */
2204 if (ceil(config->src.y+config->src.h) > config->src.h)
2206 BottomLine = config->src.h - 1;
2208 else
2210 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2213 if (BottomLine >= TopLine)
2215 SourceLinesUsed = BottomLine - TopLine + 1;
2217 else
2219 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2220 SourceLinesUsed = 1;
2224 int SourceHeightInPixels;
2225 SourceHeightInPixels = BottomLine - TopLine + 1;
2228 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2229 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2231 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2232 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2233 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2235 if (BottomUVLine >= TopUVLine)
2237 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2239 else
2241 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2242 SourceUVLinesUsed = 1;
2244 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2245 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2246 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2247 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2248 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2249 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2253 static void ComputeXStartEnd(
2254 int is_400,
2255 uint32_t LeftPixel,uint32_t LeftUVPixel,
2256 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2257 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2258 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2259 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2261 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2262 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2263 /* ToDo_Active: At the moment we are not using iOV0_VID_BUF?_START_PIX, but instead // are using iOV0_P?_X_START and iOV0_P?_X_END. We should use "start pix" and // "width" to derive the start and end. */
2265 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2266 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2268 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2269 switch (besr.surf_id)
2271 case 9:
2272 case 10:
2273 case 13:
2274 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2275 /* a multiple of a power of two when decimating */
2276 val_OV0_P2_X_START = (int)LeftUVPixel %
2277 (MemWordsInBytes/BytesPerUVPixel);
2278 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2279 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2280 break;
2281 case 11:
2282 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2283 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2284 break;
2285 case 3:
2286 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2287 /* This value is needed only to allow proper setting of */
2288 /* val_OV0_PRESHIFT_P23_TO */
2289 /* val_OV0_P2_X_END = 0; */
2290 break;
2291 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2292 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2293 break;
2294 default: /* insert debug statement here. */
2295 RADEON_ASSERT("unknown fourcc\n");
2296 break;
2298 val_OV0_P3_X_START = val_OV0_P2_X_START;
2299 val_OV0_P3_X_END = val_OV0_P2_X_END;
2301 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2302 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2303 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2304 if(is_400)
2306 besr.p2_x_start_end = 0;
2307 besr.p3_x_start_end = 0;
2309 *p1_x_start = val_OV0_P1_X_START;
2310 *p2_x_start = val_OV0_P2_X_START;
2313 static void ComputeAccumInit(
2314 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2315 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2316 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2317 uint32_t CRT_V_INC,
2318 uint32_t P1GroupSize, uint32_t P23GroupSize,
2319 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2320 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2322 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2323 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2324 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2325 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2326 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2327 /* the distance (in source pixel coordinates) to the center of the first */
2328 /* destination pixel. Need to add additional pixels depending on how many pixels */
2329 /* are fetched at a time and how many pixels in a set are masked. */
2330 /* P23 values are always fetched in groups of two or four. If the start */
2331 /* pixel does not fall on the boundary, then we need to shift preshift for */
2332 /* some additional pixels */
2335 double ExtraHalfPixel;
2336 double tempAdditionalShift;
2337 double tempP1HStartPoint;
2338 double tempP23HStartPoint;
2339 double tempP1Init;
2340 double tempP23Init;
2342 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2343 else ExtraHalfPixel = 0.0;
2344 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2345 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2346 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2348 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2349 /* need to shift an additional pixel */
2350 /* Note that if the pitch is a multiple of two, and if we store fields using */
2351 /* the traditional planer format where the V plane and the U plane share the */
2352 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2353 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2354 /* it is a requirement that the U and V start on the same polarity byte */
2355 /* (even or odd). */
2356 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2357 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2358 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2359 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2360 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2361 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2362 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2365 /* ************************************************************** */
2366 /* ** Calculate values for initializing the vertical accumulators */
2367 /* ************************************************************** */
2370 double ExtraHalfLine;
2371 double ExtraFullLine;
2372 double tempP1VStartPoint;
2373 double tempP23VStartPoint;
2375 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2376 else ExtraHalfLine = 0.0;
2378 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2379 else ExtraFullLine = 0.0;
2381 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2382 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2384 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2386 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2388 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2389 else ExtraFullLine = 0.0;
2391 switch (besr.surf_id)
2393 case 10:
2394 case 13:
2395 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2396 ((float)CRT_V_INC / (1<<0xe));
2397 break;
2398 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2399 ((float)CRT_V_INC / (1<<0xf));
2400 break;
2401 case 3:
2402 case 4:
2403 case 6:
2404 case 11:
2405 case 12: tempP23VStartPoint = 0;
2406 break;
2407 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2408 break;
2411 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2413 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2416 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2418 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2419 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2420 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2421 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2424 typedef struct RangeAndCoefSet {
2425 double Range;
2426 signed char CoefSet[5][4];
2427 } RANGEANDCOEFSET;
2429 /* Filter Setup Routine */
2430 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2432 static RANGEANDCOEFSET ArrayOfSets[] = {
2433 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2434 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2435 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2436 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2437 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2438 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2439 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2440 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2441 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2442 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2443 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2444 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2445 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2446 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2447 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2448 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2449 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2450 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2451 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2452 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2453 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2454 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2455 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2456 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2457 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2458 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2459 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2460 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2461 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2462 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2463 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2464 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2465 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2466 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2467 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2468 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2469 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2470 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2471 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2472 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2473 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2474 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2475 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2476 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2477 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2478 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2479 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2480 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2481 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2482 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2483 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2484 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2485 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2486 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2487 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2488 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2489 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2490 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2491 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2492 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2493 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2494 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2495 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2496 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2497 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2498 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2499 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2500 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2501 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2502 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2503 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2504 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2505 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2506 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2507 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2508 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2511 double DSR;
2513 unsigned ArrayElement;
2515 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2516 if (DSR<.25) DSR=.25;
2517 if (DSR>1) DSR=1;
2519 ArrayElement = (int)((DSR-0.25) * 100);
2520 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2521 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2522 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2523 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2524 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2525 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2526 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2527 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2528 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2529 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2530 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2531 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2532 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2533 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2534 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2535 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2536 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2537 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2538 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2539 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2541 For more details, refer to Microsoft's draft of PC99.
2545 /* The minimal value of horizontal scale ratio when hard coded coefficients
2546 are suitable for the best quality. */
2547 /* FIXME: Should it be 0.9 for Rage128 ??? */
2548 static const double MinHScaleHard=0.75;
2550 static int radeon_vid_init_video( vidix_playback_t *config )
2552 double V_scale_ratio;
2553 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2554 uint32_t val_OV0_P1_H_INC=0,val_OV0_P1_H_STEP_BY=0,val_OV0_P23_H_INC=0,val_OV0_P23_H_STEP_BY=0;
2555 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2556 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2557 uint32_t CRT_V_INC;
2558 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2559 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2560 uint32_t PageSizeInBytes,OV0LB_Rows;
2561 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2562 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2563 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2564 int is_400,is_410,is_420,best_pitch,mpitch;
2565 int horz_repl_factor,interlace_factor;
2566 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2567 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2569 radeon_vid_stop_video();
2570 left = config->src.x << 16;
2571 top = config->src.y << 16;
2572 src_h = config->src.h;
2573 src_w = config->src.w;
2574 is_400 = is_410 = is_420 = 0;
2575 if(config->fourcc == IMGFMT_YV12 ||
2576 config->fourcc == IMGFMT_I420 ||
2577 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2578 if(config->fourcc == IMGFMT_YVU9 ||
2579 config->fourcc == IMGFMT_IF09) is_410 = 1;
2580 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2581 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2582 mpitch = best_pitch-1;
2583 BytesPerOctWord = 16;
2584 LogMemWordsInBytes = 4;
2585 MemWordsInBytes = 1<<LogMemWordsInBytes;
2586 LogTileWidthInMemWords = 2;
2587 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2588 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2589 LogTileHeight = 4;
2590 TileHeight = 1<<LogTileHeight;
2591 PageSizeInBytes = 64*MemWordsInBytes;
2592 OV0LB_Rows = 96;
2593 h_inc = 1;
2594 switch(config->fourcc)
2596 /* 4:0:0*/
2597 case IMGFMT_Y800:
2598 /* 4:1:0*/
2599 case IMGFMT_YVU9:
2600 case IMGFMT_IF09:
2601 /* 4:2:0 */
2602 case IMGFMT_IYUV:
2603 case IMGFMT_YV12:
2604 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2605 config->dest.pitch.y =
2606 config->dest.pitch.u =
2607 config->dest.pitch.v = best_pitch;
2608 break;
2609 /* RGB 4:4:4:4 */
2610 case IMGFMT_RGB32:
2611 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2612 config->dest.pitch.y =
2613 config->dest.pitch.u =
2614 config->dest.pitch.v = best_pitch;
2615 break;
2616 /* 4:2:2 */
2618 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2619 pitch = ((src_w*2) + mpitch) & ~mpitch;
2620 config->dest.pitch.y =
2621 config->dest.pitch.u =
2622 config->dest.pitch.v = best_pitch;
2623 break;
2625 besr.load_prg_start=0;
2626 besr.swap_uv=0;
2627 switch(config->fourcc)
2629 case IMGFMT_RGB15:
2630 besr.swap_uv=1;
2631 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2632 besr.load_prg_start = 1;
2633 break;
2634 case IMGFMT_RGB16:
2635 besr.swap_uv=1;
2636 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2637 besr.load_prg_start = 1;
2638 break;
2639 case IMGFMT_RGB32:
2640 besr.swap_uv=1;
2641 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2642 besr.load_prg_start = 1;
2643 break;
2644 /* 4:1:0*/
2645 case IMGFMT_IF09:
2646 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2647 break;
2648 /* 4:0:0*/
2649 case IMGFMT_Y800:
2650 /* 4:2:0 */
2651 case IMGFMT_IYUV:
2652 case IMGFMT_I420:
2653 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2654 break;
2655 /* 4:2:2 */
2656 case IMGFMT_YVYU:
2657 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2658 break;
2659 case IMGFMT_YUY2:
2660 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2661 break;
2663 switch (besr.surf_id)
2665 case 3:
2666 case 4:
2667 case 11:
2668 case 12: BytesPerPixel = 2;
2669 break;
2670 case 6: BytesPerPixel = 4;
2671 break;
2672 case 9:
2673 case 10:
2674 case 13:
2675 case 14: BytesPerPixel = 1;
2676 break;
2677 default: BytesPerPixel = 0;/*insert a debug statement here. */
2678 break;
2680 switch (besr.surf_id)
2682 case 3:
2683 case 4: BytesPerUVPixel = 0;
2684 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2685 case 11:
2686 case 12: BytesPerUVPixel = 2;
2687 break;
2688 case 6: BytesPerUVPixel = 0;
2689 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2690 case 9:
2691 case 10: BytesPerUVPixel = 1;
2692 break;
2693 case 13:
2694 case 14: BytesPerUVPixel = 2;
2695 break;
2696 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2697 break;
2700 switch (besr.surf_id)
2702 case 3:
2703 case 4:
2704 case 6: HorzUVSubSample = 1;
2705 break;
2706 case 9: HorzUVSubSample = 4;
2707 break;
2708 case 10:
2709 case 11:
2710 case 12:
2711 case 13:
2712 case 14: HorzUVSubSample = 2;
2713 break;
2714 default: HorzUVSubSample = 0;/* insert debug statement here. */
2715 break;
2717 switch (besr.surf_id)
2719 case 3:
2720 case 4:
2721 case 6:
2722 case 11:
2723 case 12: VertUVSubSample = 1;
2724 break;
2725 case 9: VertUVSubSample = 4;
2726 break;
2727 case 10:
2728 case 13:
2729 case 14: VertUVSubSample = 2;
2730 break;
2731 default: VertUVSubSample = 0;/* insert debug statment here. */
2732 break;
2734 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2735 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2736 LeftPixel = config->src.x;
2737 RightPixel = config->src.w-1;
2738 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2739 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2740 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2741 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2742 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2743 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2744 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2745 SourceWidthInPixels = (int)(config->src.w + 1);
2746 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2748 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2749 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2750 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2751 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2752 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2753 MemWordsInBytes) + 1);
2755 switch (besr.surf_id)
2757 case 9:
2758 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2760 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2762 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2764 DisallowFourTapVertFiltering = 1;
2767 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2769 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2771 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2773 DisallowFourTapUVVertFiltering = 1;
2776 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2778 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2780 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2782 DisallowFourTapUVVertFiltering = 1;
2784 break;
2785 case 13:
2786 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2788 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2790 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2792 DisallowFourTapVertFiltering = 1;
2795 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2797 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2799 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2801 DisallowFourTapUVVertFiltering = 1;
2803 break;
2804 case 3:
2805 case 4:
2806 case 6:
2807 case 11:
2808 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2810 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2812 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2814 DisallowFourTapVertFiltering = 1;
2816 break;
2817 default: /* insert debug statement here. */
2818 break;
2820 dest_w = config->dest.w;
2821 dest_h = config->dest.h;
2822 if(radeon_is_dbl_scan()) dest_h *= 2;
2823 besr.dest_bpp = radeon_vid_get_dbpp();
2824 besr.fourcc = config->fourcc;
2825 if(radeon_is_interlace()) interlace_factor = 2;
2826 else interlace_factor = 1;
2827 /* TODO: must be checked in doublescan mode!!! */
2828 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2830 /* Force the overlay clock on for integrated chips */
2831 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2833 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2834 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2835 V_scale_ratio = (double)(dest_h+1)/src_h;
2836 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2838 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2839 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2841 else
2842 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2844 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2845 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2847 else
2849 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2850 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2852 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2853 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2854 CRT_V_INC = besr.v_inc/interlace_factor;
2855 besr.v_inc <<= 8;
2857 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2858 int P1GroupSize = 0;
2859 int P23GroupSize;
2860 int P1StepSize = 0;
2861 int P23StepSize = 0;
2863 Calc_H_INC_STEP_BY(
2864 besr.surf_id,
2865 H_scale_ratio,
2866 DisallowFourTapVertFiltering,
2867 DisallowFourTapUVVertFiltering,
2868 &val_OV0_P1_H_INC,
2869 &val_OV0_P1_H_STEP_BY,
2870 &val_OV0_P23_H_INC,
2871 &val_OV0_P23_H_STEP_BY,
2872 &P1GroupSize,
2873 &P1StepSize,
2874 &P23StepSize);
2876 if(H_scale_ratio > MinHScaleHard)
2878 h_inc = (src_w << 12) / dest_w;
2879 besr.step_by = 0x0101;
2880 switch (besr.surf_id)
2882 case 3:
2883 case 4:
2884 case 6:
2885 besr.h_inc = (h_inc)|(h_inc<<16);
2886 break;
2887 case 9:
2888 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2889 break;
2890 default:
2891 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2892 break;
2896 P23GroupSize = 2; /* Current vaue for all modes */
2898 besr.horz_pick_nearest=0;
2899 DoNotUseMostRecentlyFetchedLine=0;
2900 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2901 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2902 besr.vert_pick_nearest = 1;
2903 else
2904 besr.vert_pick_nearest = 0;
2906 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2907 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2908 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2910 if(H_scale_ratio > MinHScaleHard)
2912 unsigned tmp;
2913 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2914 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2915 ((tmp << 12) & 0xf0000000);
2917 tmp = (top & 0x0000ffff) + 0x00018000;
2918 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2919 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2920 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2921 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2922 ((tmp << 12) & 0x70000000);
2924 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2925 besr.p23_v_accum_init = (is_420||is_410) ?
2926 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2927 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2929 else
2930 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2931 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2932 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2933 CRT_V_INC,P1GroupSize,P23GroupSize,
2934 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2935 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
2938 /* keep everything in 16.16 */
2939 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
2940 config->offsets[0] = 0;
2941 for(i=1;i<besr.vid_nbufs;i++)
2942 config->offsets[i] = config->offsets[i-1]+config->frame_size;
2943 if(is_420 || is_410 || is_400)
2945 uint32_t d1line,d2line,d3line;
2946 d1line = top*pitch;
2947 if(is_420)
2949 d2line = src_h*pitch+(d1line>>2);
2950 d3line = d2line+((src_h*pitch)>>2);
2952 else
2953 if(is_410)
2955 d2line = src_h*pitch+(d1line>>4);
2956 d3line = d2line+((src_h*pitch)>>4);
2958 else
2960 d2line = 0;
2961 d3line = 0;
2963 d1line += (left >> 16) & ~15;
2964 if(is_420)
2966 d2line += (left >> 17) & ~15;
2967 d3line += (left >> 17) & ~15;
2969 else /* is_410 */
2971 d2line += (left >> 18) & ~15;
2972 d3line += (left >> 18) & ~15;
2974 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
2975 if(is_400)
2977 config->offset.v = 0;
2978 config->offset.u = 0;
2980 else
2982 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
2983 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
2985 for(i=0;i<besr.vid_nbufs;i++)
2987 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
2988 if(is_400)
2990 besr.vid_buf_base_adrs_v[i]=0;
2991 besr.vid_buf_base_adrs_u[i]=0;
2993 else
2995 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
2997 besr.vid_buf_base_adrs_u[i]=((radeon_overlay_off+config->offsets[i]+config->offset.v)&VIF_BUF1_BASE_ADRS_MASK)|VIF_BUF1_PITCH_SEL;
2998 besr.vid_buf_base_adrs_v[i]=((radeon_overlay_off+config->offsets[i]+config->offset.u)&VIF_BUF2_BASE_ADRS_MASK)|VIF_BUF2_PITCH_SEL;
3000 else
3002 besr.vid_buf_base_adrs_v[i]=((radeon_overlay_off+config->offsets[i]+config->offset.v)&VIF_BUF1_BASE_ADRS_MASK)|VIF_BUF1_PITCH_SEL;
3003 besr.vid_buf_base_adrs_u[i]=((radeon_overlay_off+config->offsets[i]+config->offset.u)&VIF_BUF2_BASE_ADRS_MASK)|VIF_BUF2_PITCH_SEL;
3007 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3008 if(is_400)
3010 config->offset.v = 0;
3011 config->offset.u = 0;
3013 else
3015 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3016 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3019 else
3021 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3022 for(i=0;i<besr.vid_nbufs;i++)
3024 besr.vid_buf_base_adrs_y[i] =
3025 besr.vid_buf_base_adrs_u[i] =
3026 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3029 leftUV = (left >> (is_410?18:17)) & 15;
3030 left = (left >> 16) & 15;
3031 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3032 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3033 ComputeBorders(config,VertUVSubSample);
3034 besr.vid_buf_pitch0_value = pitch;
3035 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3036 /* ********************************************************* */
3037 /* ** Calculate programmable coefficients as needed */
3038 /* ********************************************************* */
3040 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3041 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3042 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3043 else
3045 FilterSetup (val_OV0_P1_H_INC);
3046 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3047 /* would like to do. For now, we let the test application decide. */
3048 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3049 if(DisallowFourTapVertFiltering)
3050 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3051 if(DisallowFourTapUVVertFiltering)
3052 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3054 return 0;
3057 static void radeon_compute_framesize(vidix_playback_t *info)
3059 unsigned pitch,awidth,dbpp;
3060 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3061 dbpp = radeon_vid_get_dbpp();
3062 switch(info->fourcc)
3064 case IMGFMT_Y800:
3065 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3066 info->frame_size = awidth*info->src.h;
3067 break;
3068 case IMGFMT_YVU9:
3069 case IMGFMT_IF09:
3070 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3071 info->frame_size = awidth*(info->src.h+info->src.h/8);
3072 break;
3073 case IMGFMT_I420:
3074 case IMGFMT_YV12:
3075 case IMGFMT_IYUV:
3076 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3077 info->frame_size = awidth*(info->src.h+info->src.h/2);
3078 break;
3079 case IMGFMT_RGB32:
3080 case IMGFMT_BGR32:
3081 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3082 info->frame_size = awidth*info->src.h;
3083 break;
3084 /* YUY2 YVYU, RGB15, RGB16 */
3085 default:
3086 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3087 info->frame_size = awidth*info->src.h;
3088 break;
3090 info->frame_size = (info->frame_size+4095)&~4095;
3093 static int radeon_config_playback(vidix_playback_t *info)
3095 unsigned rgb_size,nfr;
3096 uint32_t radeon_video_size;
3097 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3098 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3099 if(info->num_frames==1) besr.double_buff=0;
3100 else besr.double_buff=1;
3101 radeon_compute_framesize(info);
3103 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3104 nfr = info->num_frames;
3105 radeon_video_size = radeon_ram_size;
3106 for(;nfr>0; nfr--)
3108 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3109 #if !defined (RAGE128) && defined(HAVE_X11)
3110 radeon_overlay_off -= firegl_shift;
3111 #endif
3112 radeon_overlay_off &= 0xffff0000;
3113 if(radeon_overlay_off >= (int)rgb_size ) break;
3115 if(nfr <= 3)
3117 nfr = info->num_frames;
3118 for(;nfr>0; nfr--)
3120 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3121 #if !defined (RAGE128) && defined(HAVE_X11)
3122 radeon_overlay_off -= firegl_shift;
3123 #endif
3124 radeon_overlay_off &= 0xffff0000;
3125 if(radeon_overlay_off > 0) break;
3128 if(nfr <= 0) return EINVAL;
3129 info->num_frames = nfr;
3130 besr.vid_nbufs = info->num_frames;
3131 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3132 radeon_vid_init_video(info);
3133 return 0;
3136 static int radeon_playback_on(void)
3138 #ifdef RAGE128
3139 unsigned dw,dh;
3140 #endif
3141 radeon_vid_display_video();
3142 #ifdef RAGE128
3143 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3144 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3145 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3146 else radeon_vid_non_exclusive();
3147 #endif
3148 return 0;
3151 static int radeon_playback_off(void)
3153 radeon_vid_stop_video();
3154 return 0;
3157 static int radeon_frame_select(unsigned frame)
3159 uint32_t off[6];
3160 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3162 buf3-5 always should point onto second buffer for better
3163 deinterlacing and TV-in
3165 if(!besr.double_buff) return 0;
3166 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3167 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3168 off[0] = besr.vid_buf_base_adrs_y[frame];
3169 off[1] = besr.vid_buf_base_adrs_v[frame];
3170 off[2] = besr.vid_buf_base_adrs_u[frame];
3171 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3172 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3173 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3174 radeon_fifo_wait(8);
3175 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3176 radeon_engine_idle();
3177 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3178 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3179 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3180 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3181 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3182 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3183 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3184 OUTREG(OV0_REG_LOAD_CNTL, 0);
3185 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3186 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
3187 return 0;
3190 static vidix_video_eq_t equal =
3192 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3193 #ifndef RAGE128
3194 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3195 #endif
3197 0, 0, 0, 0, 0, 0, 0, 0 };
3199 static int radeon_get_eq(vidix_video_eq_t * eq)
3201 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3202 return 0;
3205 #ifndef RAGE128
3206 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3207 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3208 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3209 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3210 #define RTFHue(a) (((a)*3.1416)/1000.0)
3211 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3212 #endif
3214 static int radeon_set_eq(const vidix_video_eq_t * eq)
3216 #ifdef RAGE128
3217 int br,sat;
3218 #else
3219 int itu_space;
3220 #endif
3221 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3222 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3223 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3224 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3225 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3227 equal.red_intensity = eq->red_intensity;
3228 equal.green_intensity = eq->green_intensity;
3229 equal.blue_intensity = eq->blue_intensity;
3231 equal.flags = eq->flags;
3232 #ifdef RAGE128
3233 br = equal.brightness * 64 / 1000;
3234 if(br < -64) br = -64; if(br > 63) br = 63;
3235 sat = (equal.saturation*31 + 31000) / 2000;
3236 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3237 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3238 #else
3239 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3240 RTFCheckParam(equal.brightness);
3241 RTFCheckParam(equal.saturation);
3242 RTFCheckParam(equal.contrast);
3243 RTFCheckParam(equal.hue);
3244 RTFCheckParam(equal.red_intensity);
3245 RTFCheckParam(equal.green_intensity);
3246 RTFCheckParam(equal.blue_intensity);
3247 radeon_set_transform(RTFBrightness(equal.brightness),
3248 RTFContrast(equal.contrast),
3249 RTFSaturation(equal.saturation),
3250 RTFHue(equal.hue),
3251 RTFIntensity(equal.red_intensity),
3252 RTFIntensity(equal.green_intensity),
3253 RTFIntensity(equal.blue_intensity),
3254 itu_space);
3255 #endif
3256 return 0;
3259 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3261 unsigned sflg;
3262 switch(info->flags)
3264 default:
3265 case CFG_NON_INTERLACED:
3266 besr.deinterlace_on = 0;
3267 break;
3268 case CFG_EVEN_ODD_INTERLACING:
3269 case CFG_INTERLACED:
3270 besr.deinterlace_on = 1;
3271 besr.deinterlace_pattern = 0x900AAAAA;
3272 break;
3273 case CFG_ODD_EVEN_INTERLACING:
3274 besr.deinterlace_on = 1;
3275 besr.deinterlace_pattern = 0x00055555;
3276 break;
3277 case CFG_UNIQUE_INTERLACING:
3278 besr.deinterlace_on = 1;
3279 besr.deinterlace_pattern = info->deinterlace_pattern;
3280 break;
3282 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3283 radeon_engine_idle();
3284 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3285 radeon_fifo_wait(15);
3286 sflg = INREG(OV0_SCALE_CNTL);
3287 if(besr.deinterlace_on)
3289 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3290 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3292 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3293 OUTREG(OV0_REG_LOAD_CNTL, 0);
3294 return 0;
3297 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3299 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3300 else
3302 info->flags = CFG_UNIQUE_INTERLACING;
3303 info->deinterlace_pattern = besr.deinterlace_pattern;
3305 return 0;
3309 /* Graphic keys */
3310 static vidix_grkey_t radeon_grkey;
3312 static int set_gr_key( void )
3314 int result = 0;
3316 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3317 0x00ff0000; /* graphic alpha */
3318 if(radeon_grkey.ckey.op == CKEY_TRUE)
3320 int dbpp=radeon_vid_get_dbpp();
3321 besr.ckey_on=1;
3323 switch(dbpp)
3325 case 15:
3326 #ifndef RAGE128
3327 if((besr.chip_flags&R_100)!=R_100)
3328 besr.graphics_key_clr=
3329 ((radeon_grkey.ckey.blue &0xF8))
3330 | ((radeon_grkey.ckey.green&0xF8)<<8)
3331 | ((radeon_grkey.ckey.red &0xF8)<<16);
3332 else
3333 #endif
3334 besr.graphics_key_clr=
3335 ((radeon_grkey.ckey.blue &0xF8)>>3)
3336 | ((radeon_grkey.ckey.green&0xF8)<<2)
3337 | ((radeon_grkey.ckey.red &0xF8)<<7);
3338 break;
3339 case 16:
3340 #ifndef RAGE128
3341 /* This test may be too general/specific */
3342 if((besr.chip_flags&R_100)!=R_100)
3343 besr.graphics_key_clr=
3344 ((radeon_grkey.ckey.blue &0xF8))
3345 | ((radeon_grkey.ckey.green&0xFC)<<8)
3346 | ((radeon_grkey.ckey.red &0xF8)<<16);
3347 else
3348 #endif
3349 besr.graphics_key_clr=
3350 ((radeon_grkey.ckey.blue &0xF8)>>3)
3351 | ((radeon_grkey.ckey.green&0xFC)<<3)
3352 | ((radeon_grkey.ckey.red &0xF8)<<8);
3353 break;
3354 case 24:
3355 case 32:
3356 besr.graphics_key_clr=
3357 ((radeon_grkey.ckey.blue &0xFF))
3358 | ((radeon_grkey.ckey.green&0xFF)<<8)
3359 | ((radeon_grkey.ckey.red &0xFF)<<16);
3360 break;
3361 default:
3362 besr.ckey_on=0;
3363 besr.graphics_key_msk=0;
3364 besr.graphics_key_clr=0;
3366 #ifdef RAGE128
3367 besr.graphics_key_msk=(1<<dbpp)-1;
3368 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3369 #else
3370 besr.graphics_key_msk=besr.graphics_key_clr;
3371 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3372 #endif
3374 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3376 int dbpp=radeon_vid_get_dbpp();
3377 besr.ckey_on=1;
3379 switch(dbpp)
3381 case 32:
3382 besr.ckey_on=1;
3383 besr.graphics_key_msk=0;
3384 besr.graphics_key_clr=0;
3385 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3386 besr.merge_cntl |= 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3387 break;
3388 default:
3389 besr.ckey_on=0;
3390 besr.graphics_key_msk=0;
3391 besr.graphics_key_clr=0;
3392 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3393 result = 1;
3396 else
3398 besr.ckey_on=0;
3399 besr.graphics_key_msk=0;
3400 besr.graphics_key_clr=0;
3401 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3402 besr.merge_cntl |= 0x00000100; /* DISP_RGB_OFFSET_EN */
3404 radeon_fifo_wait(3);
3405 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3406 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3407 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3408 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3409 return result;
3412 static int radeon_get_gkey(vidix_grkey_t *grkey)
3414 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3415 return(0);
3418 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3420 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3421 return (set_gr_key());
3424 #ifdef RAGE128
3425 VDXDriver rage128_drv = {
3426 "rage128",
3427 #else
3428 VDXDriver radeon_drv = {
3429 "radeon",
3430 #endif
3431 NULL,
3433 .probe = radeon_probe,
3434 .get_caps = radeon_get_caps,
3435 .query_fourcc = radeon_query_fourcc,
3436 .init = radeon_init,
3437 .destroy = radeon_destroy,
3438 .config_playback = radeon_config_playback,
3439 .playback_on = radeon_playback_on,
3440 .playback_off = radeon_playback_off,
3441 .frame_sel = radeon_frame_select,
3442 .get_eq = radeon_get_eq,
3443 .set_eq = radeon_set_eq,
3444 .get_deint = radeon_playback_get_deint,
3445 .set_deint = radeon_playback_set_deint,
3446 .get_gkey = radeon_get_gkey,
3447 .set_gkey = radeon_set_gkey,