Do not set SYS_AMIGAOS4, it is unused.
[mplayer/greg.git] / vidix / radeon_vid.c
blobaeff422a7ee1c5821c8906b5de71206d0686eaeb
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;
1141 besr.merge_cntl |= 0x00000100; /* DISP_RGB_OFFSET_EN */
1144 static int find_chip(unsigned chip_id)
1146 unsigned i;
1147 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1149 if(chip_id == ati_card_ids[i].id) return i;
1151 return -1;
1154 static pciinfo_t pci_info;
1155 static int probed=0;
1157 static vidix_capability_t def_cap =
1159 #ifdef RAGE128
1160 "BES driver for Rage128 cards",
1161 #else
1162 "BES driver for Radeon cards",
1163 #endif
1164 "Nick Kurshev",
1165 TYPE_OUTPUT | TYPE_FX,
1166 { 0, 0, 0, 0 },
1167 2048,
1168 2048,
1172 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1173 VENDOR_ATI,
1175 { 0, 0, 0, 0}
1178 #if !defined(RAGE128) && defined(HAVE_X11)
1179 static void probe_fireGL_driver(void) {
1180 Display *dp = XOpenDisplay ((void*)0);
1181 int n = 0;
1182 char **extlist;
1183 if (dp==NULL) {
1184 return;
1186 extlist = XListExtensions (dp, &n);
1187 XCloseDisplay (dp);
1188 if (extlist) {
1189 int i;
1190 int ext_fgl = 0, ext_fglrx = 0;
1191 for (i = 0; i < n; i++) {
1192 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1193 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1195 if (ext_fgl) {
1196 printf(RADEON_MSG" ATI FireGl driver detected");
1197 firegl_shift = 0x500000;
1198 if (!ext_fglrx) {
1199 printf(", but DRI seems not to be activated\n");
1200 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1202 printf("\n");
1206 #endif
1208 static int radeon_probe(int verbose, int force)
1210 pciinfo_t lst[MAX_PCI_DEVICES];
1211 unsigned i,num_pci;
1212 int err;
1213 __verbose = verbose;
1214 err = pci_scan(lst,&num_pci);
1215 if(err)
1217 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1218 return err;
1220 else
1222 err = ENXIO;
1223 for(i=0;i<num_pci;i++)
1225 if(lst[i].vendor == VENDOR_ATI)
1227 int idx;
1228 const char *dname;
1229 idx = find_chip(lst[i].device);
1230 if(idx == -1 && force == PROBE_NORMAL) continue;
1231 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1232 dname = dname ? dname : "Unknown chip";
1233 printf(RADEON_MSG" Found chip: %s\n",dname);
1234 #if 0
1235 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1237 printf("[radeon] Device is disabled, ignoring\n");
1238 continue;
1240 #endif
1241 memset(&besr,0,sizeof(bes_registers_t));
1242 if(force > PROBE_NORMAL)
1244 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1245 if(idx == -1)
1246 #ifdef RAGE128
1247 printf(RADEON_MSG" Assuming it as Rage128\n");
1248 #else
1249 printf(RADEON_MSG" Assuming it as Radeon1\n");
1250 #endif
1251 besr.chip_flags=R_100|R_OVL_SHIFT;
1253 #if !defined(RAGE128) && defined(HAVE_X11)
1254 probe_fireGL_driver();
1255 #endif
1256 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1257 def_cap.device_id = lst[i].device;
1258 err = 0;
1259 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1260 probed=1;
1261 break;
1265 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1266 return err;
1269 typedef struct saved_regs_s
1271 uint32_t ov0_vid_key_clr;
1272 uint32_t ov0_vid_key_msk;
1273 uint32_t ov0_graphics_key_clr;
1274 uint32_t ov0_graphics_key_msk;
1275 uint32_t ov0_key_cntl;
1276 uint32_t disp_merge_cntl;
1277 }saved_regs_t;
1278 static saved_regs_t savreg;
1280 static void save_regs( void )
1282 radeon_fifo_wait(6);
1283 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1284 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1285 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1286 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1287 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1288 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1291 static void restore_regs( void )
1293 radeon_fifo_wait(6);
1294 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1295 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1296 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1297 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1298 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1299 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1302 static int radeon_init(void)
1304 int err;
1306 if(__verbose>0) printf("[radeon_vid] version %d\n", VIDIX_VERSION);
1308 if(!probed)
1310 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1311 return EINTR;
1313 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1314 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1315 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1316 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1317 #ifdef RADEON
1318 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1319 if (radeon_ram_size == 0 &&
1320 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1321 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1323 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1324 radeon_ram_size = 8192*1024;
1326 else if (radeon_ram_size == 0 &&
1327 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1329 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1330 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1331 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1333 #else
1334 /* Rage Mobility (rage128) also has memsize bug */
1335 if (radeon_ram_size == 0 &&
1336 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1337 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1339 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1340 radeon_ram_size = 8192*1024;
1342 #endif
1343 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1344 radeon_vid_make_default();
1345 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1346 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1347 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1348 #ifndef RAGE128
1350 memset(&rinfo,0,sizeof(rinfo_t));
1351 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1353 radeon_get_moninfo(&rinfo);
1354 if(rinfo.hasCRTC2) {
1355 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1356 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1358 else
1359 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1361 #endif
1362 save_regs();
1363 return 0;
1366 static void radeon_destroy(void)
1368 restore_regs();
1369 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1370 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1373 static int radeon_get_caps(vidix_capability_t *to)
1375 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1376 return 0;
1380 Full list of fourcc which are supported by Win2K radeon driver:
1381 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1382 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1384 typedef struct fourcc_desc_s
1386 uint32_t fourcc;
1387 unsigned max_srcw;
1388 }fourcc_desc_t;
1390 static fourcc_desc_t supported_fourcc[] =
1392 { IMGFMT_Y800, 1567 },
1393 { IMGFMT_YVU9, 1567 },
1394 { IMGFMT_IF09, 1567 },
1395 { IMGFMT_YV12, 1567 },
1396 { IMGFMT_I420, 1567 },
1397 { IMGFMT_IYUV, 1567 },
1398 { IMGFMT_UYVY, 1551 },
1399 { IMGFMT_YUY2, 1551 },
1400 { IMGFMT_YVYU, 1551 },
1401 { IMGFMT_RGB15, 1551 },
1402 { IMGFMT_BGR15, 1551 },
1403 { IMGFMT_RGB16, 1551 },
1404 { IMGFMT_BGR16, 1551 },
1405 { IMGFMT_RGB32, 775 },
1406 { IMGFMT_BGR32, 775 }
1409 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1411 unsigned i;
1412 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1414 if(fourcc==supported_fourcc[i].fourcc)
1415 return 1;
1417 return 0;
1420 static int radeon_query_fourcc(vidix_fourcc_t *to)
1422 if(is_supported_fourcc(to->fourcc))
1424 to->depth = VID_DEPTH_ALL;
1425 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1426 VID_CAP_BLEND;
1427 return 0;
1429 else to->depth = to->flags = 0;
1430 return ENOSYS;
1433 static double H_scale_ratio;
1434 static void radeon_vid_dump_regs( void )
1436 size_t i;
1437 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1438 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1439 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1440 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1441 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1442 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1443 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1444 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1445 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1446 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1447 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1450 static void radeon_vid_stop_video( void )
1452 radeon_engine_idle();
1453 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1454 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1455 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1456 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1457 #ifdef RAGE128
1458 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1459 #else
1460 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1461 #endif
1462 OUTREG(OV0_TEST, 0);
1465 static void radeon_vid_display_video( void )
1467 int bes_flags,force_second;
1468 radeon_fifo_wait(2);
1469 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1470 radeon_engine_idle();
1471 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1472 radeon_fifo_wait(15);
1474 force_second=0;
1476 /* Shutdown capturing */
1477 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1478 OUTREG(CAP0_TRIG_CNTL, 0);
1480 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1481 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1483 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1485 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1486 #ifdef RAGE128
1487 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1488 (besr.saturation << 8) |
1489 (besr.saturation << 16));
1490 #endif
1491 radeon_fifo_wait(2);
1492 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1493 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1494 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1496 OUTREG(OV0_H_INC, besr.h_inc);
1497 OUTREG(OV0_STEP_BY, besr.step_by);
1498 if(force_second)
1500 OUTREG(OV1_Y_X_START, besr.y_x_start);
1501 OUTREG(OV1_Y_X_END, besr.y_x_end);
1503 else
1505 OUTREG(OV0_Y_X_START, besr.y_x_start);
1506 OUTREG(OV0_Y_X_END, besr.y_x_end);
1508 OUTREG(OV0_V_INC, besr.v_inc);
1509 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1510 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1511 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1512 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1513 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1514 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1515 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1516 #ifdef RADEON
1517 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1518 #endif
1519 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1520 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1521 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1522 radeon_fifo_wait(9);
1523 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1524 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1525 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1526 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1527 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1528 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1529 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1531 bes_flags = SCALER_ENABLE |
1532 SCALER_SMART_SWITCH |
1533 SCALER_Y2R_TEMP |
1534 SCALER_PIX_EXPAND;
1535 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1536 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1537 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1538 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1539 #ifdef RAGE128
1540 bes_flags |= SCALER_BURST_PER_PLANE;
1541 #endif
1542 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1543 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1544 if(force_second) bes_flags |= SCALER_USE_OV1;
1545 else bes_flags &= ~SCALER_USE_OV1;
1546 OUTREG(OV0_SCALE_CNTL, bes_flags);
1547 radeon_fifo_wait(6);
1548 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1549 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1550 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1551 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1552 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1553 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1554 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1555 OUTREG(OV0_REG_LOAD_CNTL, 0);
1556 if(__verbose > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1557 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
1560 /* Goal of this function: hide RGB background and provide black screen around movie.
1561 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1562 Reverse effect to colorkey */
1563 #ifdef RAGE128
1564 static void radeon_vid_exclusive( void )
1566 /* this function works only with Rage128.
1567 Radeon should has something the same */
1568 unsigned screenw,screenh;
1569 screenw = radeon_get_xres();
1570 screenh = radeon_get_yres();
1571 radeon_fifo_wait(2);
1572 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1573 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1576 static void radeon_vid_non_exclusive( void )
1578 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1580 #endif
1582 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1584 unsigned pitch,spy,spv,spu;
1585 spy = spv = spu = 0;
1586 switch(spitch->y)
1588 case 16:
1589 case 32:
1590 case 64:
1591 case 128:
1592 case 256: spy = spitch->y; break;
1593 default: break;
1595 switch(spitch->u)
1597 case 16:
1598 case 32:
1599 case 64:
1600 case 128:
1601 case 256: spu = spitch->u; break;
1602 default: break;
1604 switch(spitch->v)
1606 case 16:
1607 case 32:
1608 case 64:
1609 case 128:
1610 case 256: spv = spitch->v; break;
1611 default: break;
1613 switch(fourcc)
1615 /* 4:2:0 */
1616 case IMGFMT_IYUV:
1617 case IMGFMT_YV12:
1618 case IMGFMT_I420:
1619 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1620 else pitch = 32;
1621 break;
1622 case IMGFMT_IF09:
1623 case IMGFMT_YVU9:
1624 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1625 else pitch = 64;
1626 break;
1627 default:
1628 if(spy >= 16) pitch = spy;
1629 else pitch = 16;
1630 break;
1632 return pitch;
1635 static void Calc_H_INC_STEP_BY (
1636 int fieldvalue_OV0_SURFACE_FORMAT,
1637 double H_scale_ratio,
1638 int DisallowFourTapVertFiltering,
1639 int DisallowFourTapUVVertFiltering,
1640 uint32_t *val_OV0_P1_H_INC,
1641 uint32_t *val_OV0_P1_H_STEP_BY,
1642 uint32_t *val_OV0_P23_H_INC,
1643 uint32_t *val_OV0_P23_H_STEP_BY,
1644 int *P1GroupSize,
1645 int *P1StepSize,
1646 int *P23StepSize )
1649 double ClocksNeededFor16Pixels;
1651 switch (fieldvalue_OV0_SURFACE_FORMAT)
1653 case 3:
1654 case 4: /*16BPP (ARGB1555 and RGB565) */
1655 /* All colour components are fetched in pairs */
1656 *P1GroupSize = 2;
1657 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1658 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1659 if (H_scale_ratio>=.5)
1661 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1662 /* until we reach .5. P1 and P23 are the same. */
1663 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1664 *val_OV0_P1_H_STEP_BY = 1;
1665 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1666 *val_OV0_P23_H_STEP_BY = 1;
1667 *P1StepSize = 1;
1668 *P23StepSize = 1;
1670 else if (H_scale_ratio>=.25)
1672 /* Step by two */
1673 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1674 *val_OV0_P1_H_STEP_BY = 2;
1675 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1676 *val_OV0_P23_H_STEP_BY = 2;
1677 *P1StepSize = 2;
1678 *P23StepSize = 2;
1680 else if (H_scale_ratio>=.125)
1682 /* Step by four */
1683 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1684 *val_OV0_P1_H_STEP_BY = 3;
1685 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1686 *val_OV0_P23_H_STEP_BY = 3;
1687 *P1StepSize = 4;
1688 *P23StepSize = 4;
1690 else if (H_scale_ratio>=.0625)
1692 /* Step by eight */
1693 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1694 *val_OV0_P1_H_STEP_BY = 4;
1695 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1696 *val_OV0_P23_H_STEP_BY = 4;
1697 *P1StepSize = 8;
1698 *P23StepSize = 8;
1700 else if (H_scale_ratio>=0.03125)
1702 /* Step by sixteen */
1703 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1704 *val_OV0_P1_H_STEP_BY = 5;
1705 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1706 *val_OV0_P23_H_STEP_BY = 5;
1707 *P1StepSize = 16;
1708 *P23StepSize = 16;
1710 else
1712 H_scale_ratio=0.03125;
1713 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1714 *val_OV0_P1_H_STEP_BY = 5;
1715 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1716 *val_OV0_P23_H_STEP_BY = 5;
1717 *P1StepSize = 16;
1718 *P23StepSize = 16;
1720 break;
1721 case 6: /*32BPP RGB */
1722 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1724 /* All colour components are fetched in pairs */
1725 *P1GroupSize = 2;
1726 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1727 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1728 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1729 *val_OV0_P1_H_STEP_BY = 0;
1730 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1731 *val_OV0_P23_H_STEP_BY = 0;
1732 *P1StepSize = 1;
1733 *P23StepSize = 1;
1735 else if (H_scale_ratio>=0.75)
1737 /* Four G colour components are fetched at once */
1738 *P1GroupSize = 4;
1739 /* R and B colour components are fetched in pairs */
1740 /* With two tap filtering, we can generate four colour components every clock. */
1741 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1742 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1743 *val_OV0_P1_H_STEP_BY = 1;
1744 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1745 *val_OV0_P23_H_STEP_BY = 1;
1746 *P1StepSize = 1;
1747 *P23StepSize = 1;
1749 else if (H_scale_ratio>=0.375)
1751 /* Step by two. */
1752 /* Four G colour components are fetched at once */
1753 *P1GroupSize = 4;
1754 /* R and B colour components are fetched in pairs */
1755 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1756 *val_OV0_P1_H_STEP_BY = 2;
1757 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1758 *val_OV0_P23_H_STEP_BY = 2;
1759 *P1StepSize = 2;
1760 *P23StepSize = 2;
1762 else if (H_scale_ratio>=0.25)
1764 /* Step by two. */
1765 /* Four G colour components are fetched at once */
1766 *P1GroupSize = 4;
1767 /* R and B colour components are fetched in pairs */
1768 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1769 *val_OV0_P1_H_STEP_BY = 2;
1770 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1771 *val_OV0_P23_H_STEP_BY = 3;
1772 *P1StepSize = 2;
1773 *P23StepSize = 4;
1775 else if (H_scale_ratio>=0.1875)
1777 /* Step by four */
1778 /* Four G colour components are fetched at once */
1779 *P1GroupSize = 4;
1780 /* R and B colour components are fetched in pairs */
1781 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1782 *val_OV0_P1_H_STEP_BY = 3;
1783 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1784 *val_OV0_P23_H_STEP_BY = 3;
1785 *P1StepSize = 4;
1786 *P23StepSize = 4;
1788 else if (H_scale_ratio>=0.125)
1790 /* Step by four */
1791 /* Four G colour components are fetched at once */
1792 *P1GroupSize = 4;
1793 /* R and B colour components are fetched in pairs */
1794 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1795 *val_OV0_P1_H_STEP_BY = 3;
1796 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1797 *val_OV0_P23_H_STEP_BY = 4;
1798 *P1StepSize = 4;
1799 *P23StepSize = 8;
1801 else if (H_scale_ratio>=0.09375)
1803 /* Step by eight */
1804 /* Four G colour components are fetched at once */
1805 *P1GroupSize = 4;
1806 /* R and B colour components are fetched in pairs */
1807 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1808 *val_OV0_P1_H_STEP_BY = 4;
1809 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1810 *val_OV0_P23_H_STEP_BY = 4;
1811 *P1StepSize = 8;
1812 *P23StepSize = 8;
1814 else if (H_scale_ratio>=0.0625)
1816 /* Step by eight */
1817 /* Four G colour components are fetched at once */
1818 *P1GroupSize = 4;
1819 /* R and B colour components are fetched in pairs */
1820 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1821 *val_OV0_P1_H_STEP_BY = 5;
1822 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1823 *val_OV0_P23_H_STEP_BY = 5;
1824 *P1StepSize = 16;
1825 *P23StepSize = 16;
1827 else
1829 H_scale_ratio=0.0625;
1830 *P1GroupSize = 4;
1831 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1832 *val_OV0_P1_H_STEP_BY = 5;
1833 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1834 *val_OV0_P23_H_STEP_BY = 5;
1835 *P1StepSize = 16;
1836 *P23StepSize = 16;
1838 break;
1839 case 9:
1840 /*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. */
1841 /* four tap on both (unless Y is too wide) */
1842 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1843 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1844 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1845 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1846 { /*0.75 */
1847 /* Colour components are fetched in pairs */
1848 *P1GroupSize = 2;
1849 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1850 *val_OV0_P1_H_STEP_BY = 0;
1851 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1852 *val_OV0_P23_H_STEP_BY = 0;
1853 *P1StepSize = 1;
1854 *P23StepSize = 1;
1856 /* two tap on Y (because it is too big for four tap), four tap on UV */
1857 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1858 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1859 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1860 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1861 { /*0.75 */
1862 *P1GroupSize = 4;
1863 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1864 *val_OV0_P1_H_STEP_BY = 1;
1865 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1866 *val_OV0_P23_H_STEP_BY = 0;
1867 *P1StepSize = 1;
1868 *P23StepSize = 1;
1870 /* We scale the Y with the four tap filters, but UV's are generated
1871 with dual two tap configuration. */
1872 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1873 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1874 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1875 !DisallowFourTapVertFiltering)
1876 { /*0.625 */
1877 *P1GroupSize = 2;
1878 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1879 *val_OV0_P1_H_STEP_BY = 0;
1880 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1881 *val_OV0_P23_H_STEP_BY = 1;
1882 *P1StepSize = 1;
1883 *P23StepSize = 1;
1885 /* We scale the Y, U, and V with the two tap filters */
1886 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1887 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1888 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1889 { /*0.375 */
1890 *P1GroupSize = 4;
1891 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1892 *val_OV0_P1_H_STEP_BY = 1;
1893 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1894 *val_OV0_P23_H_STEP_BY = 1;
1895 *P1StepSize = 1;
1896 *P23StepSize = 1;
1898 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1899 thus we won't drop Y's yet. */
1900 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1901 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1902 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1903 { /*>=0.3125 and >.333333~ */
1904 *P1GroupSize = 4;
1905 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1906 *val_OV0_P1_H_STEP_BY = 1;
1907 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1908 *val_OV0_P23_H_STEP_BY = 2;
1909 *P1StepSize = 1;
1910 *P23StepSize = 2;
1912 /* We step the Y, U, and V by two. */
1913 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1914 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1915 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1917 *P1GroupSize = 4;
1918 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1919 *val_OV0_P1_H_STEP_BY = 2;
1920 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1921 *val_OV0_P23_H_STEP_BY = 2;
1922 *P1StepSize = 2;
1923 *P23StepSize = 2;
1925 /* We step the Y by two and the U and V by four. */
1926 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1927 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1928 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1930 *P1GroupSize = 4;
1931 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1932 *val_OV0_P1_H_STEP_BY = 2;
1933 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1934 *val_OV0_P23_H_STEP_BY = 3;
1935 *P1StepSize = 2;
1936 *P23StepSize = 4;
1938 /* We step the Y, U, and V by four. */
1939 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
1940 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
1941 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1943 *P1GroupSize = 4;
1944 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1945 *val_OV0_P1_H_STEP_BY = 3;
1946 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1947 *val_OV0_P23_H_STEP_BY = 3;
1948 *P1StepSize = 4;
1949 *P23StepSize = 4;
1951 /* 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 */
1953 /* We step the Y, U, and V by eight. */
1954 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
1955 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1956 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
1958 *P1GroupSize = 4;
1959 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1960 *val_OV0_P1_H_STEP_BY = 4;
1961 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
1962 *val_OV0_P23_H_STEP_BY = 4;
1963 *P1StepSize = 8;
1964 *P23StepSize = 8;
1966 /* We step the Y by eight and the U and V by sixteen. */
1967 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
1968 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1969 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1971 *P1GroupSize = 4;
1972 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1973 *val_OV0_P1_H_STEP_BY = 4;
1974 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1975 *val_OV0_P23_H_STEP_BY = 5;
1976 *P1StepSize = 8;
1977 *P23StepSize = 16;
1979 /* We step the Y, U, and V by sixteen. */
1980 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
1981 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
1982 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1984 *P1GroupSize = 4;
1985 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1986 *val_OV0_P1_H_STEP_BY = 5;
1987 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1988 *val_OV0_P23_H_STEP_BY = 5;
1989 *P1StepSize = 16;
1990 *P23StepSize = 16;
1992 else
1994 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
1995 *P1GroupSize = 4;
1996 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1997 *val_OV0_P1_H_STEP_BY = 5;
1998 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1999 *val_OV0_P23_H_STEP_BY = 5;
2000 *P1StepSize = 16;
2001 *P23StepSize = 16;
2003 break;
2004 case 10:
2005 case 11:
2006 case 12:
2007 case 13:
2008 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2009 /* We scale the Y, U, and V with the four tap filters */
2010 /* four tap on both (unless Y is too wide) */
2011 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2012 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2013 { /*0.75 */
2014 *P1GroupSize = 2;
2015 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2016 *val_OV0_P1_H_STEP_BY = 0;
2017 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2018 *val_OV0_P23_H_STEP_BY = 0;
2019 *P1StepSize = 1;
2020 *P23StepSize = 1;
2022 /* two tap on Y (because it is too big for four tap), four tap on UV */
2023 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2024 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2025 { /*0.75 */
2026 *P1GroupSize = 4;
2027 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2028 *val_OV0_P1_H_STEP_BY = 1;
2029 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2030 *val_OV0_P23_H_STEP_BY = 0;
2031 *P1StepSize = 1;
2032 *P23StepSize = 1;
2034 /* We scale the Y with the four tap filters, but UV's are generated
2035 with dual two tap configuration. */
2036 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2037 !DisallowFourTapVertFiltering)
2038 { /*0.625 */
2039 *P1GroupSize = 2;
2040 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2041 *val_OV0_P1_H_STEP_BY = 0;
2042 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2043 *val_OV0_P23_H_STEP_BY = 1;
2044 *P1StepSize = 1;
2045 *P23StepSize = 1;
2047 /* We scale the Y, U, and V with the two tap filters */
2048 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2049 { /*0.375 */
2050 *P1GroupSize = 4;
2051 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2052 *val_OV0_P1_H_STEP_BY = 1;
2053 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2054 *val_OV0_P23_H_STEP_BY = 1;
2055 *P1StepSize = 1;
2056 *P23StepSize = 1;
2058 /* We scale step the U and V by two to allow more bandwidth for
2059 fetching Y's, thus we won't drop Y's yet. */
2060 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2061 { /*0.312 */
2062 *P1GroupSize = 4;
2063 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2064 *val_OV0_P1_H_STEP_BY = 1;
2065 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2066 *val_OV0_P23_H_STEP_BY = 2;
2067 *P1StepSize = 1;
2068 *P23StepSize = 2;
2070 /* We step the Y, U, and V by two. */
2071 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2073 *P1GroupSize = 4;
2074 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2075 *val_OV0_P1_H_STEP_BY = 2;
2076 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2077 *val_OV0_P23_H_STEP_BY = 2;
2078 *P1StepSize = 2;
2079 *P23StepSize = 2;
2081 /* We step the Y by two and the U and V by four. */
2082 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2084 *P1GroupSize = 4;
2085 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2086 *val_OV0_P1_H_STEP_BY = 2;
2087 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2088 *val_OV0_P23_H_STEP_BY = 3;
2089 *P1StepSize = 2;
2090 *P23StepSize = 4;
2092 /* We step the Y, U, and V by four. */
2093 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2095 *P1GroupSize = 4;
2096 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2097 *val_OV0_P1_H_STEP_BY = 3;
2098 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2099 *val_OV0_P23_H_STEP_BY = 3;
2100 *P1StepSize = 4;
2101 *P23StepSize = 4;
2103 /* We step the Y by four and the U and V by eight. */
2104 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2105 (fieldvalue_OV0_SURFACE_FORMAT==10))
2107 *P1GroupSize = 4;
2108 /* Can't mix step by 3 and step by 4 for packed modes */
2109 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2110 *val_OV0_P1_H_STEP_BY = 3;
2111 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2112 *val_OV0_P23_H_STEP_BY = 4;
2113 *P1StepSize = 4;
2114 *P23StepSize = 8;
2116 /* We step the Y, U, and V by eight. */
2117 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2119 *P1GroupSize = 4;
2120 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2121 *val_OV0_P1_H_STEP_BY = 4;
2122 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2123 *val_OV0_P23_H_STEP_BY = 4;
2124 *P1StepSize = 8;
2125 *P23StepSize = 8;
2127 /* We step the Y by eight and the U and V by sixteen. */
2128 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2130 *P1GroupSize = 4;
2131 /* Step by 5 not supported for packed modes */
2132 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2133 *val_OV0_P1_H_STEP_BY = 4;
2134 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2135 *val_OV0_P23_H_STEP_BY = 5;
2136 *P1StepSize = 8;
2137 *P23StepSize = 16;
2139 /* We step the Y, U, and V by sixteen. */
2140 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2141 (fieldvalue_OV0_SURFACE_FORMAT==10))
2143 *P1GroupSize = 4;
2144 /* Step by 5 not supported for packed modes */
2145 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2146 *val_OV0_P1_H_STEP_BY = 5;
2147 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2148 *val_OV0_P23_H_STEP_BY = 5;
2149 *P1StepSize = 16;
2150 *P23StepSize = 16;
2152 else
2154 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2156 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2157 *P1GroupSize = 4;
2158 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2159 *val_OV0_P1_H_STEP_BY = 5;
2160 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2161 *val_OV0_P23_H_STEP_BY = 5;
2162 *P1StepSize = 16;
2163 *P23StepSize = 16;
2165 else
2167 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2168 *P1GroupSize = 4;
2169 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2170 *val_OV0_P1_H_STEP_BY = 4;
2171 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2172 *val_OV0_P23_H_STEP_BY = 4;
2173 *P1StepSize = 8;
2174 *P23StepSize = 8;
2177 break;
2178 default: break;
2181 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2182 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2185 /* ********************************************************* */
2186 /* ** Setup Black Bordering */
2187 /* ********************************************************* */
2189 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2191 double tempBLANK_LINES_AT_TOP;
2192 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2193 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2194 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2196 if (floor(config->src.y)<0) {
2197 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2198 TopLine = 0;
2200 else {
2201 tempBLANK_LINES_AT_TOP = 0;
2202 TopLine = (int)floor(config->src.y);
2204 /* Round rSrcBottom up and subtract one */
2205 if (ceil(config->src.y+config->src.h) > config->src.h)
2207 BottomLine = config->src.h - 1;
2209 else
2211 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2214 if (BottomLine >= TopLine)
2216 SourceLinesUsed = BottomLine - TopLine + 1;
2218 else
2220 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2221 SourceLinesUsed = 1;
2225 int SourceHeightInPixels;
2226 SourceHeightInPixels = BottomLine - TopLine + 1;
2229 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2230 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2232 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2233 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2234 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2236 if (BottomUVLine >= TopUVLine)
2238 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2240 else
2242 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2243 SourceUVLinesUsed = 1;
2245 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2246 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2247 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2248 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2249 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2250 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2254 static void ComputeXStartEnd(
2255 int is_400,
2256 uint32_t LeftPixel,uint32_t LeftUVPixel,
2257 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2258 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2259 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2260 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2262 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2263 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2264 /* 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. */
2266 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2267 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2269 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2270 switch (besr.surf_id)
2272 case 9:
2273 case 10:
2274 case 13:
2275 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2276 /* a multiple of a power of two when decimating */
2277 val_OV0_P2_X_START = (int)LeftUVPixel %
2278 (MemWordsInBytes/BytesPerUVPixel);
2279 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2280 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2281 break;
2282 case 11:
2283 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2284 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2285 break;
2286 case 3:
2287 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2288 /* This value is needed only to allow proper setting of */
2289 /* val_OV0_PRESHIFT_P23_TO */
2290 /* val_OV0_P2_X_END = 0; */
2291 break;
2292 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2293 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2294 break;
2295 default: /* insert debug statement here. */
2296 RADEON_ASSERT("unknown fourcc\n");
2297 break;
2299 val_OV0_P3_X_START = val_OV0_P2_X_START;
2300 val_OV0_P3_X_END = val_OV0_P2_X_END;
2302 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2303 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2304 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2305 if(is_400)
2307 besr.p2_x_start_end = 0;
2308 besr.p3_x_start_end = 0;
2310 *p1_x_start = val_OV0_P1_X_START;
2311 *p2_x_start = val_OV0_P2_X_START;
2314 static void ComputeAccumInit(
2315 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2316 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2317 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2318 uint32_t CRT_V_INC,
2319 uint32_t P1GroupSize, uint32_t P23GroupSize,
2320 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2321 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2323 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2324 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2325 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2326 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2327 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2328 /* the distance (in source pixel coordinates) to the center of the first */
2329 /* destination pixel. Need to add additional pixels depending on how many pixels */
2330 /* are fetched at a time and how many pixels in a set are masked. */
2331 /* P23 values are always fetched in groups of two or four. If the start */
2332 /* pixel does not fall on the boundary, then we need to shift preshift for */
2333 /* some additional pixels */
2336 double ExtraHalfPixel;
2337 double tempAdditionalShift;
2338 double tempP1HStartPoint;
2339 double tempP23HStartPoint;
2340 double tempP1Init;
2341 double tempP23Init;
2343 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2344 else ExtraHalfPixel = 0.0;
2345 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2346 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2347 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2349 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2350 /* need to shift an additional pixel */
2351 /* Note that if the pitch is a multiple of two, and if we store fields using */
2352 /* the traditional planer format where the V plane and the U plane share the */
2353 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2354 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2355 /* it is a requirement that the U and V start on the same polarity byte */
2356 /* (even or odd). */
2357 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2358 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2359 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2360 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2361 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2362 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2363 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2366 /* ************************************************************** */
2367 /* ** Calculate values for initializing the vertical accumulators */
2368 /* ************************************************************** */
2371 double ExtraHalfLine;
2372 double ExtraFullLine;
2373 double tempP1VStartPoint;
2374 double tempP23VStartPoint;
2376 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2377 else ExtraHalfLine = 0.0;
2379 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2380 else ExtraFullLine = 0.0;
2382 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2383 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2385 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2387 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2389 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2390 else ExtraFullLine = 0.0;
2392 switch (besr.surf_id)
2394 case 10:
2395 case 13:
2396 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2397 ((float)CRT_V_INC / (1<<0xe));
2398 break;
2399 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2400 ((float)CRT_V_INC / (1<<0xf));
2401 break;
2402 case 3:
2403 case 4:
2404 case 6:
2405 case 11:
2406 case 12: tempP23VStartPoint = 0;
2407 break;
2408 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2409 break;
2412 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2414 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2417 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2419 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2420 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2421 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2422 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2425 typedef struct RangeAndCoefSet {
2426 double Range;
2427 signed char CoefSet[5][4];
2428 } RANGEANDCOEFSET;
2430 /* Filter Setup Routine */
2431 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2433 static RANGEANDCOEFSET ArrayOfSets[] = {
2434 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2435 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2436 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2437 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2438 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2439 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2440 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2441 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2442 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2443 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2444 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2445 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2446 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2447 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2448 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2449 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2450 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2451 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2452 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2453 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2454 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2455 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2456 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2457 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2458 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2459 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2460 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2461 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2462 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2463 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2464 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2465 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2466 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2467 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2468 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2469 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2470 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2471 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2472 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2473 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2474 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2475 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2476 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2477 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2478 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2479 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2480 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2481 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2482 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2483 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2484 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2485 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2486 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2487 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2488 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2489 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2490 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2491 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2492 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2493 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2494 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2495 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2496 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2497 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2498 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2499 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2500 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2501 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2502 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2503 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2504 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2505 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2506 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2507 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2508 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2509 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2512 double DSR;
2514 unsigned ArrayElement;
2516 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2517 if (DSR<.25) DSR=.25;
2518 if (DSR>1) DSR=1;
2520 ArrayElement = (int)((DSR-0.25) * 100);
2521 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2522 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2523 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2524 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2525 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2526 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2527 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2528 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2529 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2530 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2531 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2532 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2533 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2534 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2535 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2536 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2537 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2538 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2539 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2540 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2542 For more details, refer to Microsoft's draft of PC99.
2546 /* The minimal value of horizontal scale ratio when hard coded coefficients
2547 are suitable for the best quality. */
2548 /* FIXME: Should it be 0.9 for Rage128 ??? */
2549 static const double MinHScaleHard=0.75;
2551 static int radeon_vid_init_video( vidix_playback_t *config )
2553 double V_scale_ratio;
2554 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2555 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;
2556 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2557 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2558 uint32_t CRT_V_INC;
2559 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2560 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2561 uint32_t PageSizeInBytes,OV0LB_Rows;
2562 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2563 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2564 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2565 int is_400,is_410,is_420,best_pitch,mpitch;
2566 int horz_repl_factor,interlace_factor;
2567 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2568 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2570 radeon_vid_stop_video();
2571 left = config->src.x << 16;
2572 top = config->src.y << 16;
2573 src_h = config->src.h;
2574 src_w = config->src.w;
2575 is_400 = is_410 = is_420 = 0;
2576 if(config->fourcc == IMGFMT_YV12 ||
2577 config->fourcc == IMGFMT_I420 ||
2578 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2579 if(config->fourcc == IMGFMT_YVU9 ||
2580 config->fourcc == IMGFMT_IF09) is_410 = 1;
2581 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2582 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2583 mpitch = best_pitch-1;
2584 BytesPerOctWord = 16;
2585 LogMemWordsInBytes = 4;
2586 MemWordsInBytes = 1<<LogMemWordsInBytes;
2587 LogTileWidthInMemWords = 2;
2588 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2589 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2590 LogTileHeight = 4;
2591 TileHeight = 1<<LogTileHeight;
2592 PageSizeInBytes = 64*MemWordsInBytes;
2593 OV0LB_Rows = 96;
2594 h_inc = 1;
2595 switch(config->fourcc)
2597 /* 4:0:0*/
2598 case IMGFMT_Y800:
2599 /* 4:1:0*/
2600 case IMGFMT_YVU9:
2601 case IMGFMT_IF09:
2602 /* 4:2:0 */
2603 case IMGFMT_IYUV:
2604 case IMGFMT_YV12:
2605 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2606 config->dest.pitch.y =
2607 config->dest.pitch.u =
2608 config->dest.pitch.v = best_pitch;
2609 break;
2610 /* RGB 4:4:4:4 */
2611 case IMGFMT_RGB32:
2612 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2613 config->dest.pitch.y =
2614 config->dest.pitch.u =
2615 config->dest.pitch.v = best_pitch;
2616 break;
2617 /* 4:2:2 */
2619 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2620 pitch = ((src_w*2) + mpitch) & ~mpitch;
2621 config->dest.pitch.y =
2622 config->dest.pitch.u =
2623 config->dest.pitch.v = best_pitch;
2624 break;
2626 besr.load_prg_start=0;
2627 besr.swap_uv=0;
2628 switch(config->fourcc)
2630 case IMGFMT_RGB15:
2631 besr.swap_uv=1;
2632 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2633 besr.load_prg_start = 1;
2634 break;
2635 case IMGFMT_RGB16:
2636 besr.swap_uv=1;
2637 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2638 besr.load_prg_start = 1;
2639 break;
2640 case IMGFMT_RGB32:
2641 besr.swap_uv=1;
2642 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2643 besr.load_prg_start = 1;
2644 break;
2645 /* 4:1:0*/
2646 case IMGFMT_IF09:
2647 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2648 break;
2649 /* 4:0:0*/
2650 case IMGFMT_Y800:
2651 /* 4:2:0 */
2652 case IMGFMT_IYUV:
2653 case IMGFMT_I420:
2654 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2655 break;
2656 /* 4:2:2 */
2657 case IMGFMT_YVYU:
2658 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2659 break;
2660 case IMGFMT_YUY2:
2661 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2662 break;
2664 switch (besr.surf_id)
2666 case 3:
2667 case 4:
2668 case 11:
2669 case 12: BytesPerPixel = 2;
2670 break;
2671 case 6: BytesPerPixel = 4;
2672 break;
2673 case 9:
2674 case 10:
2675 case 13:
2676 case 14: BytesPerPixel = 1;
2677 break;
2678 default: BytesPerPixel = 0;/*insert a debug statement here. */
2679 break;
2681 switch (besr.surf_id)
2683 case 3:
2684 case 4: BytesPerUVPixel = 0;
2685 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2686 case 11:
2687 case 12: BytesPerUVPixel = 2;
2688 break;
2689 case 6: BytesPerUVPixel = 0;
2690 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2691 case 9:
2692 case 10: BytesPerUVPixel = 1;
2693 break;
2694 case 13:
2695 case 14: BytesPerUVPixel = 2;
2696 break;
2697 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2698 break;
2701 switch (besr.surf_id)
2703 case 3:
2704 case 4:
2705 case 6: HorzUVSubSample = 1;
2706 break;
2707 case 9: HorzUVSubSample = 4;
2708 break;
2709 case 10:
2710 case 11:
2711 case 12:
2712 case 13:
2713 case 14: HorzUVSubSample = 2;
2714 break;
2715 default: HorzUVSubSample = 0;/* insert debug statement here. */
2716 break;
2718 switch (besr.surf_id)
2720 case 3:
2721 case 4:
2722 case 6:
2723 case 11:
2724 case 12: VertUVSubSample = 1;
2725 break;
2726 case 9: VertUVSubSample = 4;
2727 break;
2728 case 10:
2729 case 13:
2730 case 14: VertUVSubSample = 2;
2731 break;
2732 default: VertUVSubSample = 0;/* insert debug statment here. */
2733 break;
2735 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2736 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2737 LeftPixel = config->src.x;
2738 RightPixel = config->src.w-1;
2739 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2740 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2741 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2742 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2743 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2744 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2745 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2746 SourceWidthInPixels = (int)(config->src.w + 1);
2747 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2749 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2750 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2751 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2752 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2753 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2754 MemWordsInBytes) + 1);
2756 switch (besr.surf_id)
2758 case 9:
2759 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2761 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2763 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2765 DisallowFourTapVertFiltering = 1;
2768 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2770 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2772 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2774 DisallowFourTapUVVertFiltering = 1;
2777 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2779 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2781 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2783 DisallowFourTapUVVertFiltering = 1;
2785 break;
2786 case 13:
2787 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2789 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2791 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2793 DisallowFourTapVertFiltering = 1;
2796 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2798 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2800 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2802 DisallowFourTapUVVertFiltering = 1;
2804 break;
2805 case 3:
2806 case 4:
2807 case 6:
2808 case 11:
2809 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2811 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2813 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2815 DisallowFourTapVertFiltering = 1;
2817 break;
2818 default: /* insert debug statement here. */
2819 break;
2821 dest_w = config->dest.w;
2822 dest_h = config->dest.h;
2823 if(radeon_is_dbl_scan()) dest_h *= 2;
2824 besr.dest_bpp = radeon_vid_get_dbpp();
2825 besr.fourcc = config->fourcc;
2826 if(radeon_is_interlace()) interlace_factor = 2;
2827 else interlace_factor = 1;
2828 /* TODO: must be checked in doublescan mode!!! */
2829 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2831 /* Force the overlay clock on for integrated chips */
2832 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2834 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2835 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2836 V_scale_ratio = (double)(dest_h+1)/src_h;
2837 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2839 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2840 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2842 else
2843 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2845 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2846 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2848 else
2850 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2851 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2853 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2854 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2855 CRT_V_INC = besr.v_inc/interlace_factor;
2856 besr.v_inc <<= 8;
2858 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2859 int P1GroupSize = 0;
2860 int P23GroupSize;
2861 int P1StepSize = 0;
2862 int P23StepSize = 0;
2864 Calc_H_INC_STEP_BY(
2865 besr.surf_id,
2866 H_scale_ratio,
2867 DisallowFourTapVertFiltering,
2868 DisallowFourTapUVVertFiltering,
2869 &val_OV0_P1_H_INC,
2870 &val_OV0_P1_H_STEP_BY,
2871 &val_OV0_P23_H_INC,
2872 &val_OV0_P23_H_STEP_BY,
2873 &P1GroupSize,
2874 &P1StepSize,
2875 &P23StepSize);
2877 if(H_scale_ratio > MinHScaleHard)
2879 h_inc = (src_w << 12) / dest_w;
2880 besr.step_by = 0x0101;
2881 switch (besr.surf_id)
2883 case 3:
2884 case 4:
2885 case 6:
2886 besr.h_inc = (h_inc)|(h_inc<<16);
2887 break;
2888 case 9:
2889 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2890 break;
2891 default:
2892 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2893 break;
2897 P23GroupSize = 2; /* Current vaue for all modes */
2899 besr.horz_pick_nearest=0;
2900 DoNotUseMostRecentlyFetchedLine=0;
2901 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2902 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2903 besr.vert_pick_nearest = 1;
2904 else
2905 besr.vert_pick_nearest = 0;
2907 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2908 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2909 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2911 if(H_scale_ratio > MinHScaleHard)
2913 unsigned tmp;
2914 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2915 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2916 ((tmp << 12) & 0xf0000000);
2918 tmp = (top & 0x0000ffff) + 0x00018000;
2919 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2920 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2921 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2922 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2923 ((tmp << 12) & 0x70000000);
2925 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2926 besr.p23_v_accum_init = (is_420||is_410) ?
2927 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2928 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2930 else
2931 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2932 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2933 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2934 CRT_V_INC,P1GroupSize,P23GroupSize,
2935 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2936 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
2939 /* keep everything in 16.16 */
2940 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
2941 config->offsets[0] = 0;
2942 for(i=1;i<besr.vid_nbufs;i++)
2943 config->offsets[i] = config->offsets[i-1]+config->frame_size;
2944 if(is_420 || is_410 || is_400)
2946 uint32_t d1line,d2line,d3line;
2947 d1line = top*pitch;
2948 if(is_420)
2950 d2line = src_h*pitch+(d1line>>2);
2951 d3line = d2line+((src_h*pitch)>>2);
2953 else
2954 if(is_410)
2956 d2line = src_h*pitch+(d1line>>4);
2957 d3line = d2line+((src_h*pitch)>>4);
2959 else
2961 d2line = 0;
2962 d3line = 0;
2964 d1line += (left >> 16) & ~15;
2965 if(is_420)
2967 d2line += (left >> 17) & ~15;
2968 d3line += (left >> 17) & ~15;
2970 else /* is_410 */
2972 d2line += (left >> 18) & ~15;
2973 d3line += (left >> 18) & ~15;
2975 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
2976 if(is_400)
2978 config->offset.v = 0;
2979 config->offset.u = 0;
2981 else
2983 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
2984 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
2986 for(i=0;i<besr.vid_nbufs;i++)
2988 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
2989 if(is_400)
2991 besr.vid_buf_base_adrs_v[i]=0;
2992 besr.vid_buf_base_adrs_u[i]=0;
2994 else
2996 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
2998 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;
2999 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;
3001 else
3003 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;
3004 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;
3008 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3009 if(is_400)
3011 config->offset.v = 0;
3012 config->offset.u = 0;
3014 else
3016 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3017 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3020 else
3022 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3023 for(i=0;i<besr.vid_nbufs;i++)
3025 besr.vid_buf_base_adrs_y[i] =
3026 besr.vid_buf_base_adrs_u[i] =
3027 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3030 leftUV = (left >> (is_410?18:17)) & 15;
3031 left = (left >> 16) & 15;
3032 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3033 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3034 ComputeBorders(config,VertUVSubSample);
3035 besr.vid_buf_pitch0_value = pitch;
3036 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3037 /* ********************************************************* */
3038 /* ** Calculate programmable coefficients as needed */
3039 /* ********************************************************* */
3041 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3042 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3043 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3044 else
3046 FilterSetup (val_OV0_P1_H_INC);
3047 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3048 /* would like to do. For now, we let the test application decide. */
3049 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3050 if(DisallowFourTapVertFiltering)
3051 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3052 if(DisallowFourTapUVVertFiltering)
3053 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3055 return 0;
3058 static void radeon_compute_framesize(vidix_playback_t *info)
3060 unsigned pitch,awidth,dbpp;
3061 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3062 dbpp = radeon_vid_get_dbpp();
3063 switch(info->fourcc)
3065 case IMGFMT_Y800:
3066 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3067 info->frame_size = awidth*info->src.h;
3068 break;
3069 case IMGFMT_YVU9:
3070 case IMGFMT_IF09:
3071 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3072 info->frame_size = awidth*(info->src.h+info->src.h/8);
3073 break;
3074 case IMGFMT_I420:
3075 case IMGFMT_YV12:
3076 case IMGFMT_IYUV:
3077 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3078 info->frame_size = awidth*(info->src.h+info->src.h/2);
3079 break;
3080 case IMGFMT_RGB32:
3081 case IMGFMT_BGR32:
3082 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3083 info->frame_size = awidth*info->src.h;
3084 break;
3085 /* YUY2 YVYU, RGB15, RGB16 */
3086 default:
3087 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3088 info->frame_size = awidth*info->src.h;
3089 break;
3091 info->frame_size = (info->frame_size+4095)&~4095;
3094 static int radeon_config_playback(vidix_playback_t *info)
3096 unsigned rgb_size,nfr;
3097 uint32_t radeon_video_size;
3098 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3099 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3100 if(info->num_frames==1) besr.double_buff=0;
3101 else besr.double_buff=1;
3102 radeon_compute_framesize(info);
3104 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3105 nfr = info->num_frames;
3106 radeon_video_size = radeon_ram_size;
3107 for(;nfr>0; nfr--)
3109 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3110 #if !defined (RAGE128) && defined(HAVE_X11)
3111 radeon_overlay_off -= firegl_shift;
3112 #endif
3113 radeon_overlay_off &= 0xffff0000;
3114 if(radeon_overlay_off >= (int)rgb_size ) break;
3116 if(nfr <= 3)
3118 nfr = info->num_frames;
3119 for(;nfr>0; nfr--)
3121 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3122 #if !defined (RAGE128) && defined(HAVE_X11)
3123 radeon_overlay_off -= firegl_shift;
3124 #endif
3125 radeon_overlay_off &= 0xffff0000;
3126 if(radeon_overlay_off > 0) break;
3129 if(nfr <= 0) return EINVAL;
3130 info->num_frames = nfr;
3131 besr.vid_nbufs = info->num_frames;
3132 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3133 radeon_vid_init_video(info);
3134 return 0;
3137 static int radeon_playback_on(void)
3139 #ifdef RAGE128
3140 unsigned dw,dh;
3141 #endif
3142 radeon_vid_display_video();
3143 #ifdef RAGE128
3144 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3145 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3146 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3147 else radeon_vid_non_exclusive();
3148 #endif
3149 return 0;
3152 static int radeon_playback_off(void)
3154 radeon_vid_stop_video();
3155 return 0;
3158 static int radeon_frame_select(unsigned frame)
3160 uint32_t off[6];
3161 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3163 buf3-5 always should point onto second buffer for better
3164 deinterlacing and TV-in
3166 if(!besr.double_buff) return 0;
3167 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3168 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3169 off[0] = besr.vid_buf_base_adrs_y[frame];
3170 off[1] = besr.vid_buf_base_adrs_v[frame];
3171 off[2] = besr.vid_buf_base_adrs_u[frame];
3172 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3173 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3174 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3175 radeon_fifo_wait(8);
3176 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3177 radeon_engine_idle();
3178 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3179 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3180 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3181 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3182 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3183 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3184 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3185 OUTREG(OV0_REG_LOAD_CNTL, 0);
3186 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3187 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
3188 return 0;
3191 static vidix_video_eq_t equal =
3193 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3194 #ifndef RAGE128
3195 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3196 #endif
3198 0, 0, 0, 0, 0, 0, 0, 0 };
3200 static int radeon_get_eq(vidix_video_eq_t * eq)
3202 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3203 return 0;
3206 #ifndef RAGE128
3207 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3208 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3209 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3210 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3211 #define RTFHue(a) (((a)*3.1416)/1000.0)
3212 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3213 #endif
3215 static int radeon_set_eq(const vidix_video_eq_t * eq)
3217 #ifdef RAGE128
3218 int br,sat;
3219 #else
3220 int itu_space;
3221 #endif
3222 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3223 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3224 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3225 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3226 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3228 equal.red_intensity = eq->red_intensity;
3229 equal.green_intensity = eq->green_intensity;
3230 equal.blue_intensity = eq->blue_intensity;
3232 equal.flags = eq->flags;
3233 #ifdef RAGE128
3234 br = equal.brightness * 64 / 1000;
3235 if(br < -64) br = -64; if(br > 63) br = 63;
3236 sat = (equal.saturation*31 + 31000) / 2000;
3237 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3238 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3239 #else
3240 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3241 RTFCheckParam(equal.brightness);
3242 RTFCheckParam(equal.saturation);
3243 RTFCheckParam(equal.contrast);
3244 RTFCheckParam(equal.hue);
3245 RTFCheckParam(equal.red_intensity);
3246 RTFCheckParam(equal.green_intensity);
3247 RTFCheckParam(equal.blue_intensity);
3248 radeon_set_transform(RTFBrightness(equal.brightness),
3249 RTFContrast(equal.contrast),
3250 RTFSaturation(equal.saturation),
3251 RTFHue(equal.hue),
3252 RTFIntensity(equal.red_intensity),
3253 RTFIntensity(equal.green_intensity),
3254 RTFIntensity(equal.blue_intensity),
3255 itu_space);
3256 #endif
3257 return 0;
3260 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3262 unsigned sflg;
3263 switch(info->flags)
3265 default:
3266 case CFG_NON_INTERLACED:
3267 besr.deinterlace_on = 0;
3268 break;
3269 case CFG_EVEN_ODD_INTERLACING:
3270 case CFG_INTERLACED:
3271 besr.deinterlace_on = 1;
3272 besr.deinterlace_pattern = 0x900AAAAA;
3273 break;
3274 case CFG_ODD_EVEN_INTERLACING:
3275 besr.deinterlace_on = 1;
3276 besr.deinterlace_pattern = 0x00055555;
3277 break;
3278 case CFG_UNIQUE_INTERLACING:
3279 besr.deinterlace_on = 1;
3280 besr.deinterlace_pattern = info->deinterlace_pattern;
3281 break;
3283 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3284 radeon_engine_idle();
3285 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3286 radeon_fifo_wait(15);
3287 sflg = INREG(OV0_SCALE_CNTL);
3288 if(besr.deinterlace_on)
3290 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3291 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3293 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3294 OUTREG(OV0_REG_LOAD_CNTL, 0);
3295 return 0;
3298 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3300 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3301 else
3303 info->flags = CFG_UNIQUE_INTERLACING;
3304 info->deinterlace_pattern = besr.deinterlace_pattern;
3306 return 0;
3310 /* Graphic keys */
3311 static vidix_grkey_t radeon_grkey;
3313 static int set_gr_key( void )
3315 int result = 0;
3317 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3318 0x00ff0000; /* graphic alpha */
3319 if(radeon_grkey.ckey.op == CKEY_TRUE)
3321 int dbpp=radeon_vid_get_dbpp();
3322 besr.ckey_on=1;
3324 switch(dbpp)
3326 case 15:
3327 #ifndef RAGE128
3328 if((besr.chip_flags&R_100)!=R_100)
3329 besr.graphics_key_clr=
3330 ((radeon_grkey.ckey.blue &0xF8))
3331 | ((radeon_grkey.ckey.green&0xF8)<<8)
3332 | ((radeon_grkey.ckey.red &0xF8)<<16);
3333 else
3334 #endif
3335 besr.graphics_key_clr=
3336 ((radeon_grkey.ckey.blue &0xF8)>>3)
3337 | ((radeon_grkey.ckey.green&0xF8)<<2)
3338 | ((radeon_grkey.ckey.red &0xF8)<<7);
3339 break;
3340 case 16:
3341 #ifndef RAGE128
3342 /* This test may be too general/specific */
3343 if((besr.chip_flags&R_100)!=R_100)
3344 besr.graphics_key_clr=
3345 ((radeon_grkey.ckey.blue &0xF8))
3346 | ((radeon_grkey.ckey.green&0xFC)<<8)
3347 | ((radeon_grkey.ckey.red &0xF8)<<16);
3348 else
3349 #endif
3350 besr.graphics_key_clr=
3351 ((radeon_grkey.ckey.blue &0xF8)>>3)
3352 | ((radeon_grkey.ckey.green&0xFC)<<3)
3353 | ((radeon_grkey.ckey.red &0xF8)<<8);
3354 break;
3355 case 24:
3356 case 32:
3357 besr.graphics_key_clr=
3358 ((radeon_grkey.ckey.blue &0xFF))
3359 | ((radeon_grkey.ckey.green&0xFF)<<8)
3360 | ((radeon_grkey.ckey.red &0xFF)<<16);
3361 break;
3362 default:
3363 besr.ckey_on=0;
3364 besr.graphics_key_msk=0;
3365 besr.graphics_key_clr=0;
3367 #ifdef RAGE128
3368 besr.graphics_key_msk=(1<<dbpp)-1;
3369 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3370 #else
3371 besr.graphics_key_msk=besr.graphics_key_clr;
3372 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3373 #endif
3375 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3377 int dbpp=radeon_vid_get_dbpp();
3378 besr.ckey_on=1;
3380 switch(dbpp)
3382 case 32:
3383 besr.ckey_on=1;
3384 besr.graphics_key_msk=0;
3385 besr.graphics_key_clr=0;
3386 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3387 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3388 0x00ff0000 | /* graphic alpha */
3389 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3390 break;
3391 default:
3392 besr.ckey_on=0;
3393 besr.graphics_key_msk=0;
3394 besr.graphics_key_clr=0;
3395 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3396 result = 1;
3399 else
3401 besr.ckey_on=0;
3402 besr.graphics_key_msk=0;
3403 besr.graphics_key_clr=0;
3404 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3406 radeon_fifo_wait(3);
3407 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3408 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3409 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3410 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3411 return result;
3414 static int radeon_get_gkey(vidix_grkey_t *grkey)
3416 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3417 return(0);
3420 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3422 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3423 return (set_gr_key());
3426 #ifdef RAGE128
3427 VDXDriver rage128_drv = {
3428 "rage128",
3429 #else
3430 VDXDriver radeon_drv = {
3431 "radeon",
3432 #endif
3433 NULL,
3435 .probe = radeon_probe,
3436 .get_caps = radeon_get_caps,
3437 .query_fourcc = radeon_query_fourcc,
3438 .init = radeon_init,
3439 .destroy = radeon_destroy,
3440 .config_playback = radeon_config_playback,
3441 .playback_on = radeon_playback_on,
3442 .playback_off = radeon_playback_off,
3443 .frame_sel = radeon_frame_select,
3444 .get_eq = radeon_get_eq,
3445 .set_eq = radeon_set_eq,
3446 .get_deint = radeon_playback_get_deint,
3447 .set_deint = radeon_playback_set_deint,
3448 .get_gkey = radeon_get_gkey,
3449 .set_gkey = radeon_set_gkey,