Make up missing header update in r25326.
[mplayer/greg.git] / vidix / radeon_vid.c
blob106a453c90f4b3892c72ff906547a11ec5ab9e1b
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(DMA_GUI_TABLE_ADDR),
259 DECLARE_VREG(DMA_GUI_SRC_ADDR),
260 DECLARE_VREG(DMA_GUI_DST_ADDR),
261 DECLARE_VREG(DMA_GUI_COMMAND),
262 DECLARE_VREG(DMA_GUI_STATUS),
263 DECLARE_VREG(DMA_GUI_ACT_DSCRPTR),
264 DECLARE_VREG(DMA_VID_SRC_ADDR),
265 DECLARE_VREG(DMA_VID_DST_ADDR),
266 DECLARE_VREG(DMA_VID_COMMAND),
267 DECLARE_VREG(DMA_VID_STATUS),
268 DECLARE_VREG(DMA_VID_ACT_DSCRPTR),
269 #endif
272 #define R_FAMILY 0x000000FF
273 #define R_100 0x00000001
274 #define R_120 0x00000002
275 #define R_150 0x00000004
276 #define R_200 0x00000008
277 #define R_250 0x00000010
278 #define R_280 0x00000020
279 #define R_300 0x00000040
280 #define R_350 0x00000080
281 #define R_370 0x00000100
282 #define R_380 0x00000200
283 #define R_420 0x00000400
284 #define R_430 0x00000800
285 #define R_480 0x00001000
286 #define R_OVL_SHIFT 0x01000000
287 #define R_INTEGRATED 0x02000000
288 #define R_PCIE 0x04000000
290 typedef struct ati_card_ids_s
292 unsigned short id;
293 unsigned flags;
294 }ati_card_ids_t;
296 static const ati_card_ids_t ati_card_ids[] =
298 #ifdef RAGE128
300 This driver should be compatible with Rage128 (pro) chips.
301 (include adaptive deinterlacing!!!).
302 Moreover: the same logic can be used with Mach64 chips.
303 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
304 but they are incompatible by i/o ports. So if enthusiasts will want
305 then they can redefine OUTREG and INREG macros and redefine OV0_*
306 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
307 fourccs (422 and 420 formats only).
309 /* Rage128 Pro GL */
310 { DEVICE_ATI_RAGE_128_PA_PRO, 0 },
311 { DEVICE_ATI_RAGE_128_PB_PRO, 0 },
312 { DEVICE_ATI_RAGE_128_PC_PRO, 0 },
313 { DEVICE_ATI_RAGE_128_PD_PRO, 0 },
314 { DEVICE_ATI_RAGE_128_PE_PRO, 0 },
315 { DEVICE_ATI_RAGE_128_PF_PRO, 0 },
316 /* Rage128 Pro VR */
317 { DEVICE_ATI_RAGE_128_PG_PRO, 0 },
318 { DEVICE_ATI_RAGE_128_PH_PRO, 0 },
319 { DEVICE_ATI_RAGE_128_PI_PRO, 0 },
320 { DEVICE_ATI_RAGE_128_PJ_PRO, 0 },
321 { DEVICE_ATI_RAGE_128_PK_PRO, 0 },
322 { DEVICE_ATI_RAGE_128_PL_PRO, 0 },
323 { DEVICE_ATI_RAGE_128_PM_PRO, 0 },
324 { DEVICE_ATI_RAGE_128_PN_PRO, 0 },
325 { DEVICE_ATI_RAGE_128_PO_PRO, 0 },
326 { DEVICE_ATI_RAGE_128_PP_PRO, 0 },
327 { DEVICE_ATI_RAGE_128_PQ_PRO, 0 },
328 { DEVICE_ATI_RAGE_128_PR_PRO, 0 },
329 { DEVICE_ATI_RAGE_128_PS_PRO, 0 },
330 { DEVICE_ATI_RAGE_128_PT_PRO, 0 },
331 { DEVICE_ATI_RAGE_128_PU_PRO, 0 },
332 { DEVICE_ATI_RAGE_128_PV_PRO, 0 },
333 { DEVICE_ATI_RAGE_128_PW_PRO, 0 },
334 { DEVICE_ATI_RAGE_128_PX_PRO, 0 },
335 /* Rage128 GL */
336 { DEVICE_ATI_RAGE_128_RE_SG, 0 },
337 { DEVICE_ATI_RAGE_128_RF_SG, 0 },
338 { DEVICE_ATI_RAGE_128_RG, 0 },
339 { DEVICE_ATI_RAGE_128_RK_VR, 0 },
340 { DEVICE_ATI_RAGE_128_RL_VR, 0 },
341 { DEVICE_ATI_RAGE_128_SE_4X, 0 },
342 { DEVICE_ATI_RAGE_128_SF_4X, 0 },
343 { DEVICE_ATI_RAGE_128_SG_4X, 0 },
344 { DEVICE_ATI_RAGE_128_SH, 0 },
345 { DEVICE_ATI_RAGE_128_SK_4X, 0 },
346 { DEVICE_ATI_RAGE_128_SL_4X, 0 },
347 { DEVICE_ATI_RAGE_128_SM_4X, 0 },
348 { DEVICE_ATI_RAGE_128_4X, 0 },
349 { DEVICE_ATI_RAGE_128_PRO, 0 },
350 { DEVICE_ATI_RAGE_128_PRO2, 0 },
351 { DEVICE_ATI_RAGE_128_PRO3, 0 },
352 /* these seem to be based on rage 128 instead of mach64 */
353 { DEVICE_ATI_RAGE_MOBILITY_M3, 0 },
354 { DEVICE_ATI_RAGE_MOBILITY_M32, 0 },
355 #else
356 /* Radeon1 (indeed: Rage 256 Pro ;) */
357 { DEVICE_ATI_RADEON_R100_QD, R_100|R_OVL_SHIFT },
358 { DEVICE_ATI_RADEON_R100_QE, R_100|R_OVL_SHIFT },
359 { DEVICE_ATI_RADEON_R100_QF, R_100|R_OVL_SHIFT },
360 { DEVICE_ATI_RADEON_R100_QG, R_100|R_OVL_SHIFT },
361 { DEVICE_ATI_RADEON_IGP_320, R_150|R_OVL_SHIFT|R_INTEGRATED },
362 { DEVICE_ATI_RADEON_MOBILITY_U1, R_150|R_OVL_SHIFT|R_INTEGRATED },
363 { DEVICE_ATI_RADEON_RV100_QY, R_120|R_OVL_SHIFT },
364 { DEVICE_ATI_RADEON_RV100_QZ, R_120|R_OVL_SHIFT },
365 { DEVICE_ATI_RADEON_MOBILITY_M7, R_150|R_OVL_SHIFT },
366 { DEVICE_ATI_RADEON_RV200_LX, R_150|R_OVL_SHIFT },
367 { DEVICE_ATI_RADEON_MOBILITY_M6, R_120|R_OVL_SHIFT },
368 { DEVICE_ATI_RADEON_MOBILITY_M62, R_120|R_OVL_SHIFT },
369 /* Radeon2 (indeed: Rage 512 Pro ;) */
370 { DEVICE_ATI_R200_BB_RADEON, R_200 },
371 { DEVICE_ATI_R200_BC_RADEON, R_200 },
372 { DEVICE_ATI_RADEON_R200_QH, R_200 },
373 { DEVICE_ATI_RADEON_R200_QI, R_200 },
374 { DEVICE_ATI_RADEON_R200_QJ, R_200 },
375 { DEVICE_ATI_RADEON_R200_QK, R_200 },
376 { DEVICE_ATI_RADEON_R200_QL, R_200 },
377 { DEVICE_ATI_RADEON_R200_QM, R_200 },
378 { DEVICE_ATI_RADEON_R200_QN, R_200 },
379 { DEVICE_ATI_RADEON_R200_QO, R_200 },
380 { DEVICE_ATI_RADEON_R200_QH2, R_200 },
381 { DEVICE_ATI_RADEON_R200_QI2, R_200 },
382 { DEVICE_ATI_RADEON_R200_QJ2, R_200 },
383 { DEVICE_ATI_RADEON_R200_QK2, R_200 },
384 { DEVICE_ATI_RADEON_R200_QL2, R_200 },
385 { DEVICE_ATI_RADEON_RV200_QW, R_150|R_OVL_SHIFT },
386 { DEVICE_ATI_RADEON_RV200_QX, R_150|R_OVL_SHIFT },
387 { DEVICE_ATI_RADEON_IGP330_340_350,R_200|R_INTEGRATED },
388 { DEVICE_ATI_RADEON_IGP_330M_340M_350M,R_200|R_INTEGRATED },
389 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
390 { DEVICE_ATI_RADEON_7000_IGP, R_250|R_OVL_SHIFT|R_INTEGRATED },
391 { DEVICE_ATI_RADEON_MOBILITY_7000, R_250|R_OVL_SHIFT|R_INTEGRATED },
392 { DEVICE_ATI_RADEON_RV250_ID, R_250|R_OVL_SHIFT },
393 { DEVICE_ATI_RADEON_RV250_IE, R_250|R_OVL_SHIFT },
394 { DEVICE_ATI_RADEON_RV250_IF, R_250|R_OVL_SHIFT },
395 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
396 { DEVICE_ATI_RADEON_R250_LD, R_250|R_OVL_SHIFT },
397 { DEVICE_ATI_RADEON_R250_LE, R_250|R_OVL_SHIFT },
398 { DEVICE_ATI_RADEON_R250_MOBILITY, R_250|R_OVL_SHIFT },
399 { DEVICE_ATI_RADEON_R250_LG, R_250|R_OVL_SHIFT },
400 { DEVICE_ATI_RV250_RADEON_9000, R_250|R_OVL_SHIFT },
401 { DEVICE_ATI_RADEON_RV250_RADEON2, R_250|R_OVL_SHIFT },
402 { DEVICE_ATI_RV280_RADEON_9200, R_280 },
403 { DEVICE_ATI_RV280_RADEON_92002, R_280 },
404 { DEVICE_ATI_RV280_RADEON_92003, R_280 },
405 { DEVICE_ATI_RV280_RADEON_92004, R_280 },
406 { DEVICE_ATI_RV280_RADEON_92005, R_280 },
407 { DEVICE_ATI_RV280_RADEON_92006, R_280 },
408 { DEVICE_ATI_RV280_RADEON_92007, R_280 },
409 { DEVICE_ATI_M9_5C61_RADEON, R_280 },
410 { DEVICE_ATI_M9_5C63_RADEON, R_280 },
411 /* Radeon3 (indeed: Rage 1024 Pro ;) */
412 { DEVICE_ATI_R300_AG_FIREGL, R_300 },
413 { DEVICE_ATI_RADEON_R300_ND, R_300 },
414 { DEVICE_ATI_RADEON_R300_NE, R_300 },
415 { DEVICE_ATI_RADEON_R300_NG, R_300 },
416 { DEVICE_ATI_R300_AD_RADEON, R_300 },
417 { DEVICE_ATI_R300_AE_RADEON, R_300 },
418 { DEVICE_ATI_R300_AF_RADEON, R_300 },
419 { DEVICE_ATI_RADEON_9100_IGP2, R_300|R_OVL_SHIFT|R_INTEGRATED },
420 { DEVICE_ATI_RS300M_AGP_RADEON, R_300|R_INTEGRATED },
421 { DEVICE_ATI_RS482_RADEON_XPRESS, R_350|R_INTEGRATED },
422 { DEVICE_ATI_R350_AH_RADEON, R_350 },
423 { DEVICE_ATI_R350_AI_RADEON, R_350 },
424 { DEVICE_ATI_R350_AJ_RADEON, R_350 },
425 { DEVICE_ATI_R350_AK_FIRE, R_350 },
426 { DEVICE_ATI_RADEON_R350_RADEON2, R_350 },
427 { DEVICE_ATI_RADEON_R350_RADEON3, R_350 },
428 { DEVICE_ATI_RV350_NJ_RADEON, R_350 },
429 { DEVICE_ATI_R350_NK_FIRE, R_350 },
430 { DEVICE_ATI_RV350_AP_RADEON, R_350 },
431 { DEVICE_ATI_RV350_AQ_RADEON, R_350 },
432 { DEVICE_ATI_RV350_AR_RADEON, R_350 },
433 { DEVICE_ATI_RV350_AS_RADEON, R_350 },
434 { DEVICE_ATI_RV350_AT_FIRE, R_350 },
435 { DEVICE_ATI_RV350_AU_FIRE, R_350 },
436 { DEVICE_ATI_RV350_AV_FIRE, R_350 },
437 { DEVICE_ATI_RV350_AW_FIRE, R_350 },
438 { DEVICE_ATI_RV350_MOBILITY_RADEON, R_350 },
439 { DEVICE_ATI_RV350_NF_RADEON, R_300 },
440 { DEVICE_ATI_RV350_NJ_RADEON, R_300 },
441 { DEVICE_ATI_RV350_AS_RADEON2, R_350 },
442 { DEVICE_ATI_M10_NQ_RADEON, R_350 },
443 { DEVICE_ATI_M10_NQ_RADEON2, R_350 },
444 { DEVICE_ATI_RV350_MOBILITY_RADEON2, R_350 },
445 { DEVICE_ATI_M10_NS_RADEON, R_350 },
446 { DEVICE_ATI_M10_NT_FIREGL, R_350 },
447 { DEVICE_ATI_M11_NV_FIREGL, R_350 },
448 { DEVICE_ATI_RV370_5B60_RADEON, R_370|R_PCIE },
449 { DEVICE_ATI_RV370_SAPPHIRE_X550, R_370 },
450 { DEVICE_ATI_RV370_5B64_FIREGL, R_370|R_PCIE },
451 { DEVICE_ATI_RV370_5B65_FIREGL, R_370|R_PCIE },
452 { DEVICE_ATI_M24_1P_RADEON, R_370 },
453 { DEVICE_ATI_M22_RADEON_MOBILITY, R_370 },
454 { DEVICE_ATI_M24_1T_FIREGL, R_370 },
455 { DEVICE_ATI_M24_RADEON_MOBILITY, R_370 },
456 { DEVICE_ATI_RV370_RADEON_X300SE, R_370 },
457 { DEVICE_ATI_RV370_SECONDARY_SAPPHIRE, R_370 },
458 { DEVICE_ATI_RV370_5B64_FIREGL2, R_370 },
459 { DEVICE_ATI_RV380_0X3E50_RADEON, R_380|R_PCIE },
460 { DEVICE_ATI_RV380_0X3E54_FIREGL, R_380|R_PCIE },
461 { DEVICE_ATI_RV380_RADEON_X600, R_380|R_PCIE },
462 { DEVICE_ATI_RV380_RADEON_X6002, R_380 },
463 { DEVICE_ATI_RV380_RADEON_X6003, R_380 },
464 { DEVICE_ATI_RV410_FIREGL_V5000, R_420 },
465 { DEVICE_ATI_RV410_FIREGL_V3300, R_420 },
466 { DEVICE_ATI_RV410_RADEON_X700XT, R_420 },
467 { DEVICE_ATI_RV410_RADEON_X700, R_420|R_PCIE },
468 { DEVICE_ATI_RV410_RADEON_X700SE, R_420 },
469 { DEVICE_ATI_RV410_RADEON_X7002, R_420|R_PCIE },
470 { DEVICE_ATI_RV410_RADEON_X7003, R_420 },
471 { DEVICE_ATI_RV410_RADEON_X7004, R_420|R_PCIE },
472 { DEVICE_ATI_RV410_RADEON_X7005, R_420|R_PCIE },
473 { DEVICE_ATI_M26_MOBILITY_FIREGL, R_420 },
474 { DEVICE_ATI_M26_MOBILITY_FIREGL2, R_420 },
475 { DEVICE_ATI_M26_RADEON_MOBILITY, R_420 },
476 { DEVICE_ATI_M26_RADEON_MOBILITY2, R_420 },
477 { DEVICE_ATI_RADEON_MOBILITY_X700, R_420 },
478 { DEVICE_ATI_R420_JH_RADEON, R_420|R_PCIE },
479 { DEVICE_ATI_R420_JI_RADEON, R_420|R_PCIE },
480 { DEVICE_ATI_R420_JJ_RADEON, R_420|R_PCIE },
481 { DEVICE_ATI_R420_JK_RADEON, R_420|R_PCIE },
482 { DEVICE_ATI_R420_JL_RADEON, R_420|R_PCIE },
483 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
484 { DEVICE_ATI_M18_JN_RADEON, R_420|R_PCIE },
485 { DEVICE_ATI_R420_JP_RADEON, R_420|R_PCIE },
486 { DEVICE_ATI_R420_RADEON_X800, R_420|R_PCIE },
487 { DEVICE_ATI_R420_RADEON_X8002, R_420|R_PCIE },
488 { DEVICE_ATI_R420_RADEON_X8003, R_420|R_PCIE },
489 { DEVICE_ATI_R420_RADEON_X8004, R_420|R_PCIE },
490 { DEVICE_ATI_R420_RADEON_X8005, R_420|R_PCIE },
491 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
492 { DEVICE_ATI_R423_5F57_RADEON, R_420|R_PCIE },
493 { DEVICE_ATI_R423_5F57_RADEON2, R_420|R_PCIE },
494 { DEVICE_ATI_R423_UH_RADEON, R_420|R_PCIE },
495 { DEVICE_ATI_R423_UI_RADEON, R_420|R_PCIE },
496 { DEVICE_ATI_R423_UJ_RADEON, R_420|R_PCIE },
497 { DEVICE_ATI_R423_UK_RADEON, R_420|R_PCIE },
498 { DEVICE_ATI_R423_FIRE_GL, R_420|R_PCIE },
499 { DEVICE_ATI_R423_UQ_FIREGL, R_420|R_PCIE },
500 { DEVICE_ATI_R423_UR_FIREGL, R_420|R_PCIE },
501 { DEVICE_ATI_R423_UT_FIREGL, R_420|R_PCIE },
502 { DEVICE_ATI_R423_UI_RADEON2, R_420|R_PCIE },
503 { DEVICE_ATI_R423GL_SE_ATI_FIREGL, R_420|R_PCIE },
504 { DEVICE_ATI_R423_RADEON_X800XT, R_420|R_PCIE },
505 { DEVICE_ATI_RADEON_R423_UK, R_420|R_PCIE },
506 { DEVICE_ATI_M28_RADEON_MOBILITY, R_420 },
507 { DEVICE_ATI_M28_MOBILITY_FIREGL, R_420 },
508 { DEVICE_ATI_MOBILITY_RADEON_X800, R_420 },
509 { DEVICE_ATI_R430_RADEON_X800, R_430|R_PCIE },
510 { DEVICE_ATI_R430_RADEON_X8002, R_430|R_PCIE },
511 { DEVICE_ATI_R430_RADEON_X8003, R_430|R_PCIE },
512 { DEVICE_ATI_R430_RADEON_X8004, R_430|R_PCIE },
513 { DEVICE_ATI_R480_RADEON_X800, R_480 },
514 { DEVICE_ATI_R480_RADEON_X8002, R_480 },
515 { DEVICE_ATI_R480_RADEON_X850XT, R_480 },
516 { DEVICE_ATI_R480_RADEON_X850PRO, R_480 },
517 { DEVICE_ATI_R481_RADEON_X850XT_PE, R_480|R_PCIE },
518 { DEVICE_ATI_R480_RADEON_X850XT2, R_480 },
519 { DEVICE_ATI_R480_RADEON_X850PRO2, R_480 },
520 { DEVICE_ATI_R481_RADEON_X850XT_PE2, R_480|R_PCIE },
521 { DEVICE_ATI_R480_RADEON_X850XT3, R_480|R_PCIE },
522 { DEVICE_ATI_R480_RADEON_X850XT4, R_480|R_PCIE },
523 { DEVICE_ATI_R480_RADEON_X850XT5, R_480|R_PCIE },
524 { DEVICE_ATI_R480_RADEON_X850XT6, R_480|R_PCIE },
525 #endif
529 static void * radeon_mmio_base = 0;
530 static void * radeon_mem_base = 0;
531 static int32_t radeon_overlay_off = 0;
532 static uint32_t radeon_ram_size = 0;
534 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
535 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
537 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr)
538 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr,val)
539 static inline uint32_t INREG (uint32_t addr) {
540 uint32_t tmp = GETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr);
541 return le2me_32(tmp);
543 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr,le2me_32(val))
544 #define OUTREGP(addr,val,mask) \
545 do { \
546 unsigned int _tmp = INREG(addr); \
547 _tmp &= (mask); \
548 _tmp |= (val); \
549 OUTREG(addr, _tmp); \
550 } while (0)
552 static __inline__ uint32_t INPLL(uint32_t addr)
554 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f);
555 return (INREG(CLOCK_CNTL_DATA));
558 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \
559 OUTREG(CLOCK_CNTL_DATA, val)
560 #define OUTPLLP(addr,val,mask) \
561 do { \
562 unsigned int _tmp = INPLL(addr); \
563 _tmp &= (mask); \
564 _tmp |= (val); \
565 OUTPLL(addr, _tmp); \
566 } while (0)
568 #ifndef RAGE128
569 enum radeon_montype
571 MT_NONE,
572 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */
573 MT_LCD, /* Liquid Crystal Display */
574 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */
575 MT_CTV, /* Composite TV out (not in VE) */
576 MT_STV /* S-Video TV out (probably in VE only) */
579 typedef struct radeon_info_s
581 int hasCRTC2;
582 int crtDispType;
583 int dviDispType;
584 }rinfo_t;
586 static rinfo_t rinfo;
588 static char * GET_MON_NAME(int type)
590 char *pret;
591 switch(type)
593 case MT_NONE: pret = "no"; break;
594 case MT_CRT: pret = "CRT"; break;
595 case MT_DFP: pret = "DFP"; break;
596 case MT_LCD: pret = "LCD"; break;
597 case MT_CTV: pret = "CTV"; break;
598 case MT_STV: pret = "STV"; break;
599 default: pret = "Unknown";
601 return pret;
604 static void radeon_get_moninfo (rinfo_t *rinfo)
606 unsigned int tmp;
608 tmp = INREG(RADEON_BIOS_4_SCRATCH);
610 if (rinfo->hasCRTC2) {
611 /* primary DVI port */
612 if (tmp & 0x08)
613 rinfo->dviDispType = MT_DFP;
614 else if (tmp & 0x4)
615 rinfo->dviDispType = MT_LCD;
616 else if (tmp & 0x200)
617 rinfo->dviDispType = MT_CRT;
618 else if (tmp & 0x10)
619 rinfo->dviDispType = MT_CTV;
620 else if (tmp & 0x20)
621 rinfo->dviDispType = MT_STV;
623 /* secondary CRT port */
624 if (tmp & 0x2)
625 rinfo->crtDispType = MT_CRT;
626 else if (tmp & 0x800)
627 rinfo->crtDispType = MT_DFP;
628 else if (tmp & 0x400)
629 rinfo->crtDispType = MT_LCD;
630 else if (tmp & 0x1000)
631 rinfo->crtDispType = MT_CTV;
632 else if (tmp & 0x2000)
633 rinfo->crtDispType = MT_STV;
634 } else {
635 rinfo->dviDispType = MT_NONE;
637 tmp = INREG(FP_GEN_CNTL);
639 if (tmp & FP_EN_TMDS)
640 rinfo->crtDispType = MT_DFP;
641 else
642 rinfo->crtDispType = MT_CRT;
645 #endif
647 static uint32_t radeon_vid_get_dbpp( void )
649 uint32_t dbpp,retval;
650 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF;
651 switch(dbpp)
653 case DST_8BPP: retval = 8; break;
654 case DST_15BPP: retval = 15; break;
655 case DST_16BPP: retval = 16; break;
656 case DST_24BPP: retval = 24; break;
657 default: retval=32; break;
659 return retval;
662 static int radeon_is_dbl_scan( void )
664 return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN;
667 static int radeon_is_interlace( void )
669 return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN;
672 static uint32_t radeon_get_xres( void )
674 uint32_t xres,h_total;
675 #ifndef RAGE128
676 if(rinfo.hasCRTC2 &&
677 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
678 h_total = INREG(CRTC2_H_TOTAL_DISP);
679 else
680 #endif
681 h_total = INREG(CRTC_H_TOTAL_DISP);
682 xres = (h_total >> 16) & 0xffff;
683 return (xres + 1)*8;
686 static uint32_t radeon_get_yres( void )
688 uint32_t yres,v_total;
689 #ifndef RAGE128
690 if(rinfo.hasCRTC2 &&
691 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
692 v_total = INREG(CRTC2_V_TOTAL_DISP);
693 else
694 #endif
695 v_total = INREG(CRTC_V_TOTAL_DISP);
696 yres = (v_total >> 16) & 0xffff;
697 return yres + 1;
700 static void radeon_wait_vsync(void)
702 int i;
704 OUTREG(GEN_INT_STATUS, VSYNC_INT_AK);
705 for (i = 0; i < 2000000; i++)
707 if (INREG(GEN_INT_STATUS) & VSYNC_INT) break;
711 #ifdef RAGE128
712 static void _radeon_engine_idle(void);
713 static void _radeon_fifo_wait(unsigned);
714 #define radeon_engine_idle() _radeon_engine_idle()
715 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
716 /* Flush all dirty data in the Pixel Cache to memory. */
717 static __inline__ void radeon_engine_flush ( void )
719 unsigned i;
721 OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL);
722 for (i = 0; i < 2000000; i++) {
723 if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break;
727 /* Reset graphics card to known state. */
728 static void radeon_engine_reset( void )
730 uint32_t clock_cntl_index;
731 uint32_t mclk_cntl;
732 uint32_t gen_reset_cntl;
734 radeon_engine_flush();
736 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
737 mclk_cntl = INPLL(MCLK_CNTL);
739 OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP);
741 gen_reset_cntl = INREG(GEN_RESET_CNTL);
743 OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
744 INREG(GEN_RESET_CNTL);
745 OUTREG(GEN_RESET_CNTL,
746 gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI));
747 INREG(GEN_RESET_CNTL);
749 OUTPLL(MCLK_CNTL, mclk_cntl);
750 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
751 OUTREG(GEN_RESET_CNTL, gen_reset_cntl);
753 #else
755 static __inline__ void radeon_engine_flush ( void )
757 int i;
759 /* initiate flush */
760 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
761 ~RB2D_DC_FLUSH_ALL);
763 for (i=0; i < 2000000; i++) {
764 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
765 break;
769 static void _radeon_engine_idle(void);
770 static void _radeon_fifo_wait(unsigned);
771 #define radeon_engine_idle() _radeon_engine_idle()
772 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
774 static void radeon_engine_reset( void )
776 uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
778 radeon_engine_flush ();
780 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
781 mclk_cntl = INPLL(MCLK_CNTL);
783 OUTPLL(MCLK_CNTL, (mclk_cntl |
784 FORCEON_MCLKA |
785 FORCEON_MCLKB |
786 FORCEON_YCLKA |
787 FORCEON_YCLKB |
788 FORCEON_MC |
789 FORCEON_AIC));
790 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
792 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
793 SOFT_RESET_CP |
794 SOFT_RESET_HI |
795 SOFT_RESET_SE |
796 SOFT_RESET_RE |
797 SOFT_RESET_PP |
798 SOFT_RESET_E2 |
799 SOFT_RESET_RB |
800 SOFT_RESET_HDP);
801 INREG(RBBM_SOFT_RESET);
802 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t)
803 ~(SOFT_RESET_CP |
804 SOFT_RESET_HI |
805 SOFT_RESET_SE |
806 SOFT_RESET_RE |
807 SOFT_RESET_PP |
808 SOFT_RESET_E2 |
809 SOFT_RESET_RB |
810 SOFT_RESET_HDP));
811 INREG(RBBM_SOFT_RESET);
813 OUTPLL(MCLK_CNTL, mclk_cntl);
814 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
815 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
817 return;
819 #endif
820 static void radeon_engine_restore( void )
822 #ifndef RAGE128
823 int pitch64;
824 uint32_t xres,yres,bpp;
825 radeon_fifo_wait(1);
826 xres = radeon_get_xres();
827 yres = radeon_get_yres();
828 bpp = radeon_vid_get_dbpp();
829 /* turn of all automatic flushing - we'll do it all */
830 OUTREG(RB2D_DSTCACHE_MODE, 0);
832 pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6;
834 radeon_fifo_wait(1);
835 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) |
836 (pitch64 << 22));
838 radeon_fifo_wait(1);
839 #if defined(WORDS_BIGENDIAN)
840 OUTREGP(DP_DATATYPE,
841 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
842 #else
843 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
844 #endif
846 radeon_fifo_wait(1);
847 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX
848 | DEFAULT_SC_BOTTOM_MAX));
849 radeon_fifo_wait(1);
850 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL)
851 | GMC_BRUSH_SOLID_COLOR
852 | GMC_SRC_DATATYPE_COLOR));
854 radeon_fifo_wait(7);
855 OUTREG(DST_LINE_START, 0);
856 OUTREG(DST_LINE_END, 0);
857 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
858 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
859 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
860 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
861 OUTREG(DP_WRITE_MASK, 0xffffffff);
863 radeon_engine_idle();
864 #endif
866 #ifdef RAGE128
867 static void _radeon_fifo_wait (unsigned entries)
869 unsigned i;
871 for(;;)
873 for (i=0; i<2000000; i++)
874 if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries)
875 return;
876 radeon_engine_reset();
877 radeon_engine_restore();
881 static void _radeon_engine_idle ( void )
883 unsigned i;
885 /* ensure FIFO is empty before waiting for idle */
886 radeon_fifo_wait (64);
887 for(;;)
889 for (i=0; i<2000000; i++) {
890 if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) {
891 radeon_engine_flush ();
892 return;
895 radeon_engine_reset();
896 radeon_engine_restore();
899 #else
900 static void _radeon_fifo_wait (unsigned entries)
902 unsigned i;
904 for(;;)
906 for (i=0; i<2000000; i++)
907 if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries)
908 return;
909 radeon_engine_reset();
910 radeon_engine_restore();
913 static void _radeon_engine_idle ( void )
915 int i;
917 /* ensure FIFO is empty before waiting for idle */
918 radeon_fifo_wait (64);
919 for(;;)
921 for (i=0; i<2000000; i++) {
922 if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) {
923 radeon_engine_flush ();
924 return;
927 radeon_engine_reset();
928 radeon_engine_restore();
931 #endif
933 #ifndef RAGE128
934 /* Reference color space transform data */
935 typedef struct tagREF_TRANSFORM
937 float RefLuma;
938 float RefRCb;
939 float RefRCr;
940 float RefGCb;
941 float RefGCr;
942 float RefBCb;
943 float RefBCr;
944 } REF_TRANSFORM;
946 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
947 REF_TRANSFORM trans[2] =
949 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
950 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
952 /****************************************************************************
953 * SetTransform *
954 * Function: Calculates and sets color space transform from supplied *
955 * reference transform, gamma, brightness, contrast, hue and *
956 * saturation. *
957 * Inputs: bright - brightness *
958 * cont - contrast *
959 * sat - saturation *
960 * hue - hue *
961 * red_intensity - intense of red component *
962 * green_intensity - intense of green component *
963 * blue_intensity - intense of blue component *
964 * ref - index to the table of refernce transforms *
965 * Outputs: NONE *
966 ****************************************************************************/
968 static void radeon_set_transform(float bright, float cont, float sat,
969 float hue, float red_intensity,
970 float green_intensity,float blue_intensity,
971 unsigned ref)
973 float OvHueSin, OvHueCos;
974 float CAdjLuma, CAdjOff;
975 float RedAdj,GreenAdj,BlueAdj;
976 float CAdjRCb, CAdjRCr;
977 float CAdjGCb, CAdjGCr;
978 float CAdjBCb, CAdjBCr;
979 float OvLuma, OvROff, OvGOff, OvBOff;
980 float OvRCb, OvRCr;
981 float OvGCb, OvGCr;
982 float OvBCb, OvBCr;
983 float Loff = 64.0;
984 float Coff = 512.0f;
986 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
987 uint32_t dwOvRCb, dwOvRCr;
988 uint32_t dwOvGCb, dwOvGCr;
989 uint32_t dwOvBCb, dwOvBCr;
991 if (ref >= 2) return;
993 OvHueSin = sin((double)hue);
994 OvHueCos = cos((double)hue);
996 CAdjLuma = cont * trans[ref].RefLuma;
997 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
998 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
999 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
1000 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
1002 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
1003 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
1004 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1005 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1006 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1007 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1009 OvLuma = CAdjLuma;
1010 OvRCb = CAdjRCb;
1011 OvRCr = CAdjRCr;
1012 OvGCb = CAdjGCb;
1013 OvGCr = CAdjGCr;
1014 OvBCb = CAdjBCb;
1015 OvBCr = CAdjBCr;
1016 OvROff = RedAdj + CAdjOff -
1017 OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1018 OvGOff = GreenAdj + CAdjOff -
1019 OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1020 OvBOff = BlueAdj + CAdjOff -
1021 OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1023 dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff;
1024 dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff;
1025 dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff;
1026 /* Whatever docs say about R200 having 3.8 format instead of 3.11
1027 as in Radeon is a lie */
1029 dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17;
1030 dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1;
1031 dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17;
1032 dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1;
1033 dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17;
1034 dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1;
1035 dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17;
1037 OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1038 OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1039 OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1040 OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1041 OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1042 OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1045 /* Gamma curve definition */
1046 typedef struct
1048 unsigned int gammaReg;
1049 unsigned int gammaSlope;
1050 unsigned int gammaOffset;
1051 }GAMMA_SETTINGS;
1053 /* Recommended gamma curve parameters */
1054 GAMMA_SETTINGS r200_def_gamma[18] =
1056 {OV0_GAMMA_0_F, 0x100, 0x0000},
1057 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1058 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1059 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1060 {OV0_GAMMA_80_BF, 0x100, 0x0100},
1061 {OV0_GAMMA_C0_FF, 0x100, 0x0100},
1062 {OV0_GAMMA_100_13F, 0x100, 0x0200},
1063 {OV0_GAMMA_140_17F, 0x100, 0x0200},
1064 {OV0_GAMMA_180_1BF, 0x100, 0x0300},
1065 {OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
1066 {OV0_GAMMA_200_23F, 0x100, 0x0400},
1067 {OV0_GAMMA_240_27F, 0x100, 0x0400},
1068 {OV0_GAMMA_280_2BF, 0x100, 0x0500},
1069 {OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
1070 {OV0_GAMMA_300_33F, 0x100, 0x0600},
1071 {OV0_GAMMA_340_37F, 0x100, 0x0600},
1072 {OV0_GAMMA_380_3BF, 0x100, 0x0700},
1073 {OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
1076 GAMMA_SETTINGS r100_def_gamma[6] =
1078 {OV0_GAMMA_0_F, 0x100, 0x0000},
1079 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1080 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1081 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1082 {OV0_GAMMA_380_3BF, 0x100, 0x0100},
1083 {OV0_GAMMA_3C0_3FF, 0x100, 0x0100}
1086 static void make_default_gamma_correction( void )
1088 size_t i;
1089 if((besr.chip_flags & R_100)==R_100||
1090 (besr.chip_flags & R_120)==R_120||
1091 (besr.chip_flags & R_150)==R_150){
1092 OUTREG(OV0_LIN_TRANS_A, 0x12A00000);
1093 OUTREG(OV0_LIN_TRANS_B, 0x199018FE);
1094 OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0);
1095 OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B);
1096 OUTREG(OV0_LIN_TRANS_E, 0x12A02050);
1097 OUTREG(OV0_LIN_TRANS_F, 0x0000174E);
1098 for(i=0; i<6; i++){
1099 OUTREG(r100_def_gamma[i].gammaReg,
1100 (r100_def_gamma[i].gammaSlope<<16) |
1101 r100_def_gamma[i].gammaOffset);
1104 else{
1105 OUTREG(OV0_LIN_TRANS_A, 0x12a20000);
1106 OUTREG(OV0_LIN_TRANS_B, 0x198a190e);
1107 OUTREG(OV0_LIN_TRANS_C, 0x12a2f9da);
1108 OUTREG(OV0_LIN_TRANS_D, 0xf2fe0442);
1109 OUTREG(OV0_LIN_TRANS_E, 0x12a22046);
1110 OUTREG(OV0_LIN_TRANS_F, 0x175f);
1111 /* Default Gamma,
1112 Of 18 segments for gamma cure, all segments in R200 are programmable,
1113 while only lower 4 and upper 2 segments are programmable in Radeon*/
1114 for(i=0; i<18; i++){
1115 OUTREG(r200_def_gamma[i].gammaReg,
1116 (r200_def_gamma[i].gammaSlope<<16) |
1117 r200_def_gamma[i].gammaOffset);
1121 #endif
1123 static void radeon_vid_make_default(void)
1125 #ifdef RAGE128
1126 besr.saturation = 0x0F;
1127 besr.brightness = 0;
1128 OUTREG(OV0_COLOUR_CNTL,0x000F0F00UL); /* Default brihgtness and saturation for Rage128 */
1129 #else
1130 make_default_gamma_correction();
1131 #endif
1132 besr.deinterlace_pattern = 0x900AAAAA;
1133 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1134 besr.deinterlace_on=1;
1135 besr.double_buff=1;
1136 besr.ckey_on=0;
1137 besr.graphics_key_msk=0;
1138 besr.graphics_key_clr=0;
1139 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
1142 static int find_chip(unsigned chip_id)
1144 unsigned i;
1145 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1147 if(chip_id == ati_card_ids[i].id) return i;
1149 return -1;
1152 static pciinfo_t pci_info;
1153 static int probed=0;
1155 static vidix_capability_t def_cap =
1157 #ifdef RAGE128
1158 "BES driver for Rage128 cards",
1159 #else
1160 "BES driver for Radeon cards",
1161 #endif
1162 "Nick Kurshev",
1163 TYPE_OUTPUT | TYPE_FX,
1164 { 0, 0, 0, 0 },
1165 2048,
1166 2048,
1170 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1171 VENDOR_ATI,
1173 { 0, 0, 0, 0}
1176 #if !defined(RAGE128) && defined(HAVE_X11)
1177 static void probe_fireGL_driver(void) {
1178 Display *dp = XOpenDisplay ((void*)0);
1179 int n = 0;
1180 char **extlist;
1181 if (dp==NULL) {
1182 return;
1184 extlist = XListExtensions (dp, &n);
1185 XCloseDisplay (dp);
1186 if (extlist) {
1187 int i;
1188 int ext_fgl = 0, ext_fglrx = 0;
1189 for (i = 0; i < n; i++) {
1190 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1191 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1193 if (ext_fgl) {
1194 printf(RADEON_MSG" ATI FireGl driver detected");
1195 firegl_shift = 0x500000;
1196 if (!ext_fglrx) {
1197 printf(", but DRI seems not to be activated\n");
1198 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1200 printf("\n");
1204 #endif
1206 static int radeon_probe(int verbose, int force)
1208 pciinfo_t lst[MAX_PCI_DEVICES];
1209 unsigned i,num_pci;
1210 int err;
1211 __verbose = verbose;
1212 err = pci_scan(lst,&num_pci);
1213 if(err)
1215 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1216 return err;
1218 else
1220 err = ENXIO;
1221 for(i=0;i<num_pci;i++)
1223 if(lst[i].vendor == VENDOR_ATI)
1225 int idx;
1226 const char *dname;
1227 idx = find_chip(lst[i].device);
1228 if(idx == -1 && force == PROBE_NORMAL) continue;
1229 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1230 dname = dname ? dname : "Unknown chip";
1231 printf(RADEON_MSG" Found chip: %s\n",dname);
1232 #if 0
1233 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1235 printf("[radeon] Device is disabled, ignoring\n");
1236 continue;
1238 #endif
1239 memset(&besr,0,sizeof(bes_registers_t));
1240 if(force > PROBE_NORMAL)
1242 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1243 if(idx == -1)
1244 #ifdef RAGE128
1245 printf(RADEON_MSG" Assuming it as Rage128\n");
1246 #else
1247 printf(RADEON_MSG" Assuming it as Radeon1\n");
1248 #endif
1249 besr.chip_flags=R_100|R_OVL_SHIFT;
1251 #if !defined(RAGE128) && defined(HAVE_X11)
1252 probe_fireGL_driver();
1253 #endif
1254 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1255 def_cap.device_id = lst[i].device;
1256 err = 0;
1257 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1258 probed=1;
1259 break;
1263 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1264 return err;
1267 typedef struct saved_regs_s
1269 uint32_t ov0_vid_key_clr;
1270 uint32_t ov0_vid_key_msk;
1271 uint32_t ov0_graphics_key_clr;
1272 uint32_t ov0_graphics_key_msk;
1273 uint32_t ov0_key_cntl;
1274 uint32_t disp_merge_cntl;
1275 }saved_regs_t;
1276 static saved_regs_t savreg;
1278 static void save_regs( void )
1280 radeon_fifo_wait(6);
1281 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1282 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1283 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1284 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1285 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1286 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1289 static void restore_regs( void )
1291 radeon_fifo_wait(6);
1292 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1293 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1294 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1295 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1296 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1297 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1300 static int radeon_init(void)
1302 int err;
1304 if(__verbose>0) printf("[radeon_vid] version %d\n", VIDIX_VERSION);
1306 if(!probed)
1308 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1309 return EINTR;
1311 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1312 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1313 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1314 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1315 #ifdef RADEON
1316 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1317 if (radeon_ram_size == 0 &&
1318 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1319 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1321 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1322 radeon_ram_size = 8192*1024;
1324 else if (radeon_ram_size == 0 &&
1325 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1327 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1328 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1329 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1331 #else
1332 /* Rage Mobility (rage128) also has memsize bug */
1333 if (radeon_ram_size == 0 &&
1334 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1335 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1337 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1338 radeon_ram_size = 8192*1024;
1340 #endif
1341 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1342 radeon_vid_make_default();
1343 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1344 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1345 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1346 #ifndef RAGE128
1348 memset(&rinfo,0,sizeof(rinfo_t));
1349 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1351 radeon_get_moninfo(&rinfo);
1352 if(rinfo.hasCRTC2) {
1353 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1354 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1356 else
1357 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1359 #endif
1360 save_regs();
1361 return 0;
1364 static void radeon_destroy(void)
1366 restore_regs();
1367 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1368 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1371 static int radeon_get_caps(vidix_capability_t *to)
1373 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1374 return 0;
1378 Full list of fourcc which are supported by Win2K radeon driver:
1379 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1380 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1382 typedef struct fourcc_desc_s
1384 uint32_t fourcc;
1385 unsigned max_srcw;
1386 }fourcc_desc_t;
1388 static fourcc_desc_t supported_fourcc[] =
1390 { IMGFMT_Y800, 1567 },
1391 { IMGFMT_YVU9, 1567 },
1392 { IMGFMT_IF09, 1567 },
1393 { IMGFMT_YV12, 1567 },
1394 { IMGFMT_I420, 1567 },
1395 { IMGFMT_IYUV, 1567 },
1396 { IMGFMT_UYVY, 1551 },
1397 { IMGFMT_YUY2, 1551 },
1398 { IMGFMT_YVYU, 1551 },
1399 { IMGFMT_RGB15, 1551 },
1400 { IMGFMT_BGR15, 1551 },
1401 { IMGFMT_RGB16, 1551 },
1402 { IMGFMT_BGR16, 1551 },
1403 { IMGFMT_RGB32, 775 },
1404 { IMGFMT_BGR32, 775 }
1407 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1409 unsigned i;
1410 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1412 if(fourcc==supported_fourcc[i].fourcc)
1413 return 1;
1415 return 0;
1418 static int radeon_query_fourcc(vidix_fourcc_t *to)
1420 if(is_supported_fourcc(to->fourcc))
1422 to->depth = VID_DEPTH_ALL;
1423 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1424 VID_CAP_BLEND;
1425 return 0;
1427 else to->depth = to->flags = 0;
1428 return ENOSYS;
1431 static double H_scale_ratio;
1432 static void radeon_vid_dump_regs( void )
1434 size_t i;
1435 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1436 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1437 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1438 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1439 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1440 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1441 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1442 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1443 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1444 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1445 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1448 static void radeon_vid_stop_video( void )
1450 radeon_engine_idle();
1451 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1452 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1453 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1454 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1455 #ifdef RAGE128
1456 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1457 #else
1458 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1459 #endif
1460 OUTREG(OV0_TEST, 0);
1463 static void radeon_vid_display_video( void )
1465 int bes_flags,force_second;
1466 radeon_fifo_wait(2);
1467 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1468 radeon_engine_idle();
1469 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1470 radeon_fifo_wait(15);
1472 force_second=0;
1474 /* Shutdown capturing */
1475 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1476 OUTREG(CAP0_TRIG_CNTL, 0);
1478 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1479 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1481 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1483 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1484 #ifdef RAGE128
1485 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1486 (besr.saturation << 8) |
1487 (besr.saturation << 16));
1488 #endif
1489 radeon_fifo_wait(2);
1490 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1491 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1492 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1494 OUTREG(OV0_H_INC, besr.h_inc);
1495 OUTREG(OV0_STEP_BY, besr.step_by);
1496 if(force_second)
1498 OUTREG(OV1_Y_X_START, besr.y_x_start);
1499 OUTREG(OV1_Y_X_END, besr.y_x_end);
1501 else
1503 OUTREG(OV0_Y_X_START, besr.y_x_start);
1504 OUTREG(OV0_Y_X_END, besr.y_x_end);
1506 OUTREG(OV0_V_INC, besr.v_inc);
1507 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1508 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1509 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1510 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1511 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1512 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1513 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1514 #ifdef RADEON
1515 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1516 #endif
1517 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1518 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1519 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1520 radeon_fifo_wait(9);
1521 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1522 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1523 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1524 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1525 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1526 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1527 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1529 bes_flags = SCALER_ENABLE |
1530 SCALER_SMART_SWITCH |
1531 SCALER_Y2R_TEMP |
1532 SCALER_PIX_EXPAND;
1533 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1534 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1535 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1536 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1537 #ifdef RAGE128
1538 bes_flags |= SCALER_BURST_PER_PLANE;
1539 #endif
1540 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1541 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1542 if(force_second) bes_flags |= SCALER_USE_OV1;
1543 else bes_flags &= ~SCALER_USE_OV1;
1544 OUTREG(OV0_SCALE_CNTL, bes_flags);
1545 radeon_fifo_wait(6);
1546 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1547 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1548 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1549 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1550 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1551 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1552 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1553 OUTREG(OV0_REG_LOAD_CNTL, 0);
1554 if(__verbose > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1555 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
1558 /* Goal of this function: hide RGB background and provide black screen around movie.
1559 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1560 Reverse effect to colorkey */
1561 #ifdef RAGE128
1562 static void radeon_vid_exclusive( void )
1564 /* this function works only with Rage128.
1565 Radeon should has something the same */
1566 unsigned screenw,screenh;
1567 screenw = radeon_get_xres();
1568 screenh = radeon_get_yres();
1569 radeon_fifo_wait(2);
1570 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1571 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1574 static void radeon_vid_non_exclusive( void )
1576 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1578 #endif
1580 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1582 unsigned pitch,spy,spv,spu;
1583 spy = spv = spu = 0;
1584 switch(spitch->y)
1586 case 16:
1587 case 32:
1588 case 64:
1589 case 128:
1590 case 256: spy = spitch->y; break;
1591 default: break;
1593 switch(spitch->u)
1595 case 16:
1596 case 32:
1597 case 64:
1598 case 128:
1599 case 256: spu = spitch->u; break;
1600 default: break;
1602 switch(spitch->v)
1604 case 16:
1605 case 32:
1606 case 64:
1607 case 128:
1608 case 256: spv = spitch->v; break;
1609 default: break;
1611 switch(fourcc)
1613 /* 4:2:0 */
1614 case IMGFMT_IYUV:
1615 case IMGFMT_YV12:
1616 case IMGFMT_I420:
1617 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1618 else pitch = 32;
1619 break;
1620 case IMGFMT_IF09:
1621 case IMGFMT_YVU9:
1622 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1623 else pitch = 64;
1624 break;
1625 default:
1626 if(spy >= 16) pitch = spy;
1627 else pitch = 16;
1628 break;
1630 return pitch;
1633 static void Calc_H_INC_STEP_BY (
1634 int fieldvalue_OV0_SURFACE_FORMAT,
1635 double H_scale_ratio,
1636 int DisallowFourTapVertFiltering,
1637 int DisallowFourTapUVVertFiltering,
1638 uint32_t *val_OV0_P1_H_INC,
1639 uint32_t *val_OV0_P1_H_STEP_BY,
1640 uint32_t *val_OV0_P23_H_INC,
1641 uint32_t *val_OV0_P23_H_STEP_BY,
1642 int *P1GroupSize,
1643 int *P1StepSize,
1644 int *P23StepSize )
1647 double ClocksNeededFor16Pixels;
1649 switch (fieldvalue_OV0_SURFACE_FORMAT)
1651 case 3:
1652 case 4: /*16BPP (ARGB1555 and RGB565) */
1653 /* All colour components are fetched in pairs */
1654 *P1GroupSize = 2;
1655 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1656 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1657 if (H_scale_ratio>=.5)
1659 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1660 /* until we reach .5. P1 and P23 are the same. */
1661 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1662 *val_OV0_P1_H_STEP_BY = 1;
1663 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1664 *val_OV0_P23_H_STEP_BY = 1;
1665 *P1StepSize = 1;
1666 *P23StepSize = 1;
1668 else if (H_scale_ratio>=.25)
1670 /* Step by two */
1671 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1672 *val_OV0_P1_H_STEP_BY = 2;
1673 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1674 *val_OV0_P23_H_STEP_BY = 2;
1675 *P1StepSize = 2;
1676 *P23StepSize = 2;
1678 else if (H_scale_ratio>=.125)
1680 /* Step by four */
1681 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1682 *val_OV0_P1_H_STEP_BY = 3;
1683 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1684 *val_OV0_P23_H_STEP_BY = 3;
1685 *P1StepSize = 4;
1686 *P23StepSize = 4;
1688 else if (H_scale_ratio>=.0625)
1690 /* Step by eight */
1691 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1692 *val_OV0_P1_H_STEP_BY = 4;
1693 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1694 *val_OV0_P23_H_STEP_BY = 4;
1695 *P1StepSize = 8;
1696 *P23StepSize = 8;
1698 else if (H_scale_ratio>=0.03125)
1700 /* Step by sixteen */
1701 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1702 *val_OV0_P1_H_STEP_BY = 5;
1703 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1704 *val_OV0_P23_H_STEP_BY = 5;
1705 *P1StepSize = 16;
1706 *P23StepSize = 16;
1708 else
1710 H_scale_ratio=0.03125;
1711 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1712 *val_OV0_P1_H_STEP_BY = 5;
1713 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1714 *val_OV0_P23_H_STEP_BY = 5;
1715 *P1StepSize = 16;
1716 *P23StepSize = 16;
1718 break;
1719 case 6: /*32BPP RGB */
1720 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1722 /* All colour components are fetched in pairs */
1723 *P1GroupSize = 2;
1724 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1725 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1726 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1727 *val_OV0_P1_H_STEP_BY = 0;
1728 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1729 *val_OV0_P23_H_STEP_BY = 0;
1730 *P1StepSize = 1;
1731 *P23StepSize = 1;
1733 else if (H_scale_ratio>=0.75)
1735 /* Four G colour components are fetched at once */
1736 *P1GroupSize = 4;
1737 /* R and B colour components are fetched in pairs */
1738 /* With two tap filtering, we can generate four colour components every clock. */
1739 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1740 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1741 *val_OV0_P1_H_STEP_BY = 1;
1742 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1743 *val_OV0_P23_H_STEP_BY = 1;
1744 *P1StepSize = 1;
1745 *P23StepSize = 1;
1747 else if (H_scale_ratio>=0.375)
1749 /* Step by two. */
1750 /* Four G colour components are fetched at once */
1751 *P1GroupSize = 4;
1752 /* R and B colour components are fetched in pairs */
1753 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1754 *val_OV0_P1_H_STEP_BY = 2;
1755 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1756 *val_OV0_P23_H_STEP_BY = 2;
1757 *P1StepSize = 2;
1758 *P23StepSize = 2;
1760 else if (H_scale_ratio>=0.25)
1762 /* Step by two. */
1763 /* Four G colour components are fetched at once */
1764 *P1GroupSize = 4;
1765 /* R and B colour components are fetched in pairs */
1766 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1767 *val_OV0_P1_H_STEP_BY = 2;
1768 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1769 *val_OV0_P23_H_STEP_BY = 3;
1770 *P1StepSize = 2;
1771 *P23StepSize = 4;
1773 else if (H_scale_ratio>=0.1875)
1775 /* Step by four */
1776 /* Four G colour components are fetched at once */
1777 *P1GroupSize = 4;
1778 /* R and B colour components are fetched in pairs */
1779 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1780 *val_OV0_P1_H_STEP_BY = 3;
1781 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1782 *val_OV0_P23_H_STEP_BY = 3;
1783 *P1StepSize = 4;
1784 *P23StepSize = 4;
1786 else if (H_scale_ratio>=0.125)
1788 /* Step by four */
1789 /* Four G colour components are fetched at once */
1790 *P1GroupSize = 4;
1791 /* R and B colour components are fetched in pairs */
1792 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1793 *val_OV0_P1_H_STEP_BY = 3;
1794 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1795 *val_OV0_P23_H_STEP_BY = 4;
1796 *P1StepSize = 4;
1797 *P23StepSize = 8;
1799 else if (H_scale_ratio>=0.09375)
1801 /* Step by eight */
1802 /* Four G colour components are fetched at once */
1803 *P1GroupSize = 4;
1804 /* R and B colour components are fetched in pairs */
1805 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1806 *val_OV0_P1_H_STEP_BY = 4;
1807 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1808 *val_OV0_P23_H_STEP_BY = 4;
1809 *P1StepSize = 8;
1810 *P23StepSize = 8;
1812 else if (H_scale_ratio>=0.0625)
1814 /* Step by eight */
1815 /* Four G colour components are fetched at once */
1816 *P1GroupSize = 4;
1817 /* R and B colour components are fetched in pairs */
1818 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1819 *val_OV0_P1_H_STEP_BY = 5;
1820 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1821 *val_OV0_P23_H_STEP_BY = 5;
1822 *P1StepSize = 16;
1823 *P23StepSize = 16;
1825 else
1827 H_scale_ratio=0.0625;
1828 *P1GroupSize = 4;
1829 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1830 *val_OV0_P1_H_STEP_BY = 5;
1831 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1832 *val_OV0_P23_H_STEP_BY = 5;
1833 *P1StepSize = 16;
1834 *P23StepSize = 16;
1836 break;
1837 case 9:
1838 /*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. */
1839 /* four tap on both (unless Y is too wide) */
1840 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1841 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1842 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1843 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1844 { /*0.75 */
1845 /* Colour components are fetched in pairs */
1846 *P1GroupSize = 2;
1847 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1848 *val_OV0_P1_H_STEP_BY = 0;
1849 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1850 *val_OV0_P23_H_STEP_BY = 0;
1851 *P1StepSize = 1;
1852 *P23StepSize = 1;
1854 /* two tap on Y (because it is too big for four tap), four tap on UV */
1855 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1856 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1857 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1858 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1859 { /*0.75 */
1860 *P1GroupSize = 4;
1861 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1862 *val_OV0_P1_H_STEP_BY = 1;
1863 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1864 *val_OV0_P23_H_STEP_BY = 0;
1865 *P1StepSize = 1;
1866 *P23StepSize = 1;
1868 /* We scale the Y with the four tap filters, but UV's are generated
1869 with dual two tap configuration. */
1870 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1871 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1872 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1873 !DisallowFourTapVertFiltering)
1874 { /*0.625 */
1875 *P1GroupSize = 2;
1876 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1877 *val_OV0_P1_H_STEP_BY = 0;
1878 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1879 *val_OV0_P23_H_STEP_BY = 1;
1880 *P1StepSize = 1;
1881 *P23StepSize = 1;
1883 /* We scale the Y, U, and V with the two tap filters */
1884 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1885 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1886 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1887 { /*0.375 */
1888 *P1GroupSize = 4;
1889 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1890 *val_OV0_P1_H_STEP_BY = 1;
1891 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1892 *val_OV0_P23_H_STEP_BY = 1;
1893 *P1StepSize = 1;
1894 *P23StepSize = 1;
1896 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1897 thus we won't drop Y's yet. */
1898 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1899 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1900 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1901 { /*>=0.3125 and >.333333~ */
1902 *P1GroupSize = 4;
1903 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1904 *val_OV0_P1_H_STEP_BY = 1;
1905 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1906 *val_OV0_P23_H_STEP_BY = 2;
1907 *P1StepSize = 1;
1908 *P23StepSize = 2;
1910 /* We step the Y, U, and V by two. */
1911 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1912 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1913 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1915 *P1GroupSize = 4;
1916 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1917 *val_OV0_P1_H_STEP_BY = 2;
1918 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1919 *val_OV0_P23_H_STEP_BY = 2;
1920 *P1StepSize = 2;
1921 *P23StepSize = 2;
1923 /* We step the Y by two and the U and V by four. */
1924 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1925 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1926 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1928 *P1GroupSize = 4;
1929 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1930 *val_OV0_P1_H_STEP_BY = 2;
1931 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1932 *val_OV0_P23_H_STEP_BY = 3;
1933 *P1StepSize = 2;
1934 *P23StepSize = 4;
1936 /* We step the Y, U, and V by four. */
1937 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
1938 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
1939 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1941 *P1GroupSize = 4;
1942 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1943 *val_OV0_P1_H_STEP_BY = 3;
1944 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1945 *val_OV0_P23_H_STEP_BY = 3;
1946 *P1StepSize = 4;
1947 *P23StepSize = 4;
1949 /* 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 */
1951 /* We step the Y, U, and V by eight. */
1952 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
1953 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1954 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
1956 *P1GroupSize = 4;
1957 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1958 *val_OV0_P1_H_STEP_BY = 4;
1959 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
1960 *val_OV0_P23_H_STEP_BY = 4;
1961 *P1StepSize = 8;
1962 *P23StepSize = 8;
1964 /* We step the Y by eight and the U and V by sixteen. */
1965 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
1966 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1967 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1969 *P1GroupSize = 4;
1970 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1971 *val_OV0_P1_H_STEP_BY = 4;
1972 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1973 *val_OV0_P23_H_STEP_BY = 5;
1974 *P1StepSize = 8;
1975 *P23StepSize = 16;
1977 /* We step the Y, U, and V by sixteen. */
1978 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
1979 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
1980 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1982 *P1GroupSize = 4;
1983 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1984 *val_OV0_P1_H_STEP_BY = 5;
1985 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1986 *val_OV0_P23_H_STEP_BY = 5;
1987 *P1StepSize = 16;
1988 *P23StepSize = 16;
1990 else
1992 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
1993 *P1GroupSize = 4;
1994 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1995 *val_OV0_P1_H_STEP_BY = 5;
1996 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1997 *val_OV0_P23_H_STEP_BY = 5;
1998 *P1StepSize = 16;
1999 *P23StepSize = 16;
2001 break;
2002 case 10:
2003 case 11:
2004 case 12:
2005 case 13:
2006 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2007 /* We scale the Y, U, and V with the four tap filters */
2008 /* four tap on both (unless Y is too wide) */
2009 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2010 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2011 { /*0.75 */
2012 *P1GroupSize = 2;
2013 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2014 *val_OV0_P1_H_STEP_BY = 0;
2015 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2016 *val_OV0_P23_H_STEP_BY = 0;
2017 *P1StepSize = 1;
2018 *P23StepSize = 1;
2020 /* two tap on Y (because it is too big for four tap), four tap on UV */
2021 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2022 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2023 { /*0.75 */
2024 *P1GroupSize = 4;
2025 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2026 *val_OV0_P1_H_STEP_BY = 1;
2027 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2028 *val_OV0_P23_H_STEP_BY = 0;
2029 *P1StepSize = 1;
2030 *P23StepSize = 1;
2032 /* We scale the Y with the four tap filters, but UV's are generated
2033 with dual two tap configuration. */
2034 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2035 !DisallowFourTapVertFiltering)
2036 { /*0.625 */
2037 *P1GroupSize = 2;
2038 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2039 *val_OV0_P1_H_STEP_BY = 0;
2040 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2041 *val_OV0_P23_H_STEP_BY = 1;
2042 *P1StepSize = 1;
2043 *P23StepSize = 1;
2045 /* We scale the Y, U, and V with the two tap filters */
2046 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2047 { /*0.375 */
2048 *P1GroupSize = 4;
2049 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2050 *val_OV0_P1_H_STEP_BY = 1;
2051 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2052 *val_OV0_P23_H_STEP_BY = 1;
2053 *P1StepSize = 1;
2054 *P23StepSize = 1;
2056 /* We scale step the U and V by two to allow more bandwidth for
2057 fetching Y's, thus we won't drop Y's yet. */
2058 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2059 { /*0.312 */
2060 *P1GroupSize = 4;
2061 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2062 *val_OV0_P1_H_STEP_BY = 1;
2063 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2064 *val_OV0_P23_H_STEP_BY = 2;
2065 *P1StepSize = 1;
2066 *P23StepSize = 2;
2068 /* We step the Y, U, and V by two. */
2069 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2071 *P1GroupSize = 4;
2072 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2073 *val_OV0_P1_H_STEP_BY = 2;
2074 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2075 *val_OV0_P23_H_STEP_BY = 2;
2076 *P1StepSize = 2;
2077 *P23StepSize = 2;
2079 /* We step the Y by two and the U and V by four. */
2080 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2082 *P1GroupSize = 4;
2083 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2084 *val_OV0_P1_H_STEP_BY = 2;
2085 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2086 *val_OV0_P23_H_STEP_BY = 3;
2087 *P1StepSize = 2;
2088 *P23StepSize = 4;
2090 /* We step the Y, U, and V by four. */
2091 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2093 *P1GroupSize = 4;
2094 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2095 *val_OV0_P1_H_STEP_BY = 3;
2096 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2097 *val_OV0_P23_H_STEP_BY = 3;
2098 *P1StepSize = 4;
2099 *P23StepSize = 4;
2101 /* We step the Y by four and the U and V by eight. */
2102 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2103 (fieldvalue_OV0_SURFACE_FORMAT==10))
2105 *P1GroupSize = 4;
2106 /* Can't mix step by 3 and step by 4 for packed modes */
2107 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2108 *val_OV0_P1_H_STEP_BY = 3;
2109 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2110 *val_OV0_P23_H_STEP_BY = 4;
2111 *P1StepSize = 4;
2112 *P23StepSize = 8;
2114 /* We step the Y, U, and V by eight. */
2115 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2117 *P1GroupSize = 4;
2118 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2119 *val_OV0_P1_H_STEP_BY = 4;
2120 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2121 *val_OV0_P23_H_STEP_BY = 4;
2122 *P1StepSize = 8;
2123 *P23StepSize = 8;
2125 /* We step the Y by eight and the U and V by sixteen. */
2126 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2128 *P1GroupSize = 4;
2129 /* Step by 5 not supported for packed modes */
2130 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2131 *val_OV0_P1_H_STEP_BY = 4;
2132 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2133 *val_OV0_P23_H_STEP_BY = 5;
2134 *P1StepSize = 8;
2135 *P23StepSize = 16;
2137 /* We step the Y, U, and V by sixteen. */
2138 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2139 (fieldvalue_OV0_SURFACE_FORMAT==10))
2141 *P1GroupSize = 4;
2142 /* Step by 5 not supported for packed modes */
2143 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2144 *val_OV0_P1_H_STEP_BY = 5;
2145 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2146 *val_OV0_P23_H_STEP_BY = 5;
2147 *P1StepSize = 16;
2148 *P23StepSize = 16;
2150 else
2152 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2154 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2155 *P1GroupSize = 4;
2156 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2157 *val_OV0_P1_H_STEP_BY = 5;
2158 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2159 *val_OV0_P23_H_STEP_BY = 5;
2160 *P1StepSize = 16;
2161 *P23StepSize = 16;
2163 else
2165 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2166 *P1GroupSize = 4;
2167 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2168 *val_OV0_P1_H_STEP_BY = 4;
2169 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2170 *val_OV0_P23_H_STEP_BY = 4;
2171 *P1StepSize = 8;
2172 *P23StepSize = 8;
2175 break;
2176 default: break;
2179 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2180 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2183 /* ********************************************************* */
2184 /* ** Setup Black Bordering */
2185 /* ********************************************************* */
2187 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2189 double tempBLANK_LINES_AT_TOP;
2190 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2191 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2192 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2194 if (floor(config->src.y)<0) {
2195 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2196 TopLine = 0;
2198 else {
2199 tempBLANK_LINES_AT_TOP = 0;
2200 TopLine = (int)floor(config->src.y);
2202 /* Round rSrcBottom up and subtract one */
2203 if (ceil(config->src.y+config->src.h) > config->src.h)
2205 BottomLine = config->src.h - 1;
2207 else
2209 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2212 if (BottomLine >= TopLine)
2214 SourceLinesUsed = BottomLine - TopLine + 1;
2216 else
2218 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2219 SourceLinesUsed = 1;
2223 int SourceHeightInPixels;
2224 SourceHeightInPixels = BottomLine - TopLine + 1;
2227 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2228 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2230 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2231 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2232 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2234 if (BottomUVLine >= TopUVLine)
2236 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2238 else
2240 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2241 SourceUVLinesUsed = 1;
2243 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2244 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2245 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2246 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2247 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2248 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2252 static void ComputeXStartEnd(
2253 int is_400,
2254 uint32_t LeftPixel,uint32_t LeftUVPixel,
2255 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2256 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2257 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2258 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2260 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2261 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2262 /* 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. */
2264 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2265 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2267 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2268 switch (besr.surf_id)
2270 case 9:
2271 case 10:
2272 case 13:
2273 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2274 /* a multiple of a power of two when decimating */
2275 val_OV0_P2_X_START = (int)LeftUVPixel %
2276 (MemWordsInBytes/BytesPerUVPixel);
2277 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2278 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2279 break;
2280 case 11:
2281 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2282 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2283 break;
2284 case 3:
2285 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2286 /* This value is needed only to allow proper setting of */
2287 /* val_OV0_PRESHIFT_P23_TO */
2288 /* val_OV0_P2_X_END = 0; */
2289 break;
2290 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2291 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2292 break;
2293 default: /* insert debug statement here. */
2294 RADEON_ASSERT("unknown fourcc\n");
2295 break;
2297 val_OV0_P3_X_START = val_OV0_P2_X_START;
2298 val_OV0_P3_X_END = val_OV0_P2_X_END;
2300 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2301 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2302 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2303 if(is_400)
2305 besr.p2_x_start_end = 0;
2306 besr.p3_x_start_end = 0;
2308 *p1_x_start = val_OV0_P1_X_START;
2309 *p2_x_start = val_OV0_P2_X_START;
2312 static void ComputeAccumInit(
2313 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2314 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2315 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2316 uint32_t CRT_V_INC,
2317 uint32_t P1GroupSize, uint32_t P23GroupSize,
2318 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2319 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2321 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2322 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2323 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2324 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2325 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2326 /* the distance (in source pixel coordinates) to the center of the first */
2327 /* destination pixel. Need to add additional pixels depending on how many pixels */
2328 /* are fetched at a time and how many pixels in a set are masked. */
2329 /* P23 values are always fetched in groups of two or four. If the start */
2330 /* pixel does not fall on the boundary, then we need to shift preshift for */
2331 /* some additional pixels */
2334 double ExtraHalfPixel;
2335 double tempAdditionalShift;
2336 double tempP1HStartPoint;
2337 double tempP23HStartPoint;
2338 double tempP1Init;
2339 double tempP23Init;
2341 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2342 else ExtraHalfPixel = 0.0;
2343 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2344 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2345 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2347 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2348 /* need to shift an additional pixel */
2349 /* Note that if the pitch is a multiple of two, and if we store fields using */
2350 /* the traditional planer format where the V plane and the U plane share the */
2351 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2352 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2353 /* it is a requirement that the U and V start on the same polarity byte */
2354 /* (even or odd). */
2355 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2356 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2357 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2358 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2359 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2360 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2361 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2364 /* ************************************************************** */
2365 /* ** Calculate values for initializing the vertical accumulators */
2366 /* ************************************************************** */
2369 double ExtraHalfLine;
2370 double ExtraFullLine;
2371 double tempP1VStartPoint;
2372 double tempP23VStartPoint;
2374 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2375 else ExtraHalfLine = 0.0;
2377 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2378 else ExtraFullLine = 0.0;
2380 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2381 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2383 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2385 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2387 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2388 else ExtraFullLine = 0.0;
2390 switch (besr.surf_id)
2392 case 10:
2393 case 13:
2394 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2395 ((float)CRT_V_INC / (1<<0xe));
2396 break;
2397 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2398 ((float)CRT_V_INC / (1<<0xf));
2399 break;
2400 case 3:
2401 case 4:
2402 case 6:
2403 case 11:
2404 case 12: tempP23VStartPoint = 0;
2405 break;
2406 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2407 break;
2410 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2412 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2415 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2417 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2418 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2419 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2420 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2423 typedef struct RangeAndCoefSet {
2424 double Range;
2425 signed char CoefSet[5][4];
2426 } RANGEANDCOEFSET;
2428 /* Filter Setup Routine */
2429 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2431 static RANGEANDCOEFSET ArrayOfSets[] = {
2432 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2433 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2434 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2435 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2436 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2437 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2438 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2439 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2440 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2441 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2442 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2443 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2444 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2445 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2446 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2447 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2448 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2449 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2450 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2451 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2452 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2453 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2454 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2455 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2456 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2457 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2458 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2459 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2460 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2461 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2462 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2463 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2464 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2465 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2466 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2467 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2468 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2469 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2470 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2471 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2472 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2473 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2474 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2475 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2476 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2477 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2478 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2479 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2480 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2481 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2482 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2483 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2484 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2485 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2486 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2487 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2488 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2489 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2490 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2491 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2492 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2493 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2494 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2495 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2496 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2497 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2498 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2499 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2500 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2501 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2502 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2503 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2504 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2505 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2506 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2507 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2510 double DSR;
2512 unsigned ArrayElement;
2514 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2515 if (DSR<.25) DSR=.25;
2516 if (DSR>1) DSR=1;
2518 ArrayElement = (int)((DSR-0.25) * 100);
2519 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2520 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2521 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2522 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2523 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2524 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2525 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2526 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2527 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2528 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2529 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2530 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2531 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2532 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2533 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2534 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2535 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2536 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2537 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2538 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2540 For more details, refer to Microsoft's draft of PC99.
2544 /* The minimal value of horizontal scale ratio when hard coded coefficients
2545 are suitable for the best quality. */
2546 /* FIXME: Should it be 0.9 for Rage128 ??? */
2547 static const double MinHScaleHard=0.75;
2549 static int radeon_vid_init_video( vidix_playback_t *config )
2551 double V_scale_ratio;
2552 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2553 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;
2554 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2555 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2556 uint32_t CRT_V_INC;
2557 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2558 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2559 uint32_t PageSizeInBytes,OV0LB_Rows;
2560 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2561 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2562 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2563 int is_400,is_410,is_420,best_pitch,mpitch;
2564 int horz_repl_factor,interlace_factor;
2565 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2566 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2568 radeon_vid_stop_video();
2569 left = config->src.x << 16;
2570 top = config->src.y << 16;
2571 src_h = config->src.h;
2572 src_w = config->src.w;
2573 is_400 = is_410 = is_420 = 0;
2574 if(config->fourcc == IMGFMT_YV12 ||
2575 config->fourcc == IMGFMT_I420 ||
2576 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2577 if(config->fourcc == IMGFMT_YVU9 ||
2578 config->fourcc == IMGFMT_IF09) is_410 = 1;
2579 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2580 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2581 mpitch = best_pitch-1;
2582 BytesPerOctWord = 16;
2583 LogMemWordsInBytes = 4;
2584 MemWordsInBytes = 1<<LogMemWordsInBytes;
2585 LogTileWidthInMemWords = 2;
2586 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2587 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2588 LogTileHeight = 4;
2589 TileHeight = 1<<LogTileHeight;
2590 PageSizeInBytes = 64*MemWordsInBytes;
2591 OV0LB_Rows = 96;
2592 h_inc = 1;
2593 switch(config->fourcc)
2595 /* 4:0:0*/
2596 case IMGFMT_Y800:
2597 /* 4:1:0*/
2598 case IMGFMT_YVU9:
2599 case IMGFMT_IF09:
2600 /* 4:2:0 */
2601 case IMGFMT_IYUV:
2602 case IMGFMT_YV12:
2603 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2604 config->dest.pitch.y =
2605 config->dest.pitch.u =
2606 config->dest.pitch.v = best_pitch;
2607 break;
2608 /* RGB 4:4:4:4 */
2609 case IMGFMT_RGB32:
2610 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2611 config->dest.pitch.y =
2612 config->dest.pitch.u =
2613 config->dest.pitch.v = best_pitch;
2614 break;
2615 /* 4:2:2 */
2617 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2618 pitch = ((src_w*2) + mpitch) & ~mpitch;
2619 config->dest.pitch.y =
2620 config->dest.pitch.u =
2621 config->dest.pitch.v = best_pitch;
2622 break;
2624 besr.load_prg_start=0;
2625 besr.swap_uv=0;
2626 switch(config->fourcc)
2628 case IMGFMT_RGB15:
2629 besr.swap_uv=1;
2630 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2631 besr.load_prg_start = 1;
2632 break;
2633 case IMGFMT_RGB16:
2634 besr.swap_uv=1;
2635 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2636 besr.load_prg_start = 1;
2637 break;
2638 case IMGFMT_RGB32:
2639 besr.swap_uv=1;
2640 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2641 besr.load_prg_start = 1;
2642 break;
2643 /* 4:1:0*/
2644 case IMGFMT_IF09:
2645 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2646 break;
2647 /* 4:0:0*/
2648 case IMGFMT_Y800:
2649 /* 4:2:0 */
2650 case IMGFMT_IYUV:
2651 case IMGFMT_I420:
2652 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2653 break;
2654 /* 4:2:2 */
2655 case IMGFMT_YVYU:
2656 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2657 break;
2658 case IMGFMT_YUY2:
2659 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2660 break;
2662 switch (besr.surf_id)
2664 case 3:
2665 case 4:
2666 case 11:
2667 case 12: BytesPerPixel = 2;
2668 break;
2669 case 6: BytesPerPixel = 4;
2670 break;
2671 case 9:
2672 case 10:
2673 case 13:
2674 case 14: BytesPerPixel = 1;
2675 break;
2676 default: BytesPerPixel = 0;/*insert a debug statement here. */
2677 break;
2679 switch (besr.surf_id)
2681 case 3:
2682 case 4: BytesPerUVPixel = 0;
2683 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2684 case 11:
2685 case 12: BytesPerUVPixel = 2;
2686 break;
2687 case 6: BytesPerUVPixel = 0;
2688 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2689 case 9:
2690 case 10: BytesPerUVPixel = 1;
2691 break;
2692 case 13:
2693 case 14: BytesPerUVPixel = 2;
2694 break;
2695 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2696 break;
2699 switch (besr.surf_id)
2701 case 3:
2702 case 4:
2703 case 6: HorzUVSubSample = 1;
2704 break;
2705 case 9: HorzUVSubSample = 4;
2706 break;
2707 case 10:
2708 case 11:
2709 case 12:
2710 case 13:
2711 case 14: HorzUVSubSample = 2;
2712 break;
2713 default: HorzUVSubSample = 0;/* insert debug statement here. */
2714 break;
2716 switch (besr.surf_id)
2718 case 3:
2719 case 4:
2720 case 6:
2721 case 11:
2722 case 12: VertUVSubSample = 1;
2723 break;
2724 case 9: VertUVSubSample = 4;
2725 break;
2726 case 10:
2727 case 13:
2728 case 14: VertUVSubSample = 2;
2729 break;
2730 default: VertUVSubSample = 0;/* insert debug statment here. */
2731 break;
2733 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2734 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2735 LeftPixel = config->src.x;
2736 RightPixel = config->src.w-1;
2737 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2738 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2739 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2740 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2741 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2742 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2743 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2744 SourceWidthInPixels = (int)(config->src.w + 1);
2745 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2747 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2748 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2749 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2750 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2751 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2752 MemWordsInBytes) + 1);
2754 switch (besr.surf_id)
2756 case 9:
2757 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2759 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2761 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2763 DisallowFourTapVertFiltering = 1;
2766 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2768 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2770 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2772 DisallowFourTapUVVertFiltering = 1;
2775 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2777 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2779 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2781 DisallowFourTapUVVertFiltering = 1;
2783 break;
2784 case 13:
2785 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2787 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2789 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2791 DisallowFourTapVertFiltering = 1;
2794 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2796 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2798 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2800 DisallowFourTapUVVertFiltering = 1;
2802 break;
2803 case 3:
2804 case 4:
2805 case 6:
2806 case 11:
2807 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2809 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2811 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2813 DisallowFourTapVertFiltering = 1;
2815 break;
2816 default: /* insert debug statement here. */
2817 break;
2819 dest_w = config->dest.w;
2820 dest_h = config->dest.h;
2821 if(radeon_is_dbl_scan()) dest_h *= 2;
2822 besr.dest_bpp = radeon_vid_get_dbpp();
2823 besr.fourcc = config->fourcc;
2824 if(radeon_is_interlace()) interlace_factor = 2;
2825 else interlace_factor = 1;
2826 /* TODO: must be checked in doublescan mode!!! */
2827 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2829 /* Force the overlay clock on for integrated chips */
2830 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2832 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2833 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2834 V_scale_ratio = (double)(dest_h+1)/src_h;
2835 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2837 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2838 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2840 else
2841 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2843 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2844 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2846 else
2848 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2849 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2851 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2852 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2853 CRT_V_INC = besr.v_inc/interlace_factor;
2854 besr.v_inc <<= 8;
2856 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2857 int P1GroupSize = 0;
2858 int P23GroupSize;
2859 int P1StepSize = 0;
2860 int P23StepSize = 0;
2862 Calc_H_INC_STEP_BY(
2863 besr.surf_id,
2864 H_scale_ratio,
2865 DisallowFourTapVertFiltering,
2866 DisallowFourTapUVVertFiltering,
2867 &val_OV0_P1_H_INC,
2868 &val_OV0_P1_H_STEP_BY,
2869 &val_OV0_P23_H_INC,
2870 &val_OV0_P23_H_STEP_BY,
2871 &P1GroupSize,
2872 &P1StepSize,
2873 &P23StepSize);
2875 if(H_scale_ratio > MinHScaleHard)
2877 h_inc = (src_w << 12) / dest_w;
2878 besr.step_by = 0x0101;
2879 switch (besr.surf_id)
2881 case 3:
2882 case 4:
2883 case 6:
2884 besr.h_inc = (h_inc)|(h_inc<<16);
2885 break;
2886 case 9:
2887 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2888 break;
2889 default:
2890 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2891 break;
2895 P23GroupSize = 2; /* Current vaue for all modes */
2897 besr.horz_pick_nearest=0;
2898 DoNotUseMostRecentlyFetchedLine=0;
2899 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2900 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2901 besr.vert_pick_nearest = 1;
2902 else
2903 besr.vert_pick_nearest = 0;
2905 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2906 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2907 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2909 if(H_scale_ratio > MinHScaleHard)
2911 unsigned tmp;
2912 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2913 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2914 ((tmp << 12) & 0xf0000000);
2916 tmp = (top & 0x0000ffff) + 0x00018000;
2917 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2918 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2919 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2920 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2921 ((tmp << 12) & 0x70000000);
2923 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2924 besr.p23_v_accum_init = (is_420||is_410) ?
2925 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2926 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2928 else
2929 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2930 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2931 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2932 CRT_V_INC,P1GroupSize,P23GroupSize,
2933 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2934 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
2937 /* keep everything in 16.16 */
2938 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
2939 config->offsets[0] = 0;
2940 for(i=1;i<besr.vid_nbufs;i++)
2941 config->offsets[i] = config->offsets[i-1]+config->frame_size;
2942 if(is_420 || is_410 || is_400)
2944 uint32_t d1line,d2line,d3line;
2945 d1line = top*pitch;
2946 if(is_420)
2948 d2line = src_h*pitch+(d1line>>2);
2949 d3line = d2line+((src_h*pitch)>>2);
2951 else
2952 if(is_410)
2954 d2line = src_h*pitch+(d1line>>4);
2955 d3line = d2line+((src_h*pitch)>>4);
2957 else
2959 d2line = 0;
2960 d3line = 0;
2962 d1line += (left >> 16) & ~15;
2963 if(is_420)
2965 d2line += (left >> 17) & ~15;
2966 d3line += (left >> 17) & ~15;
2968 else /* is_410 */
2970 d2line += (left >> 18) & ~15;
2971 d3line += (left >> 18) & ~15;
2973 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
2974 if(is_400)
2976 config->offset.v = 0;
2977 config->offset.u = 0;
2979 else
2981 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
2982 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
2984 for(i=0;i<besr.vid_nbufs;i++)
2986 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
2987 if(is_400)
2989 besr.vid_buf_base_adrs_v[i]=0;
2990 besr.vid_buf_base_adrs_u[i]=0;
2992 else
2994 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
2996 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;
2997 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;
2999 else
3001 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;
3002 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;
3006 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3007 if(is_400)
3009 config->offset.v = 0;
3010 config->offset.u = 0;
3012 else
3014 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3015 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3018 else
3020 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3021 for(i=0;i<besr.vid_nbufs;i++)
3023 besr.vid_buf_base_adrs_y[i] =
3024 besr.vid_buf_base_adrs_u[i] =
3025 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3028 leftUV = (left >> (is_410?18:17)) & 15;
3029 left = (left >> 16) & 15;
3030 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3031 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3032 ComputeBorders(config,VertUVSubSample);
3033 besr.vid_buf_pitch0_value = pitch;
3034 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3035 /* ********************************************************* */
3036 /* ** Calculate programmable coefficients as needed */
3037 /* ********************************************************* */
3039 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3040 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3041 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3042 else
3044 FilterSetup (val_OV0_P1_H_INC);
3045 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3046 /* would like to do. For now, we let the test application decide. */
3047 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3048 if(DisallowFourTapVertFiltering)
3049 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3050 if(DisallowFourTapUVVertFiltering)
3051 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3053 return 0;
3056 static void radeon_compute_framesize(vidix_playback_t *info)
3058 unsigned pitch,awidth,dbpp;
3059 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3060 dbpp = radeon_vid_get_dbpp();
3061 switch(info->fourcc)
3063 case IMGFMT_Y800:
3064 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3065 info->frame_size = awidth*info->src.h;
3066 break;
3067 case IMGFMT_YVU9:
3068 case IMGFMT_IF09:
3069 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3070 info->frame_size = awidth*(info->src.h+info->src.h/8);
3071 break;
3072 case IMGFMT_I420:
3073 case IMGFMT_YV12:
3074 case IMGFMT_IYUV:
3075 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3076 info->frame_size = awidth*(info->src.h+info->src.h/2);
3077 break;
3078 case IMGFMT_RGB32:
3079 case IMGFMT_BGR32:
3080 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3081 info->frame_size = awidth*info->src.h;
3082 break;
3083 /* YUY2 YVYU, RGB15, RGB16 */
3084 default:
3085 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3086 info->frame_size = awidth*info->src.h;
3087 break;
3089 info->frame_size = (info->frame_size+4095)&~4095;
3092 static int radeon_config_playback(vidix_playback_t *info)
3094 unsigned rgb_size,nfr;
3095 uint32_t radeon_video_size;
3096 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3097 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3098 if(info->num_frames==1) besr.double_buff=0;
3099 else besr.double_buff=1;
3100 radeon_compute_framesize(info);
3102 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3103 nfr = info->num_frames;
3104 radeon_video_size = radeon_ram_size;
3105 for(;nfr>0; nfr--)
3107 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3108 #if !defined (RAGE128) && defined(HAVE_X11)
3109 radeon_overlay_off -= firegl_shift;
3110 #endif
3111 radeon_overlay_off &= 0xffff0000;
3112 if(radeon_overlay_off >= (int)rgb_size ) break;
3114 if(nfr <= 3)
3116 nfr = info->num_frames;
3117 for(;nfr>0; nfr--)
3119 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3120 #if !defined (RAGE128) && defined(HAVE_X11)
3121 radeon_overlay_off -= firegl_shift;
3122 #endif
3123 radeon_overlay_off &= 0xffff0000;
3124 if(radeon_overlay_off > 0) break;
3127 if(nfr <= 0) return EINVAL;
3128 info->num_frames = nfr;
3129 besr.vid_nbufs = info->num_frames;
3130 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3131 radeon_vid_init_video(info);
3132 return 0;
3135 static int radeon_playback_on(void)
3137 #ifdef RAGE128
3138 unsigned dw,dh;
3139 #endif
3140 radeon_vid_display_video();
3141 #ifdef RAGE128
3142 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3143 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3144 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3145 else radeon_vid_non_exclusive();
3146 #endif
3147 return 0;
3150 static int radeon_playback_off(void)
3152 radeon_vid_stop_video();
3153 return 0;
3156 static int radeon_frame_select(unsigned frame)
3158 uint32_t off[6];
3159 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3161 buf3-5 always should point onto second buffer for better
3162 deinterlacing and TV-in
3164 if(!besr.double_buff) return 0;
3165 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3166 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3167 off[0] = besr.vid_buf_base_adrs_y[frame];
3168 off[1] = besr.vid_buf_base_adrs_v[frame];
3169 off[2] = besr.vid_buf_base_adrs_u[frame];
3170 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3171 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3172 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3173 radeon_fifo_wait(8);
3174 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3175 radeon_engine_idle();
3176 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3177 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3178 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3179 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3180 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3181 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3182 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3183 OUTREG(OV0_REG_LOAD_CNTL, 0);
3184 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3185 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
3186 return 0;
3189 static vidix_video_eq_t equal =
3191 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3192 #ifndef RAGE128
3193 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3194 #endif
3196 0, 0, 0, 0, 0, 0, 0, 0 };
3198 static int radeon_get_eq(vidix_video_eq_t * eq)
3200 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3201 return 0;
3204 #ifndef RAGE128
3205 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3206 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3207 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3208 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3209 #define RTFHue(a) (((a)*3.1416)/1000.0)
3210 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3211 #endif
3213 static int radeon_set_eq(const vidix_video_eq_t * eq)
3215 #ifdef RAGE128
3216 int br,sat;
3217 #else
3218 int itu_space;
3219 #endif
3220 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3221 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3222 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3223 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3224 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3226 equal.red_intensity = eq->red_intensity;
3227 equal.green_intensity = eq->green_intensity;
3228 equal.blue_intensity = eq->blue_intensity;
3230 equal.flags = eq->flags;
3231 #ifdef RAGE128
3232 br = equal.brightness * 64 / 1000;
3233 if(br < -64) br = -64; if(br > 63) br = 63;
3234 sat = (equal.saturation*31 + 31000) / 2000;
3235 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3236 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3237 #else
3238 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3239 RTFCheckParam(equal.brightness);
3240 RTFCheckParam(equal.saturation);
3241 RTFCheckParam(equal.contrast);
3242 RTFCheckParam(equal.hue);
3243 RTFCheckParam(equal.red_intensity);
3244 RTFCheckParam(equal.green_intensity);
3245 RTFCheckParam(equal.blue_intensity);
3246 radeon_set_transform(RTFBrightness(equal.brightness),
3247 RTFContrast(equal.contrast),
3248 RTFSaturation(equal.saturation),
3249 RTFHue(equal.hue),
3250 RTFIntensity(equal.red_intensity),
3251 RTFIntensity(equal.green_intensity),
3252 RTFIntensity(equal.blue_intensity),
3253 itu_space);
3254 #endif
3255 return 0;
3258 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3260 unsigned sflg;
3261 switch(info->flags)
3263 default:
3264 case CFG_NON_INTERLACED:
3265 besr.deinterlace_on = 0;
3266 break;
3267 case CFG_EVEN_ODD_INTERLACING:
3268 case CFG_INTERLACED:
3269 besr.deinterlace_on = 1;
3270 besr.deinterlace_pattern = 0x900AAAAA;
3271 break;
3272 case CFG_ODD_EVEN_INTERLACING:
3273 besr.deinterlace_on = 1;
3274 besr.deinterlace_pattern = 0x00055555;
3275 break;
3276 case CFG_UNIQUE_INTERLACING:
3277 besr.deinterlace_on = 1;
3278 besr.deinterlace_pattern = info->deinterlace_pattern;
3279 break;
3281 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3282 radeon_engine_idle();
3283 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3284 radeon_fifo_wait(15);
3285 sflg = INREG(OV0_SCALE_CNTL);
3286 if(besr.deinterlace_on)
3288 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3289 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3291 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3292 OUTREG(OV0_REG_LOAD_CNTL, 0);
3293 return 0;
3296 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3298 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3299 else
3301 info->flags = CFG_UNIQUE_INTERLACING;
3302 info->deinterlace_pattern = besr.deinterlace_pattern;
3304 return 0;
3308 /* Graphic keys */
3309 static vidix_grkey_t radeon_grkey;
3311 static int set_gr_key( void )
3313 int result = 0;
3315 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3316 0x00ff0000; /* graphic alpha */
3317 if(radeon_grkey.ckey.op == CKEY_TRUE)
3319 int dbpp=radeon_vid_get_dbpp();
3320 besr.ckey_on=1;
3322 switch(dbpp)
3324 case 15:
3325 #ifndef RAGE128
3326 if((besr.chip_flags&R_100)!=R_100)
3327 besr.graphics_key_clr=
3328 ((radeon_grkey.ckey.blue &0xF8))
3329 | ((radeon_grkey.ckey.green&0xF8)<<8)
3330 | ((radeon_grkey.ckey.red &0xF8)<<16);
3331 else
3332 #endif
3333 besr.graphics_key_clr=
3334 ((radeon_grkey.ckey.blue &0xF8)>>3)
3335 | ((radeon_grkey.ckey.green&0xF8)<<2)
3336 | ((radeon_grkey.ckey.red &0xF8)<<7);
3337 break;
3338 case 16:
3339 #ifndef RAGE128
3340 /* This test may be too general/specific */
3341 if((besr.chip_flags&R_100)!=R_100)
3342 besr.graphics_key_clr=
3343 ((radeon_grkey.ckey.blue &0xF8))
3344 | ((radeon_grkey.ckey.green&0xFC)<<8)
3345 | ((radeon_grkey.ckey.red &0xF8)<<16);
3346 else
3347 #endif
3348 besr.graphics_key_clr=
3349 ((radeon_grkey.ckey.blue &0xF8)>>3)
3350 | ((radeon_grkey.ckey.green&0xFC)<<3)
3351 | ((radeon_grkey.ckey.red &0xF8)<<8);
3352 break;
3353 case 24:
3354 case 32:
3355 besr.graphics_key_clr=
3356 ((radeon_grkey.ckey.blue &0xFF))
3357 | ((radeon_grkey.ckey.green&0xFF)<<8)
3358 | ((radeon_grkey.ckey.red &0xFF)<<16);
3359 break;
3360 default:
3361 besr.ckey_on=0;
3362 besr.graphics_key_msk=0;
3363 besr.graphics_key_clr=0;
3365 #ifdef RAGE128
3366 besr.graphics_key_msk=(1<<dbpp)-1;
3367 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3368 #else
3369 besr.graphics_key_msk=besr.graphics_key_clr;
3370 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3371 #endif
3373 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3375 int dbpp=radeon_vid_get_dbpp();
3376 besr.ckey_on=1;
3378 switch(dbpp)
3380 case 32:
3381 besr.ckey_on=1;
3382 besr.graphics_key_msk=0;
3383 besr.graphics_key_clr=0;
3384 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3385 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3386 0x00ff0000 | /* graphic alpha */
3387 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3388 break;
3389 default:
3390 besr.ckey_on=0;
3391 besr.graphics_key_msk=0;
3392 besr.graphics_key_clr=0;
3393 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3394 result = 1;
3397 else
3399 besr.ckey_on=0;
3400 besr.graphics_key_msk=0;
3401 besr.graphics_key_clr=0;
3402 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3404 radeon_fifo_wait(3);
3405 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3406 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3407 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3408 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3409 return result;
3412 static int radeon_get_gkey(vidix_grkey_t *grkey)
3414 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3415 return(0);
3418 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3420 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3421 return (set_gr_key());
3424 #ifdef RAGE128
3425 VDXDriver rage128_drv = {
3426 "rage128",
3427 #else
3428 VDXDriver radeon_drv = {
3429 "radeon",
3430 #endif
3431 NULL,
3433 .probe = radeon_probe,
3434 .get_caps = radeon_get_caps,
3435 .query_fourcc = radeon_query_fourcc,
3436 .init = radeon_init,
3437 .destroy = radeon_destroy,
3438 .config_playback = radeon_config_playback,
3439 .playback_on = radeon_playback_on,
3440 .playback_off = radeon_playback_off,
3441 .frame_sel = radeon_frame_select,
3442 .get_eq = radeon_get_eq,
3443 .set_eq = radeon_set_eq,
3444 .get_deint = radeon_playback_get_deint,
3445 .set_deint = radeon_playback_set_deint,
3446 .get_gkey = radeon_get_gkey,
3447 .set_gkey = radeon_set_gkey,