Make dhasetup more verbose based on code by
[mplayer/greg.git] / vidix / radeon_vid.c
blobf8a8695d53938af155ee040549943f78cf518b7b
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 0x00000003
276 #define R_200 0x00000004
277 #define R_250 0x00000005
278 #define R_280 0x00000006
279 #define R_300 0x00000007
280 #define R_350 0x00000008
281 #define R_370 0x00000010
282 #define R_380 0x00000020
283 #define R_420 0x00000040
284 #define R_430 0x00000080
285 #define R_480 0x00000100
286 #define R_520 0x00000200
287 #define R_530 0x00000400
288 #define R_580 0x00000800
289 #define R_OVL_SHIFT 0x01000000
290 #define R_INTEGRATED 0x02000000
291 #define R_PCIE 0x04000000
293 typedef struct ati_card_ids_s
295 unsigned short id;
296 unsigned flags;
297 }ati_card_ids_t;
299 static const ati_card_ids_t ati_card_ids[] =
301 #ifdef RAGE128
303 This driver should be compatible with Rage128 (pro) chips.
304 (include adaptive deinterlacing!!!).
305 Moreover: the same logic can be used with Mach64 chips.
306 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
307 but they are incompatible by i/o ports. So if enthusiasts will want
308 then they can redefine OUTREG and INREG macros and redefine OV0_*
309 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
310 fourccs (422 and 420 formats only).
312 /* Rage128 Pro GL */
313 { DEVICE_ATI_RAGE_128_PA_PRO, 0 },
314 { DEVICE_ATI_RAGE_128_PB_PRO, 0 },
315 { DEVICE_ATI_RAGE_128_PC_PRO, 0 },
316 { DEVICE_ATI_RAGE_128_PD_PRO, 0 },
317 { DEVICE_ATI_RAGE_128_PE_PRO, 0 },
318 { DEVICE_ATI_RAGE_128_PF_PRO, 0 },
319 /* Rage128 Pro VR */
320 { DEVICE_ATI_RAGE_128_PG_PRO, 0 },
321 { DEVICE_ATI_RAGE_128_PH_PRO, 0 },
322 { DEVICE_ATI_RAGE_128_PI_PRO, 0 },
323 { DEVICE_ATI_RAGE_128_PJ_PRO, 0 },
324 { DEVICE_ATI_RAGE_128_PK_PRO, 0 },
325 { DEVICE_ATI_RAGE_128_PL_PRO, 0 },
326 { DEVICE_ATI_RAGE_128_PM_PRO, 0 },
327 { DEVICE_ATI_RAGE_128_PN_PRO, 0 },
328 { DEVICE_ATI_RAGE_128_PO_PRO, 0 },
329 { DEVICE_ATI_RAGE_128_PP_PRO, 0 },
330 { DEVICE_ATI_RAGE_128_PQ_PRO, 0 },
331 { DEVICE_ATI_RAGE_128_PR_PRO, 0 },
332 { DEVICE_ATI_RAGE_128_PS_PRO, 0 },
333 { DEVICE_ATI_RAGE_128_PT_PRO, 0 },
334 { DEVICE_ATI_RAGE_128_PU_PRO, 0 },
335 { DEVICE_ATI_RAGE_128_PV_PRO, 0 },
336 { DEVICE_ATI_RAGE_128_PW_PRO, 0 },
337 { DEVICE_ATI_RAGE_128_PX_PRO, 0 },
338 /* Rage128 GL */
339 { DEVICE_ATI_RAGE_128_RE_SG, 0 },
340 { DEVICE_ATI_RAGE_128_RF_SG, 0 },
341 { DEVICE_ATI_RAGE_128_RG, 0 },
342 { DEVICE_ATI_RAGE_128_RK_VR, 0 },
343 { DEVICE_ATI_RAGE_128_RL_VR, 0 },
344 { DEVICE_ATI_RAGE_128_SE_4X, 0 },
345 { DEVICE_ATI_RAGE_128_SF_4X, 0 },
346 { DEVICE_ATI_RAGE_128_SG_4X, 0 },
347 { DEVICE_ATI_RAGE_128_SH, 0 },
348 { DEVICE_ATI_RAGE_128_SK_4X, 0 },
349 { DEVICE_ATI_RAGE_128_SL_4X, 0 },
350 { DEVICE_ATI_RAGE_128_SM_4X, 0 },
351 { DEVICE_ATI_RAGE_128_4X, 0 },
352 { DEVICE_ATI_RAGE_128_PRO, 0 },
353 { DEVICE_ATI_RAGE_128_PRO2, 0 },
354 { DEVICE_ATI_RAGE_128_PRO3, 0 },
355 /* these seem to be based on rage 128 instead of mach64 */
356 { DEVICE_ATI_RAGE_MOBILITY_M3, 0 },
357 { DEVICE_ATI_RAGE_MOBILITY_M32, 0 },
358 #else
359 /* Radeon1 (indeed: Rage 256 Pro ;) */
360 { DEVICE_ATI_RADEON_R100_QD, R_100|R_OVL_SHIFT },
361 { DEVICE_ATI_RADEON_R100_QE, R_100|R_OVL_SHIFT },
362 { DEVICE_ATI_RADEON_R100_QF, R_100|R_OVL_SHIFT },
363 { DEVICE_ATI_RADEON_R100_QG, R_100|R_OVL_SHIFT },
364 { DEVICE_ATI_RADEON_IGP_320, R_150|R_OVL_SHIFT|R_INTEGRATED },
365 { DEVICE_ATI_RADEON_MOBILITY_U1, R_150|R_OVL_SHIFT|R_INTEGRATED },
366 { DEVICE_ATI_RADEON_RV100_QY, R_120|R_OVL_SHIFT },
367 { DEVICE_ATI_RADEON_RV100_QZ, R_120|R_OVL_SHIFT },
368 { DEVICE_ATI_RADEON_MOBILITY_M7, R_150|R_OVL_SHIFT },
369 { DEVICE_ATI_RADEON_RV200_LX, R_150|R_OVL_SHIFT },
370 { DEVICE_ATI_RADEON_MOBILITY_M6, R_120|R_OVL_SHIFT },
371 { DEVICE_ATI_RADEON_MOBILITY_M62, R_120|R_OVL_SHIFT },
372 /* Radeon2 (indeed: Rage 512 Pro ;) */
373 { DEVICE_ATI_R200_BB_RADEON, R_200 },
374 { DEVICE_ATI_R200_BC_RADEON, R_200 },
375 { DEVICE_ATI_RADEON_R200_QH, R_200 },
376 { DEVICE_ATI_RADEON_R200_QI, R_200 },
377 { DEVICE_ATI_RADEON_R200_QJ, R_200 },
378 { DEVICE_ATI_RADEON_R200_QK, R_200 },
379 { DEVICE_ATI_RADEON_R200_QL, R_200 },
380 { DEVICE_ATI_RADEON_R200_QM, R_200 },
381 { DEVICE_ATI_RADEON_R200_QN, R_200 },
382 { DEVICE_ATI_RADEON_R200_QO, R_200 },
383 { DEVICE_ATI_RADEON_R200_QH2, R_200 },
384 { DEVICE_ATI_RADEON_R200_QI2, R_200 },
385 { DEVICE_ATI_RADEON_R200_QJ2, R_200 },
386 { DEVICE_ATI_RADEON_R200_QK2, R_200 },
387 { DEVICE_ATI_RADEON_R200_QL2, R_200 },
388 { DEVICE_ATI_RADEON_RV200_QW, R_150|R_OVL_SHIFT },
389 { DEVICE_ATI_RADEON_RV200_QX, R_150|R_OVL_SHIFT },
390 { DEVICE_ATI_RADEON_IGP330_340_350,R_200|R_INTEGRATED },
391 { DEVICE_ATI_RADEON_IGP_330M_340M_350M,R_200|R_INTEGRATED },
392 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
393 { DEVICE_ATI_RADEON_7000_IGP, R_250|R_OVL_SHIFT|R_INTEGRATED },
394 { DEVICE_ATI_RADEON_MOBILITY_7000, R_250|R_OVL_SHIFT|R_INTEGRATED },
395 { DEVICE_ATI_RADEON_RV250_ID, R_250|R_OVL_SHIFT },
396 { DEVICE_ATI_RADEON_RV250_IE, R_250|R_OVL_SHIFT },
397 { DEVICE_ATI_RADEON_RV250_IF, R_250|R_OVL_SHIFT },
398 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
399 { DEVICE_ATI_RADEON_R250_LD, R_250|R_OVL_SHIFT },
400 { DEVICE_ATI_RADEON_R250_LE, R_250|R_OVL_SHIFT },
401 { DEVICE_ATI_RADEON_R250_MOBILITY, R_250|R_OVL_SHIFT },
402 { DEVICE_ATI_RADEON_R250_LG, R_250|R_OVL_SHIFT },
403 { DEVICE_ATI_RV250_RADEON_9000, R_250|R_OVL_SHIFT },
404 { DEVICE_ATI_RADEON_RV250_RADEON2, R_250|R_OVL_SHIFT },
405 { DEVICE_ATI_RV280_RADEON_9200, R_280 },
406 { DEVICE_ATI_RV280_RADEON_92002, R_280 },
407 { DEVICE_ATI_RV280_RADEON_92003, R_280 },
408 { DEVICE_ATI_RV280_RADEON_92004, R_280 },
409 { DEVICE_ATI_RV280_RADEON_92005, R_280 },
410 { DEVICE_ATI_RV280_RADEON_92006, R_280 },
411 { DEVICE_ATI_RV280_RADEON_92007, R_280 },
412 { DEVICE_ATI_M9_5C61_RADEON, R_280 },
413 { DEVICE_ATI_M9_5C63_RADEON, R_280 },
414 /* Radeon3 (indeed: Rage 1024 Pro ;) */
415 { DEVICE_ATI_R300_AG_FIREGL, R_300 },
416 { DEVICE_ATI_RADEON_R300_ND, R_300 },
417 { DEVICE_ATI_RADEON_R300_NE, R_300 },
418 { DEVICE_ATI_RADEON_R300_NG, R_300 },
419 { DEVICE_ATI_R300_AD_RADEON, R_300 },
420 { DEVICE_ATI_R300_AE_RADEON, R_300 },
421 { DEVICE_ATI_R300_AF_RADEON, R_300 },
422 { DEVICE_ATI_RADEON_9100_IGP2, R_300|R_OVL_SHIFT|R_INTEGRATED },
423 { DEVICE_ATI_RS300M_AGP_RADEON, R_300|R_INTEGRATED },
424 { DEVICE_ATI_RS482_RADEON_XPRESS, R_350|R_INTEGRATED },
425 { DEVICE_ATI_R350_AH_RADEON, R_350 },
426 { DEVICE_ATI_R350_AI_RADEON, R_350 },
427 { DEVICE_ATI_R350_AJ_RADEON, R_350 },
428 { DEVICE_ATI_R350_AK_FIRE, R_350 },
429 { DEVICE_ATI_RADEON_R350_RADEON2, R_350 },
430 { DEVICE_ATI_RADEON_R350_RADEON3, R_350 },
431 { DEVICE_ATI_RV350_NJ_RADEON, R_350 },
432 { DEVICE_ATI_R350_NK_FIRE, R_350 },
433 { DEVICE_ATI_RV350_AP_RADEON, R_350 },
434 { DEVICE_ATI_RV350_AQ_RADEON, R_350 },
435 { DEVICE_ATI_RV350_AR_RADEON, R_350 },
436 { DEVICE_ATI_RV350_AS_RADEON, R_350 },
437 { DEVICE_ATI_RV350_AT_FIRE, R_350 },
438 { DEVICE_ATI_RV350_AU_FIRE, R_350 },
439 { DEVICE_ATI_RV350_AV_FIRE, R_350 },
440 { DEVICE_ATI_RV350_AW_FIRE, R_350 },
441 { DEVICE_ATI_RV350_MOBILITY_RADEON, R_350 },
442 { DEVICE_ATI_RV350_NF_RADEON, R_300 },
443 { DEVICE_ATI_RV350_NJ_RADEON, R_300 },
444 { DEVICE_ATI_RV350_AS_RADEON2, R_350 },
445 { DEVICE_ATI_M10_NQ_RADEON, R_350 },
446 { DEVICE_ATI_M10_NQ_RADEON2, R_350 },
447 { DEVICE_ATI_RV350_MOBILITY_RADEON2, R_350 },
448 { DEVICE_ATI_M10_NS_RADEON, R_350 },
449 { DEVICE_ATI_M10_NT_FIREGL, R_350 },
450 { DEVICE_ATI_M11_NV_FIREGL, R_350 },
451 { DEVICE_ATI_RV370_5B60_RADEON, R_370|R_PCIE },
452 { DEVICE_ATI_RV370_SAPPHIRE_X550, R_370 },
453 { DEVICE_ATI_RV370_5B64_FIREGL, R_370|R_PCIE },
454 { DEVICE_ATI_RV370_5B65_FIREGL, R_370|R_PCIE },
455 { DEVICE_ATI_M24_1P_RADEON, R_370 },
456 { DEVICE_ATI_M22_RADEON_MOBILITY, R_370 },
457 { DEVICE_ATI_M24_1T_FIREGL, R_370 },
458 { DEVICE_ATI_M24_RADEON_MOBILITY, R_370 },
459 { DEVICE_ATI_RV370_RADEON_X300SE, R_370 },
460 { DEVICE_ATI_RV370_SECONDARY_SAPPHIRE, R_370 },
461 { DEVICE_ATI_RV370_5B64_FIREGL2, R_370 },
462 { DEVICE_ATI_RV380_0X3E50_RADEON, R_380|R_PCIE },
463 { DEVICE_ATI_RV380_0X3E54_FIREGL, R_380|R_PCIE },
464 { DEVICE_ATI_RV380_RADEON_X600, R_380|R_PCIE },
465 { DEVICE_ATI_RV380_RADEON_X6002, R_380 },
466 { DEVICE_ATI_RV380_RADEON_X6003, R_380 },
467 { DEVICE_ATI_RV410_FIREGL_V5000, R_420 },
468 { DEVICE_ATI_RV410_FIREGL_V3300, R_420 },
469 { DEVICE_ATI_RV410_RADEON_X700XT, R_420 },
470 { DEVICE_ATI_RV410_RADEON_X700, R_420|R_PCIE },
471 { DEVICE_ATI_RV410_RADEON_X700SE, R_420 },
472 { DEVICE_ATI_RV410_RADEON_X7002, R_420|R_PCIE },
473 { DEVICE_ATI_RV410_RADEON_X7003, R_420 },
474 { DEVICE_ATI_RV410_RADEON_X7004, R_420|R_PCIE },
475 { DEVICE_ATI_RV410_RADEON_X7005, R_420|R_PCIE },
476 { DEVICE_ATI_M26_MOBILITY_FIREGL, R_420 },
477 { DEVICE_ATI_M26_MOBILITY_FIREGL2, R_420 },
478 { DEVICE_ATI_M26_RADEON_MOBILITY, R_420 },
479 { DEVICE_ATI_M26_RADEON_MOBILITY2, R_420 },
480 { DEVICE_ATI_RADEON_MOBILITY_X700, R_420 },
481 { DEVICE_ATI_R420_JH_RADEON, R_420|R_PCIE },
482 { DEVICE_ATI_R420_JI_RADEON, R_420|R_PCIE },
483 { DEVICE_ATI_R420_JJ_RADEON, R_420|R_PCIE },
484 { DEVICE_ATI_R420_JK_RADEON, R_420|R_PCIE },
485 { DEVICE_ATI_R420_JL_RADEON, R_420|R_PCIE },
486 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
487 { DEVICE_ATI_M18_JN_RADEON, R_420|R_PCIE },
488 { DEVICE_ATI_R420_JP_RADEON, R_420|R_PCIE },
489 { DEVICE_ATI_R420_RADEON_X800, R_420|R_PCIE },
490 { DEVICE_ATI_R420_RADEON_X8002, R_420|R_PCIE },
491 { DEVICE_ATI_R420_RADEON_X8003, R_420|R_PCIE },
492 { DEVICE_ATI_R420_RADEON_X8004, R_420|R_PCIE },
493 { DEVICE_ATI_R420_RADEON_X8005, R_420|R_PCIE },
494 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
495 { DEVICE_ATI_R423_5F57_RADEON, R_420|R_PCIE },
496 { DEVICE_ATI_R423_5F57_RADEON2, R_420|R_PCIE },
497 { DEVICE_ATI_R423_UH_RADEON, R_420|R_PCIE },
498 { DEVICE_ATI_R423_UI_RADEON, R_420|R_PCIE },
499 { DEVICE_ATI_R423_UJ_RADEON, R_420|R_PCIE },
500 { DEVICE_ATI_R423_UK_RADEON, R_420|R_PCIE },
501 { DEVICE_ATI_R423_FIRE_GL, R_420|R_PCIE },
502 { DEVICE_ATI_R423_UQ_FIREGL, R_420|R_PCIE },
503 { DEVICE_ATI_R423_UR_FIREGL, R_420|R_PCIE },
504 { DEVICE_ATI_R423_UT_FIREGL, R_420|R_PCIE },
505 { DEVICE_ATI_R423_UI_RADEON2, R_420|R_PCIE },
506 { DEVICE_ATI_R423GL_SE_ATI_FIREGL, R_420|R_PCIE },
507 { DEVICE_ATI_R423_RADEON_X800XT, R_420|R_PCIE },
508 { DEVICE_ATI_RADEON_R423_UK, R_420|R_PCIE },
509 { DEVICE_ATI_M28_RADEON_MOBILITY, R_420 },
510 { DEVICE_ATI_M28_MOBILITY_FIREGL, R_420 },
511 { DEVICE_ATI_MOBILITY_RADEON_X800, R_420 },
512 { DEVICE_ATI_R430_RADEON_X800, R_430|R_PCIE },
513 { DEVICE_ATI_R430_RADEON_X8002, R_430|R_PCIE },
514 { DEVICE_ATI_R430_RADEON_X8003, R_430|R_PCIE },
515 { DEVICE_ATI_R430_RADEON_X8004, R_430|R_PCIE },
516 { DEVICE_ATI_R480_RADEON_X800, R_480 },
517 { DEVICE_ATI_R480_RADEON_X8002, R_480 },
518 { DEVICE_ATI_R480_RADEON_X850XT, R_480 },
519 { DEVICE_ATI_R480_RADEON_X850PRO, R_480 },
520 { DEVICE_ATI_R481_RADEON_X850XT_PE, R_480|R_PCIE },
521 { DEVICE_ATI_R480_RADEON_X850XT2, R_480 },
522 { DEVICE_ATI_R480_RADEON_X850PRO2, R_480 },
523 { DEVICE_ATI_R481_RADEON_X850XT_PE2, R_480|R_PCIE },
524 { DEVICE_ATI_R480_RADEON_X850XT3, R_480|R_PCIE },
525 { DEVICE_ATI_R480_RADEON_X850XT4, R_480|R_PCIE },
526 { DEVICE_ATI_R480_RADEON_X850XT5, R_480|R_PCIE },
527 { DEVICE_ATI_R480_RADEON_X850XT6, R_480|R_PCIE },
528 { DEVICE_ATI_R520_FIREGL, R_520 },
529 { DEVICE_ATI_R520_GL_ATI, R_520 },
530 { DEVICE_ATI_R520_GL_ATI2, R_520 },
531 { DEVICE_ATI_R520_RADEON_X1800, R_520 },
532 { DEVICE_ATI_R520_RADEON_X18002, R_520 },
533 { DEVICE_ATI_R520_RADEON_X18003, R_520 },
534 { DEVICE_ATI_R520_RADEON_X18004, R_520 },
535 { DEVICE_ATI_R520_RADEON_X18005, R_520 },
536 { DEVICE_ATI_R520_RADEON_X18006, R_520 },
537 { DEVICE_ATI_R520_RADEON_X18007, R_520 },
538 { DEVICE_ATI_M58_RADEON_MOBILITY, R_520 },
539 { DEVICE_ATI_M58_RADEON_MOBILITY2, R_520 },
540 { DEVICE_ATI_M58_MOBILITY_FIREGL, R_520 },
541 { DEVICE_ATI_M58_MOBILITY_FIREGL2, R_520 },
542 { DEVICE_ATI_RV515_RADEON_X1600, R_520 },
543 { DEVICE_ATI_RV515_RADEON_X1300, R_520 },
544 { DEVICE_ATI_RV515_RADEON_X13002, R_520 },
545 { DEVICE_ATI_RV515_RADEON_X13003, R_520 },
546 { DEVICE_ATI_RV515_RADEON_X13004, R_520 },
547 { DEVICE_ATI_RV515_RADEON_X13005, R_520 },
548 { DEVICE_ATI_RV515_RADEON_X13006, R_520 },
549 { DEVICE_ATI_RV515_RADEON_X13007, R_520 },
550 { DEVICE_ATI_RV515_GL_ATI, R_520 },
551 { DEVICE_ATI_RV515_GL_ATI2, R_520 },
552 { DEVICE_ATI_RADEON_MOBILITY_X1400, R_520 },
553 { DEVICE_ATI_M52_ATI_MOBILITY, R_520 },
554 { DEVICE_ATI_M52_ATI_MOBILITY2, R_520 },
555 { DEVICE_ATI_M52_ATI_MOBILITY3, R_520 },
556 { DEVICE_ATI_M52_ATI_MOBILITY4, R_520 },
557 { DEVICE_ATI_RV516_RADEON_X1300, R_520 },
558 { DEVICE_ATI_RV516_RADEON_X13002, R_520 },
559 { DEVICE_ATI_RV516_XT_RADEON, R_520 },
560 { DEVICE_ATI_RV516_XT_RADEON2, R_520 },
561 { DEVICE_ATI_RV530_RADEON_X1600, R_520 },
562 { DEVICE_ATI_RV530_RADEON_X16002, R_520 },
563 { DEVICE_ATI_M56GL_ATI_MOBILITY, R_520 },
564 { DEVICE_ATI_M56P_RADEON_MOBILITY, R_520 },
565 { DEVICE_ATI_M66_P_ATI_MOBILITY, R_520 },
566 { DEVICE_ATI_M66_XT_ATI_MOBILITY, R_520 },
567 { DEVICE_ATI_RV530LE_RADEON_X1600, R_520 },
568 { DEVICE_ATI_RV530LE_RADEON_X16002, R_520 },
569 { DEVICE_ATI_RV530LE_RADEON_X16003, R_520 },
570 { DEVICE_ATI_RV530_RADEON_X16003, R_520 },
571 { DEVICE_ATI_RV530_RADEON_X16004, R_520 },
572 { DEVICE_ATI_R580_RADEON_X1900, R_520 },
573 { DEVICE_ATI_R580_RADEON_X19002, R_520 },
574 { DEVICE_ATI_R580_RADEON_X19003, R_520 },
575 { DEVICE_ATI_R580_RADEON_X19004, R_520 },
576 { DEVICE_ATI_R580_RADEON_X19005, R_520 },
577 { DEVICE_ATI_R580_RADEON_X19006, R_520 },
578 { DEVICE_ATI_R580_RADEON_X19007, R_520 },
579 { DEVICE_ATI_R580_RADEON_X19008, R_520 },
580 { DEVICE_ATI_R580_RADEON_X19009, R_520 },
581 { DEVICE_ATI_R580_RADEON_X190010, R_520 },
582 { DEVICE_ATI_R580_RADEON_X190011, R_520 },
583 { DEVICE_ATI_R580_RADEON_X190012, R_520 },
584 { DEVICE_ATI_R580_RADEON_X190013, R_520 },
585 { DEVICE_ATI_R580_RADEON_X190014, R_520 },
586 { DEVICE_ATI_R580_RADEON_X190015, R_520 },
587 { DEVICE_ATI_R580_FIREGL_V7300_V7350, R_520 },
588 { DEVICE_ATI_R580_FIREGL_V7300_V73502, R_520 },
589 #endif
593 static void * radeon_mmio_base = 0;
594 static void * radeon_mem_base = 0;
595 static int32_t radeon_overlay_off = 0;
596 static uint32_t radeon_ram_size = 0;
598 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
599 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
601 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr)
602 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr,val)
603 static inline uint32_t INREG (uint32_t addr) {
604 uint32_t tmp = GETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr);
605 return le2me_32(tmp);
607 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr,le2me_32(val))
608 #define OUTREGP(addr,val,mask) \
609 do { \
610 unsigned int _tmp = INREG(addr); \
611 _tmp &= (mask); \
612 _tmp |= (val); \
613 OUTREG(addr, _tmp); \
614 } while (0)
616 static __inline__ uint32_t INPLL(uint32_t addr)
618 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f);
619 return (INREG(CLOCK_CNTL_DATA));
622 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \
623 OUTREG(CLOCK_CNTL_DATA, val)
624 #define OUTPLLP(addr,val,mask) \
625 do { \
626 unsigned int _tmp = INPLL(addr); \
627 _tmp &= (mask); \
628 _tmp |= (val); \
629 OUTPLL(addr, _tmp); \
630 } while (0)
632 #ifndef RAGE128
633 enum radeon_montype
635 MT_NONE,
636 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */
637 MT_LCD, /* Liquid Crystal Display */
638 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */
639 MT_CTV, /* Composite TV out (not in VE) */
640 MT_STV /* S-Video TV out (probably in VE only) */
643 typedef struct radeon_info_s
645 int hasCRTC2;
646 int crtDispType;
647 int dviDispType;
648 }rinfo_t;
650 static rinfo_t rinfo;
652 static char * GET_MON_NAME(int type)
654 char *pret;
655 switch(type)
657 case MT_NONE: pret = "no"; break;
658 case MT_CRT: pret = "CRT"; break;
659 case MT_DFP: pret = "DFP"; break;
660 case MT_LCD: pret = "LCD"; break;
661 case MT_CTV: pret = "CTV"; break;
662 case MT_STV: pret = "STV"; break;
663 default: pret = "Unknown";
665 return pret;
668 static void radeon_get_moninfo (rinfo_t *rinfo)
670 unsigned int tmp;
672 tmp = INREG(RADEON_BIOS_4_SCRATCH);
674 if (rinfo->hasCRTC2) {
675 /* primary DVI port */
676 if (tmp & 0x08)
677 rinfo->dviDispType = MT_DFP;
678 else if (tmp & 0x4)
679 rinfo->dviDispType = MT_LCD;
680 else if (tmp & 0x200)
681 rinfo->dviDispType = MT_CRT;
682 else if (tmp & 0x10)
683 rinfo->dviDispType = MT_CTV;
684 else if (tmp & 0x20)
685 rinfo->dviDispType = MT_STV;
687 /* secondary CRT port */
688 if (tmp & 0x2)
689 rinfo->crtDispType = MT_CRT;
690 else if (tmp & 0x800)
691 rinfo->crtDispType = MT_DFP;
692 else if (tmp & 0x400)
693 rinfo->crtDispType = MT_LCD;
694 else if (tmp & 0x1000)
695 rinfo->crtDispType = MT_CTV;
696 else if (tmp & 0x2000)
697 rinfo->crtDispType = MT_STV;
698 } else {
699 rinfo->dviDispType = MT_NONE;
701 tmp = INREG(FP_GEN_CNTL);
703 if (tmp & FP_EN_TMDS)
704 rinfo->crtDispType = MT_DFP;
705 else
706 rinfo->crtDispType = MT_CRT;
709 #endif
711 static uint32_t radeon_vid_get_dbpp( void )
713 uint32_t dbpp,retval;
714 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF;
715 switch(dbpp)
717 case DST_8BPP: retval = 8; break;
718 case DST_15BPP: retval = 15; break;
719 case DST_16BPP: retval = 16; break;
720 case DST_24BPP: retval = 24; break;
721 default: retval=32; break;
723 return retval;
726 static int radeon_is_dbl_scan( void )
728 return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN;
731 static int radeon_is_interlace( void )
733 return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN;
736 static uint32_t radeon_get_xres( void )
738 uint32_t xres,h_total;
739 #ifndef RAGE128
740 if(rinfo.hasCRTC2 &&
741 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
742 h_total = INREG(CRTC2_H_TOTAL_DISP);
743 else
744 #endif
745 h_total = INREG(CRTC_H_TOTAL_DISP);
746 xres = (h_total >> 16) & 0xffff;
747 return (xres + 1)*8;
750 static uint32_t radeon_get_yres( void )
752 uint32_t yres,v_total;
753 #ifndef RAGE128
754 if(rinfo.hasCRTC2 &&
755 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
756 v_total = INREG(CRTC2_V_TOTAL_DISP);
757 else
758 #endif
759 v_total = INREG(CRTC_V_TOTAL_DISP);
760 yres = (v_total >> 16) & 0xffff;
761 return yres + 1;
764 static void radeon_wait_vsync(void)
766 int i;
768 OUTREG(GEN_INT_STATUS, VSYNC_INT_AK);
769 for (i = 0; i < 2000000; i++)
771 if (INREG(GEN_INT_STATUS) & VSYNC_INT) break;
775 #ifdef RAGE128
776 static void _radeon_engine_idle(void);
777 static void _radeon_fifo_wait(unsigned);
778 #define radeon_engine_idle() _radeon_engine_idle()
779 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
780 /* Flush all dirty data in the Pixel Cache to memory. */
781 static __inline__ void radeon_engine_flush ( void )
783 unsigned i;
785 OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL);
786 for (i = 0; i < 2000000; i++) {
787 if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break;
791 /* Reset graphics card to known state. */
792 static void radeon_engine_reset( void )
794 uint32_t clock_cntl_index;
795 uint32_t mclk_cntl;
796 uint32_t gen_reset_cntl;
798 radeon_engine_flush();
800 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
801 mclk_cntl = INPLL(MCLK_CNTL);
803 OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP);
805 gen_reset_cntl = INREG(GEN_RESET_CNTL);
807 OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
808 INREG(GEN_RESET_CNTL);
809 OUTREG(GEN_RESET_CNTL,
810 gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI));
811 INREG(GEN_RESET_CNTL);
813 OUTPLL(MCLK_CNTL, mclk_cntl);
814 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
815 OUTREG(GEN_RESET_CNTL, gen_reset_cntl);
817 #else
819 static __inline__ void radeon_engine_flush ( void )
821 int i;
823 /* initiate flush */
824 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
825 ~RB2D_DC_FLUSH_ALL);
827 for (i=0; i < 2000000; i++) {
828 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
829 break;
833 static void _radeon_engine_idle(void);
834 static void _radeon_fifo_wait(unsigned);
835 #define radeon_engine_idle() _radeon_engine_idle()
836 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
838 static void radeon_engine_reset( void )
840 uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
842 radeon_engine_flush ();
844 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
845 mclk_cntl = INPLL(MCLK_CNTL);
847 OUTPLL(MCLK_CNTL, (mclk_cntl |
848 FORCEON_MCLKA |
849 FORCEON_MCLKB |
850 FORCEON_YCLKA |
851 FORCEON_YCLKB |
852 FORCEON_MC |
853 FORCEON_AIC));
854 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
856 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
857 SOFT_RESET_CP |
858 SOFT_RESET_HI |
859 SOFT_RESET_SE |
860 SOFT_RESET_RE |
861 SOFT_RESET_PP |
862 SOFT_RESET_E2 |
863 SOFT_RESET_RB |
864 SOFT_RESET_HDP);
865 INREG(RBBM_SOFT_RESET);
866 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t)
867 ~(SOFT_RESET_CP |
868 SOFT_RESET_HI |
869 SOFT_RESET_SE |
870 SOFT_RESET_RE |
871 SOFT_RESET_PP |
872 SOFT_RESET_E2 |
873 SOFT_RESET_RB |
874 SOFT_RESET_HDP));
875 INREG(RBBM_SOFT_RESET);
877 OUTPLL(MCLK_CNTL, mclk_cntl);
878 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
879 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
881 return;
883 #endif
884 static void radeon_engine_restore( void )
886 #ifndef RAGE128
887 int pitch64;
888 uint32_t xres,yres,bpp;
889 radeon_fifo_wait(1);
890 xres = radeon_get_xres();
891 yres = radeon_get_yres();
892 bpp = radeon_vid_get_dbpp();
893 /* turn of all automatic flushing - we'll do it all */
894 OUTREG(RB2D_DSTCACHE_MODE, 0);
896 pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6;
898 radeon_fifo_wait(1);
899 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) |
900 (pitch64 << 22));
902 radeon_fifo_wait(1);
903 #if defined(WORDS_BIGENDIAN)
904 OUTREGP(DP_DATATYPE,
905 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
906 #else
907 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
908 #endif
910 radeon_fifo_wait(1);
911 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX
912 | DEFAULT_SC_BOTTOM_MAX));
913 radeon_fifo_wait(1);
914 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL)
915 | GMC_BRUSH_SOLID_COLOR
916 | GMC_SRC_DATATYPE_COLOR));
918 radeon_fifo_wait(7);
919 OUTREG(DST_LINE_START, 0);
920 OUTREG(DST_LINE_END, 0);
921 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
922 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
923 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
924 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
925 OUTREG(DP_WRITE_MASK, 0xffffffff);
927 radeon_engine_idle();
928 #endif
930 #ifdef RAGE128
931 static void _radeon_fifo_wait (unsigned entries)
933 unsigned i;
935 for(;;)
937 for (i=0; i<2000000; i++)
938 if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries)
939 return;
940 radeon_engine_reset();
941 radeon_engine_restore();
945 static void _radeon_engine_idle ( void )
947 unsigned i;
949 /* ensure FIFO is empty before waiting for idle */
950 radeon_fifo_wait (64);
951 for(;;)
953 for (i=0; i<2000000; i++) {
954 if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) {
955 radeon_engine_flush ();
956 return;
959 radeon_engine_reset();
960 radeon_engine_restore();
963 #else
964 static void _radeon_fifo_wait (unsigned entries)
966 unsigned i;
968 for(;;)
970 for (i=0; i<2000000; i++)
971 if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries)
972 return;
973 radeon_engine_reset();
974 radeon_engine_restore();
977 static void _radeon_engine_idle ( void )
979 int i;
981 /* ensure FIFO is empty before waiting for idle */
982 radeon_fifo_wait (64);
983 for(;;)
985 for (i=0; i<2000000; i++) {
986 if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) {
987 radeon_engine_flush ();
988 return;
991 radeon_engine_reset();
992 radeon_engine_restore();
995 #endif
997 #ifndef RAGE128
998 /* Reference color space transform data */
999 typedef struct tagREF_TRANSFORM
1001 float RefLuma;
1002 float RefRCb;
1003 float RefRCr;
1004 float RefGCb;
1005 float RefGCr;
1006 float RefBCb;
1007 float RefBCr;
1008 } REF_TRANSFORM;
1010 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
1011 REF_TRANSFORM trans[2] =
1013 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
1014 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
1016 /****************************************************************************
1017 * SetTransform *
1018 * Function: Calculates and sets color space transform from supplied *
1019 * reference transform, gamma, brightness, contrast, hue and *
1020 * saturation. *
1021 * Inputs: bright - brightness *
1022 * cont - contrast *
1023 * sat - saturation *
1024 * hue - hue *
1025 * red_intensity - intense of red component *
1026 * green_intensity - intense of green component *
1027 * blue_intensity - intense of blue component *
1028 * ref - index to the table of refernce transforms *
1029 * Outputs: NONE *
1030 ****************************************************************************/
1032 static void radeon_set_transform(float bright, float cont, float sat,
1033 float hue, float red_intensity,
1034 float green_intensity,float blue_intensity,
1035 unsigned ref)
1037 float OvHueSin, OvHueCos;
1038 float CAdjLuma, CAdjOff;
1039 float RedAdj,GreenAdj,BlueAdj;
1040 float CAdjRCb, CAdjRCr;
1041 float CAdjGCb, CAdjGCr;
1042 float CAdjBCb, CAdjBCr;
1043 float OvLuma, OvROff, OvGOff, OvBOff;
1044 float OvRCb, OvRCr;
1045 float OvGCb, OvGCr;
1046 float OvBCb, OvBCr;
1047 float Loff = 64.0;
1048 float Coff = 512.0f;
1050 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
1051 uint32_t dwOvRCb, dwOvRCr;
1052 uint32_t dwOvGCb, dwOvGCr;
1053 uint32_t dwOvBCb, dwOvBCr;
1055 if (ref >= 2) return;
1057 OvHueSin = sin((double)hue);
1058 OvHueCos = cos((double)hue);
1060 CAdjLuma = cont * trans[ref].RefLuma;
1061 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
1062 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
1063 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
1064 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
1066 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
1067 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
1068 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1069 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1070 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1071 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1073 OvLuma = CAdjLuma;
1074 OvRCb = CAdjRCb;
1075 OvRCr = CAdjRCr;
1076 OvGCb = CAdjGCb;
1077 OvGCr = CAdjGCr;
1078 OvBCb = CAdjBCb;
1079 OvBCr = CAdjBCr;
1080 OvROff = RedAdj + CAdjOff -
1081 OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1082 OvGOff = GreenAdj + CAdjOff -
1083 OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1084 OvBOff = BlueAdj + CAdjOff -
1085 OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1087 dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff;
1088 dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff;
1089 dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff;
1090 /* Whatever docs say about R200 having 3.8 format instead of 3.11
1091 as in Radeon is a lie */
1093 dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17;
1094 dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1;
1095 dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17;
1096 dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1;
1097 dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17;
1098 dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1;
1099 dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17;
1101 OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1102 OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1103 OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1104 OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1105 OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1106 OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1109 /* Gamma curve definition */
1110 typedef struct
1112 unsigned int gammaReg;
1113 unsigned int gammaSlope;
1114 unsigned int gammaOffset;
1115 }GAMMA_SETTINGS;
1117 /* Recommended gamma curve parameters */
1118 GAMMA_SETTINGS r200_def_gamma[18] =
1120 {OV0_GAMMA_0_F, 0x100, 0x0000},
1121 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1122 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1123 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1124 {OV0_GAMMA_80_BF, 0x100, 0x0100},
1125 {OV0_GAMMA_C0_FF, 0x100, 0x0100},
1126 {OV0_GAMMA_100_13F, 0x100, 0x0200},
1127 {OV0_GAMMA_140_17F, 0x100, 0x0200},
1128 {OV0_GAMMA_180_1BF, 0x100, 0x0300},
1129 {OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
1130 {OV0_GAMMA_200_23F, 0x100, 0x0400},
1131 {OV0_GAMMA_240_27F, 0x100, 0x0400},
1132 {OV0_GAMMA_280_2BF, 0x100, 0x0500},
1133 {OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
1134 {OV0_GAMMA_300_33F, 0x100, 0x0600},
1135 {OV0_GAMMA_340_37F, 0x100, 0x0600},
1136 {OV0_GAMMA_380_3BF, 0x100, 0x0700},
1137 {OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
1140 GAMMA_SETTINGS r100_def_gamma[6] =
1142 {OV0_GAMMA_0_F, 0x100, 0x0000},
1143 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1144 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1145 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1146 {OV0_GAMMA_380_3BF, 0x100, 0x0100},
1147 {OV0_GAMMA_3C0_3FF, 0x100, 0x0100}
1150 static void make_default_gamma_correction( void )
1152 size_t i;
1153 if((besr.chip_flags & R_100)==R_100||
1154 (besr.chip_flags & R_120)==R_120||
1155 (besr.chip_flags & R_150)==R_150){
1156 OUTREG(OV0_LIN_TRANS_A, 0x12A00000);
1157 OUTREG(OV0_LIN_TRANS_B, 0x199018FE);
1158 OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0);
1159 OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B);
1160 OUTREG(OV0_LIN_TRANS_E, 0x12A02050);
1161 OUTREG(OV0_LIN_TRANS_F, 0x0000174E);
1162 for(i=0; i<6; i++){
1163 OUTREG(r100_def_gamma[i].gammaReg,
1164 (r100_def_gamma[i].gammaSlope<<16) |
1165 r100_def_gamma[i].gammaOffset);
1168 else{
1169 OUTREG(OV0_LIN_TRANS_A, 0x12a20000);
1170 OUTREG(OV0_LIN_TRANS_B, 0x198a190e);
1171 OUTREG(OV0_LIN_TRANS_C, 0x12a2f9da);
1172 OUTREG(OV0_LIN_TRANS_D, 0xf2fe0442);
1173 OUTREG(OV0_LIN_TRANS_E, 0x12a22046);
1174 OUTREG(OV0_LIN_TRANS_F, 0x175f);
1175 /* Default Gamma,
1176 Of 18 segments for gamma cure, all segments in R200 are programmable,
1177 while only lower 4 and upper 2 segments are programmable in Radeon*/
1178 for(i=0; i<18; i++){
1179 OUTREG(r200_def_gamma[i].gammaReg,
1180 (r200_def_gamma[i].gammaSlope<<16) |
1181 r200_def_gamma[i].gammaOffset);
1185 #endif
1187 static void radeon_vid_make_default(void)
1189 #ifdef RAGE128
1190 besr.saturation = 0x0F;
1191 besr.brightness = 0;
1192 OUTREG(OV0_COLOUR_CNTL,0x000F0F00UL); /* Default brihgtness and saturation for Rage128 */
1193 #else
1194 make_default_gamma_correction();
1195 #endif
1196 besr.deinterlace_pattern = 0x900AAAAA;
1197 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1198 besr.deinterlace_on=1;
1199 besr.double_buff=1;
1200 besr.ckey_on=0;
1201 besr.graphics_key_msk=0;
1202 besr.graphics_key_clr=0;
1203 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
1206 static int find_chip(unsigned chip_id)
1208 unsigned i;
1209 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1211 if(chip_id == ati_card_ids[i].id) return i;
1213 return -1;
1216 static pciinfo_t pci_info;
1217 static int probed=0;
1219 static vidix_capability_t def_cap =
1221 #ifdef RAGE128
1222 "BES driver for Rage128 cards",
1223 #else
1224 "BES driver for Radeon cards",
1225 #endif
1226 "Nick Kurshev",
1227 TYPE_OUTPUT | TYPE_FX,
1228 { 0, 0, 0, 0 },
1229 2048,
1230 2048,
1234 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1235 VENDOR_ATI,
1237 { 0, 0, 0, 0}
1240 #if !defined(RAGE128) && defined(HAVE_X11)
1241 static void probe_fireGL_driver(void) {
1242 Display *dp = XOpenDisplay ((void*)0);
1243 int n = 0;
1244 char **extlist;
1245 if (dp==NULL) {
1246 return;
1248 extlist = XListExtensions (dp, &n);
1249 XCloseDisplay (dp);
1250 if (extlist) {
1251 int i;
1252 int ext_fgl = 0, ext_fglrx = 0;
1253 for (i = 0; i < n; i++) {
1254 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1255 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1257 if (ext_fgl) {
1258 printf(RADEON_MSG" ATI FireGl driver detected");
1259 firegl_shift = 0x500000;
1260 if (!ext_fglrx) {
1261 printf(", but DRI seems not to be activated\n");
1262 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1264 printf("\n");
1268 #endif
1270 static int radeon_probe(int verbose, int force)
1272 pciinfo_t lst[MAX_PCI_DEVICES];
1273 unsigned i,num_pci;
1274 int err;
1275 __verbose = verbose;
1276 err = pci_scan(lst,&num_pci);
1277 if(err)
1279 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1280 return err;
1282 else
1284 err = ENXIO;
1285 for(i=0;i<num_pci;i++)
1287 if(lst[i].vendor == VENDOR_ATI)
1289 int idx;
1290 const char *dname;
1291 idx = find_chip(lst[i].device);
1292 if(idx == -1 && force == PROBE_NORMAL) continue;
1293 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1294 dname = dname ? dname : "Unknown chip";
1295 printf(RADEON_MSG" Found chip: %s\n",dname);
1296 #if 0
1297 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1299 printf("[radeon] Device is disabled, ignoring\n");
1300 continue;
1302 #endif
1303 memset(&besr,0,sizeof(bes_registers_t));
1304 if(force > PROBE_NORMAL)
1306 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1307 if(idx == -1)
1308 #ifdef RAGE128
1309 printf(RADEON_MSG" Assuming it as Rage128\n");
1310 #else
1311 printf(RADEON_MSG" Assuming it as Radeon1\n");
1312 #endif
1313 besr.chip_flags=R_100|R_OVL_SHIFT;
1315 #if !defined(RAGE128) && defined(HAVE_X11)
1316 probe_fireGL_driver();
1317 #endif
1318 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1319 def_cap.device_id = lst[i].device;
1320 err = 0;
1321 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1322 probed=1;
1323 break;
1327 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1328 return err;
1331 typedef struct saved_regs_s
1333 uint32_t ov0_vid_key_clr;
1334 uint32_t ov0_vid_key_msk;
1335 uint32_t ov0_graphics_key_clr;
1336 uint32_t ov0_graphics_key_msk;
1337 uint32_t ov0_key_cntl;
1338 uint32_t disp_merge_cntl;
1339 }saved_regs_t;
1340 static saved_regs_t savreg;
1342 static void save_regs( void )
1344 radeon_fifo_wait(6);
1345 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1346 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1347 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1348 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1349 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1350 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1353 static void restore_regs( void )
1355 radeon_fifo_wait(6);
1356 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1357 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1358 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1359 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1360 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1361 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1364 static int radeon_init(void)
1366 int err;
1368 if(__verbose>0) printf("[radeon_vid] version %d\n", VIDIX_VERSION);
1370 if(!probed)
1372 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1373 return EINTR;
1375 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1376 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1377 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1378 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1379 #ifdef RADEON
1380 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1381 if (radeon_ram_size == 0 &&
1382 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1383 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1385 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1386 radeon_ram_size = 8192*1024;
1388 else if (radeon_ram_size == 0 &&
1389 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1391 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1392 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1393 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1395 #else
1396 /* Rage Mobility (rage128) also has memsize bug */
1397 if (radeon_ram_size == 0 &&
1398 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1399 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1401 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1402 radeon_ram_size = 8192*1024;
1404 #endif
1405 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1406 radeon_vid_make_default();
1407 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1408 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1409 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1410 #ifndef RAGE128
1412 memset(&rinfo,0,sizeof(rinfo_t));
1413 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1415 radeon_get_moninfo(&rinfo);
1416 if(rinfo.hasCRTC2) {
1417 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1418 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1420 else
1421 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1423 #endif
1424 save_regs();
1425 return 0;
1428 static void radeon_destroy(void)
1430 restore_regs();
1431 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1432 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1435 static int radeon_get_caps(vidix_capability_t *to)
1437 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1438 return 0;
1442 Full list of fourcc which are supported by Win2K radeon driver:
1443 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1444 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1446 typedef struct fourcc_desc_s
1448 uint32_t fourcc;
1449 unsigned max_srcw;
1450 }fourcc_desc_t;
1452 static fourcc_desc_t supported_fourcc[] =
1454 { IMGFMT_Y800, 1567 },
1455 { IMGFMT_YVU9, 1567 },
1456 { IMGFMT_IF09, 1567 },
1457 { IMGFMT_YV12, 1567 },
1458 { IMGFMT_I420, 1567 },
1459 { IMGFMT_IYUV, 1567 },
1460 { IMGFMT_UYVY, 1551 },
1461 { IMGFMT_YUY2, 1551 },
1462 { IMGFMT_YVYU, 1551 },
1463 { IMGFMT_RGB15, 1551 },
1464 { IMGFMT_BGR15, 1551 },
1465 { IMGFMT_RGB16, 1551 },
1466 { IMGFMT_BGR16, 1551 },
1467 { IMGFMT_RGB32, 775 },
1468 { IMGFMT_BGR32, 775 }
1471 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1473 unsigned i;
1474 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1476 if(fourcc==supported_fourcc[i].fourcc)
1477 return 1;
1479 return 0;
1482 static int radeon_query_fourcc(vidix_fourcc_t *to)
1484 if(is_supported_fourcc(to->fourcc))
1486 to->depth = VID_DEPTH_ALL;
1487 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1488 VID_CAP_BLEND;
1489 return 0;
1491 else to->depth = to->flags = 0;
1492 return ENOSYS;
1495 static double H_scale_ratio;
1496 static void radeon_vid_dump_regs( void )
1498 size_t i;
1499 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1500 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1501 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1502 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1503 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1504 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1505 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1506 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1507 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1508 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1509 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1512 static void radeon_vid_stop_video( void )
1514 radeon_engine_idle();
1515 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1516 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1517 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1518 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1519 #ifdef RAGE128
1520 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1521 #else
1522 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1523 #endif
1524 OUTREG(OV0_TEST, 0);
1527 static void radeon_vid_display_video( void )
1529 int bes_flags,force_second;
1530 radeon_fifo_wait(2);
1531 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1532 radeon_engine_idle();
1533 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1534 radeon_fifo_wait(15);
1536 force_second=0;
1538 /* Shutdown capturing */
1539 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1540 OUTREG(CAP0_TRIG_CNTL, 0);
1542 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1543 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1545 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1547 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1548 #ifdef RAGE128
1549 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1550 (besr.saturation << 8) |
1551 (besr.saturation << 16));
1552 #endif
1553 radeon_fifo_wait(2);
1554 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1555 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1556 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1558 OUTREG(OV0_H_INC, besr.h_inc);
1559 OUTREG(OV0_STEP_BY, besr.step_by);
1560 if(force_second)
1562 OUTREG(OV1_Y_X_START, besr.y_x_start);
1563 OUTREG(OV1_Y_X_END, besr.y_x_end);
1565 else
1567 OUTREG(OV0_Y_X_START, besr.y_x_start);
1568 OUTREG(OV0_Y_X_END, besr.y_x_end);
1570 OUTREG(OV0_V_INC, besr.v_inc);
1571 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1572 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1573 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1574 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1575 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1576 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1577 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1578 #ifdef RADEON
1579 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1580 #endif
1581 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1582 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1583 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1584 radeon_fifo_wait(9);
1585 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1586 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1587 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1588 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1589 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1590 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1591 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1593 bes_flags = SCALER_ENABLE |
1594 SCALER_SMART_SWITCH |
1595 SCALER_Y2R_TEMP |
1596 SCALER_PIX_EXPAND;
1597 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1598 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1599 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1600 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1601 #ifdef RAGE128
1602 bes_flags |= SCALER_BURST_PER_PLANE;
1603 #endif
1604 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1605 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1606 if(force_second) bes_flags |= SCALER_USE_OV1;
1607 else bes_flags &= ~SCALER_USE_OV1;
1608 OUTREG(OV0_SCALE_CNTL, bes_flags);
1609 radeon_fifo_wait(6);
1610 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1611 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1612 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1613 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1614 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1615 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1616 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1617 OUTREG(OV0_REG_LOAD_CNTL, 0);
1618 if(__verbose > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1619 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
1622 /* Goal of this function: hide RGB background and provide black screen around movie.
1623 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1624 Reverse effect to colorkey */
1625 #ifdef RAGE128
1626 static void radeon_vid_exclusive( void )
1628 /* this function works only with Rage128.
1629 Radeon should has something the same */
1630 unsigned screenw,screenh;
1631 screenw = radeon_get_xres();
1632 screenh = radeon_get_yres();
1633 radeon_fifo_wait(2);
1634 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1635 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1638 static void radeon_vid_non_exclusive( void )
1640 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1642 #endif
1644 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1646 unsigned pitch,spy,spv,spu;
1647 spy = spv = spu = 0;
1648 switch(spitch->y)
1650 case 16:
1651 case 32:
1652 case 64:
1653 case 128:
1654 case 256: spy = spitch->y; break;
1655 default: break;
1657 switch(spitch->u)
1659 case 16:
1660 case 32:
1661 case 64:
1662 case 128:
1663 case 256: spu = spitch->u; break;
1664 default: break;
1666 switch(spitch->v)
1668 case 16:
1669 case 32:
1670 case 64:
1671 case 128:
1672 case 256: spv = spitch->v; break;
1673 default: break;
1675 switch(fourcc)
1677 /* 4:2:0 */
1678 case IMGFMT_IYUV:
1679 case IMGFMT_YV12:
1680 case IMGFMT_I420:
1681 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1682 else pitch = 32;
1683 break;
1684 case IMGFMT_IF09:
1685 case IMGFMT_YVU9:
1686 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1687 else pitch = 64;
1688 break;
1689 default:
1690 if(spy >= 16) pitch = spy;
1691 else pitch = 16;
1692 break;
1694 return pitch;
1697 static void Calc_H_INC_STEP_BY (
1698 int fieldvalue_OV0_SURFACE_FORMAT,
1699 double H_scale_ratio,
1700 int DisallowFourTapVertFiltering,
1701 int DisallowFourTapUVVertFiltering,
1702 uint32_t *val_OV0_P1_H_INC,
1703 uint32_t *val_OV0_P1_H_STEP_BY,
1704 uint32_t *val_OV0_P23_H_INC,
1705 uint32_t *val_OV0_P23_H_STEP_BY,
1706 int *P1GroupSize,
1707 int *P1StepSize,
1708 int *P23StepSize )
1711 double ClocksNeededFor16Pixels;
1713 switch (fieldvalue_OV0_SURFACE_FORMAT)
1715 case 3:
1716 case 4: /*16BPP (ARGB1555 and RGB565) */
1717 /* All colour components are fetched in pairs */
1718 *P1GroupSize = 2;
1719 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1720 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1721 if (H_scale_ratio>=.5)
1723 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1724 /* until we reach .5. P1 and P23 are the same. */
1725 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1726 *val_OV0_P1_H_STEP_BY = 1;
1727 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1728 *val_OV0_P23_H_STEP_BY = 1;
1729 *P1StepSize = 1;
1730 *P23StepSize = 1;
1732 else if (H_scale_ratio>=.25)
1734 /* Step by two */
1735 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1736 *val_OV0_P1_H_STEP_BY = 2;
1737 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1738 *val_OV0_P23_H_STEP_BY = 2;
1739 *P1StepSize = 2;
1740 *P23StepSize = 2;
1742 else if (H_scale_ratio>=.125)
1744 /* Step by four */
1745 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1746 *val_OV0_P1_H_STEP_BY = 3;
1747 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1748 *val_OV0_P23_H_STEP_BY = 3;
1749 *P1StepSize = 4;
1750 *P23StepSize = 4;
1752 else if (H_scale_ratio>=.0625)
1754 /* Step by eight */
1755 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1756 *val_OV0_P1_H_STEP_BY = 4;
1757 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1758 *val_OV0_P23_H_STEP_BY = 4;
1759 *P1StepSize = 8;
1760 *P23StepSize = 8;
1762 else if (H_scale_ratio>=0.03125)
1764 /* Step by sixteen */
1765 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1766 *val_OV0_P1_H_STEP_BY = 5;
1767 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1768 *val_OV0_P23_H_STEP_BY = 5;
1769 *P1StepSize = 16;
1770 *P23StepSize = 16;
1772 else
1774 H_scale_ratio=0.03125;
1775 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1776 *val_OV0_P1_H_STEP_BY = 5;
1777 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1778 *val_OV0_P23_H_STEP_BY = 5;
1779 *P1StepSize = 16;
1780 *P23StepSize = 16;
1782 break;
1783 case 6: /*32BPP RGB */
1784 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1786 /* All colour components are fetched in pairs */
1787 *P1GroupSize = 2;
1788 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1789 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1790 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1791 *val_OV0_P1_H_STEP_BY = 0;
1792 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1793 *val_OV0_P23_H_STEP_BY = 0;
1794 *P1StepSize = 1;
1795 *P23StepSize = 1;
1797 else if (H_scale_ratio>=0.75)
1799 /* Four G colour components are fetched at once */
1800 *P1GroupSize = 4;
1801 /* R and B colour components are fetched in pairs */
1802 /* With two tap filtering, we can generate four colour components every clock. */
1803 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1804 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1805 *val_OV0_P1_H_STEP_BY = 1;
1806 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1807 *val_OV0_P23_H_STEP_BY = 1;
1808 *P1StepSize = 1;
1809 *P23StepSize = 1;
1811 else if (H_scale_ratio>=0.375)
1813 /* Step by two. */
1814 /* Four G colour components are fetched at once */
1815 *P1GroupSize = 4;
1816 /* R and B colour components are fetched in pairs */
1817 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1818 *val_OV0_P1_H_STEP_BY = 2;
1819 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1820 *val_OV0_P23_H_STEP_BY = 2;
1821 *P1StepSize = 2;
1822 *P23StepSize = 2;
1824 else if (H_scale_ratio>=0.25)
1826 /* Step by two. */
1827 /* Four G colour components are fetched at once */
1828 *P1GroupSize = 4;
1829 /* R and B colour components are fetched in pairs */
1830 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1831 *val_OV0_P1_H_STEP_BY = 2;
1832 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1833 *val_OV0_P23_H_STEP_BY = 3;
1834 *P1StepSize = 2;
1835 *P23StepSize = 4;
1837 else if (H_scale_ratio>=0.1875)
1839 /* Step by four */
1840 /* Four G colour components are fetched at once */
1841 *P1GroupSize = 4;
1842 /* R and B colour components are fetched in pairs */
1843 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1844 *val_OV0_P1_H_STEP_BY = 3;
1845 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1846 *val_OV0_P23_H_STEP_BY = 3;
1847 *P1StepSize = 4;
1848 *P23StepSize = 4;
1850 else if (H_scale_ratio>=0.125)
1852 /* Step by four */
1853 /* Four G colour components are fetched at once */
1854 *P1GroupSize = 4;
1855 /* R and B colour components are fetched in pairs */
1856 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1857 *val_OV0_P1_H_STEP_BY = 3;
1858 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1859 *val_OV0_P23_H_STEP_BY = 4;
1860 *P1StepSize = 4;
1861 *P23StepSize = 8;
1863 else if (H_scale_ratio>=0.09375)
1865 /* Step by eight */
1866 /* Four G colour components are fetched at once */
1867 *P1GroupSize = 4;
1868 /* R and B colour components are fetched in pairs */
1869 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1870 *val_OV0_P1_H_STEP_BY = 4;
1871 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1872 *val_OV0_P23_H_STEP_BY = 4;
1873 *P1StepSize = 8;
1874 *P23StepSize = 8;
1876 else if (H_scale_ratio>=0.0625)
1878 /* Step by eight */
1879 /* Four G colour components are fetched at once */
1880 *P1GroupSize = 4;
1881 /* R and B colour components are fetched in pairs */
1882 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1883 *val_OV0_P1_H_STEP_BY = 5;
1884 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1885 *val_OV0_P23_H_STEP_BY = 5;
1886 *P1StepSize = 16;
1887 *P23StepSize = 16;
1889 else
1891 H_scale_ratio=0.0625;
1892 *P1GroupSize = 4;
1893 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1894 *val_OV0_P1_H_STEP_BY = 5;
1895 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1896 *val_OV0_P23_H_STEP_BY = 5;
1897 *P1StepSize = 16;
1898 *P23StepSize = 16;
1900 break;
1901 case 9:
1902 /*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. */
1903 /* four tap on both (unless Y is too wide) */
1904 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1905 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1906 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1907 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1908 { /*0.75 */
1909 /* Colour components are fetched in pairs */
1910 *P1GroupSize = 2;
1911 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1912 *val_OV0_P1_H_STEP_BY = 0;
1913 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1914 *val_OV0_P23_H_STEP_BY = 0;
1915 *P1StepSize = 1;
1916 *P23StepSize = 1;
1918 /* two tap on Y (because it is too big for four tap), four tap on UV */
1919 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1920 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1921 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1922 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1923 { /*0.75 */
1924 *P1GroupSize = 4;
1925 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1926 *val_OV0_P1_H_STEP_BY = 1;
1927 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1928 *val_OV0_P23_H_STEP_BY = 0;
1929 *P1StepSize = 1;
1930 *P23StepSize = 1;
1932 /* We scale the Y with the four tap filters, but UV's are generated
1933 with dual two tap configuration. */
1934 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1935 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1936 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1937 !DisallowFourTapVertFiltering)
1938 { /*0.625 */
1939 *P1GroupSize = 2;
1940 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1941 *val_OV0_P1_H_STEP_BY = 0;
1942 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1943 *val_OV0_P23_H_STEP_BY = 1;
1944 *P1StepSize = 1;
1945 *P23StepSize = 1;
1947 /* We scale the Y, U, and V with the two tap filters */
1948 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1949 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1950 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1951 { /*0.375 */
1952 *P1GroupSize = 4;
1953 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1954 *val_OV0_P1_H_STEP_BY = 1;
1955 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1956 *val_OV0_P23_H_STEP_BY = 1;
1957 *P1StepSize = 1;
1958 *P23StepSize = 1;
1960 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1961 thus we won't drop Y's yet. */
1962 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1963 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1964 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1965 { /*>=0.3125 and >.333333~ */
1966 *P1GroupSize = 4;
1967 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1968 *val_OV0_P1_H_STEP_BY = 1;
1969 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1970 *val_OV0_P23_H_STEP_BY = 2;
1971 *P1StepSize = 1;
1972 *P23StepSize = 2;
1974 /* We step the Y, U, and V by two. */
1975 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1976 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1977 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1979 *P1GroupSize = 4;
1980 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1981 *val_OV0_P1_H_STEP_BY = 2;
1982 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1983 *val_OV0_P23_H_STEP_BY = 2;
1984 *P1StepSize = 2;
1985 *P23StepSize = 2;
1987 /* We step the Y by two and the U and V by four. */
1988 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1989 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1990 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1992 *P1GroupSize = 4;
1993 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1994 *val_OV0_P1_H_STEP_BY = 2;
1995 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1996 *val_OV0_P23_H_STEP_BY = 3;
1997 *P1StepSize = 2;
1998 *P23StepSize = 4;
2000 /* We step the Y, U, and V by four. */
2001 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2002 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
2003 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
2005 *P1GroupSize = 4;
2006 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2007 *val_OV0_P1_H_STEP_BY = 3;
2008 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
2009 *val_OV0_P23_H_STEP_BY = 3;
2010 *P1StepSize = 4;
2011 *P23StepSize = 4;
2013 /* 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 */
2015 /* We step the Y, U, and V by eight. */
2016 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
2017 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
2018 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
2020 *P1GroupSize = 4;
2021 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2022 *val_OV0_P1_H_STEP_BY = 4;
2023 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
2024 *val_OV0_P23_H_STEP_BY = 4;
2025 *P1StepSize = 8;
2026 *P23StepSize = 8;
2028 /* We step the Y by eight and the U and V by sixteen. */
2029 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
2030 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
2031 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
2033 *P1GroupSize = 4;
2034 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2035 *val_OV0_P1_H_STEP_BY = 4;
2036 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2037 *val_OV0_P23_H_STEP_BY = 5;
2038 *P1StepSize = 8;
2039 *P23StepSize = 16;
2041 /* We step the Y, U, and V by sixteen. */
2042 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
2043 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
2044 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
2046 *P1GroupSize = 4;
2047 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2048 *val_OV0_P1_H_STEP_BY = 5;
2049 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2050 *val_OV0_P23_H_STEP_BY = 5;
2051 *P1StepSize = 16;
2052 *P23StepSize = 16;
2054 else
2056 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
2057 *P1GroupSize = 4;
2058 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2059 *val_OV0_P1_H_STEP_BY = 5;
2060 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2061 *val_OV0_P23_H_STEP_BY = 5;
2062 *P1StepSize = 16;
2063 *P23StepSize = 16;
2065 break;
2066 case 10:
2067 case 11:
2068 case 12:
2069 case 13:
2070 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2071 /* We scale the Y, U, and V with the four tap filters */
2072 /* four tap on both (unless Y is too wide) */
2073 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2074 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2075 { /*0.75 */
2076 *P1GroupSize = 2;
2077 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2078 *val_OV0_P1_H_STEP_BY = 0;
2079 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2080 *val_OV0_P23_H_STEP_BY = 0;
2081 *P1StepSize = 1;
2082 *P23StepSize = 1;
2084 /* two tap on Y (because it is too big for four tap), four tap on UV */
2085 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2086 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2087 { /*0.75 */
2088 *P1GroupSize = 4;
2089 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2090 *val_OV0_P1_H_STEP_BY = 1;
2091 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2092 *val_OV0_P23_H_STEP_BY = 0;
2093 *P1StepSize = 1;
2094 *P23StepSize = 1;
2096 /* We scale the Y with the four tap filters, but UV's are generated
2097 with dual two tap configuration. */
2098 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2099 !DisallowFourTapVertFiltering)
2100 { /*0.625 */
2101 *P1GroupSize = 2;
2102 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2103 *val_OV0_P1_H_STEP_BY = 0;
2104 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2105 *val_OV0_P23_H_STEP_BY = 1;
2106 *P1StepSize = 1;
2107 *P23StepSize = 1;
2109 /* We scale the Y, U, and V with the two tap filters */
2110 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2111 { /*0.375 */
2112 *P1GroupSize = 4;
2113 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2114 *val_OV0_P1_H_STEP_BY = 1;
2115 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2116 *val_OV0_P23_H_STEP_BY = 1;
2117 *P1StepSize = 1;
2118 *P23StepSize = 1;
2120 /* We scale step the U and V by two to allow more bandwidth for
2121 fetching Y's, thus we won't drop Y's yet. */
2122 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2123 { /*0.312 */
2124 *P1GroupSize = 4;
2125 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2126 *val_OV0_P1_H_STEP_BY = 1;
2127 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2128 *val_OV0_P23_H_STEP_BY = 2;
2129 *P1StepSize = 1;
2130 *P23StepSize = 2;
2132 /* We step the Y, U, and V by two. */
2133 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2135 *P1GroupSize = 4;
2136 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2137 *val_OV0_P1_H_STEP_BY = 2;
2138 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2139 *val_OV0_P23_H_STEP_BY = 2;
2140 *P1StepSize = 2;
2141 *P23StepSize = 2;
2143 /* We step the Y by two and the U and V by four. */
2144 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2146 *P1GroupSize = 4;
2147 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2148 *val_OV0_P1_H_STEP_BY = 2;
2149 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2150 *val_OV0_P23_H_STEP_BY = 3;
2151 *P1StepSize = 2;
2152 *P23StepSize = 4;
2154 /* We step the Y, U, and V by four. */
2155 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2157 *P1GroupSize = 4;
2158 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2159 *val_OV0_P1_H_STEP_BY = 3;
2160 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2161 *val_OV0_P23_H_STEP_BY = 3;
2162 *P1StepSize = 4;
2163 *P23StepSize = 4;
2165 /* We step the Y by four and the U and V by eight. */
2166 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2167 (fieldvalue_OV0_SURFACE_FORMAT==10))
2169 *P1GroupSize = 4;
2170 /* Can't mix step by 3 and step by 4 for packed modes */
2171 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2172 *val_OV0_P1_H_STEP_BY = 3;
2173 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2174 *val_OV0_P23_H_STEP_BY = 4;
2175 *P1StepSize = 4;
2176 *P23StepSize = 8;
2178 /* We step the Y, U, and V by eight. */
2179 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2181 *P1GroupSize = 4;
2182 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2183 *val_OV0_P1_H_STEP_BY = 4;
2184 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2185 *val_OV0_P23_H_STEP_BY = 4;
2186 *P1StepSize = 8;
2187 *P23StepSize = 8;
2189 /* We step the Y by eight and the U and V by sixteen. */
2190 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2192 *P1GroupSize = 4;
2193 /* Step by 5 not supported for packed modes */
2194 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2195 *val_OV0_P1_H_STEP_BY = 4;
2196 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2197 *val_OV0_P23_H_STEP_BY = 5;
2198 *P1StepSize = 8;
2199 *P23StepSize = 16;
2201 /* We step the Y, U, and V by sixteen. */
2202 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2203 (fieldvalue_OV0_SURFACE_FORMAT==10))
2205 *P1GroupSize = 4;
2206 /* Step by 5 not supported for packed modes */
2207 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2208 *val_OV0_P1_H_STEP_BY = 5;
2209 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2210 *val_OV0_P23_H_STEP_BY = 5;
2211 *P1StepSize = 16;
2212 *P23StepSize = 16;
2214 else
2216 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2218 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2219 *P1GroupSize = 4;
2220 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2221 *val_OV0_P1_H_STEP_BY = 5;
2222 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2223 *val_OV0_P23_H_STEP_BY = 5;
2224 *P1StepSize = 16;
2225 *P23StepSize = 16;
2227 else
2229 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2230 *P1GroupSize = 4;
2231 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2232 *val_OV0_P1_H_STEP_BY = 4;
2233 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2234 *val_OV0_P23_H_STEP_BY = 4;
2235 *P1StepSize = 8;
2236 *P23StepSize = 8;
2239 break;
2240 default: break;
2243 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2244 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2247 /* ********************************************************* */
2248 /* ** Setup Black Bordering */
2249 /* ********************************************************* */
2251 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2253 double tempBLANK_LINES_AT_TOP;
2254 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2255 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2256 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2258 if (floor(config->src.y)<0) {
2259 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2260 TopLine = 0;
2262 else {
2263 tempBLANK_LINES_AT_TOP = 0;
2264 TopLine = (int)floor(config->src.y);
2266 /* Round rSrcBottom up and subtract one */
2267 if (ceil(config->src.y+config->src.h) > config->src.h)
2269 BottomLine = config->src.h - 1;
2271 else
2273 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2276 if (BottomLine >= TopLine)
2278 SourceLinesUsed = BottomLine - TopLine + 1;
2280 else
2282 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2283 SourceLinesUsed = 1;
2287 int SourceHeightInPixels;
2288 SourceHeightInPixels = BottomLine - TopLine + 1;
2291 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2292 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2294 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2295 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2296 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2298 if (BottomUVLine >= TopUVLine)
2300 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2302 else
2304 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2305 SourceUVLinesUsed = 1;
2307 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2308 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2309 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2310 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2311 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2312 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2316 static void ComputeXStartEnd(
2317 int is_400,
2318 uint32_t LeftPixel,uint32_t LeftUVPixel,
2319 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2320 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2321 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2322 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2324 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2325 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2326 /* 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. */
2328 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2329 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2331 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2332 switch (besr.surf_id)
2334 case 9:
2335 case 10:
2336 case 13:
2337 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2338 /* a multiple of a power of two when decimating */
2339 val_OV0_P2_X_START = (int)LeftUVPixel %
2340 (MemWordsInBytes/BytesPerUVPixel);
2341 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2342 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2343 break;
2344 case 11:
2345 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2346 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2347 break;
2348 case 3:
2349 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2350 /* This value is needed only to allow proper setting of */
2351 /* val_OV0_PRESHIFT_P23_TO */
2352 /* val_OV0_P2_X_END = 0; */
2353 break;
2354 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2355 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2356 break;
2357 default: /* insert debug statement here. */
2358 RADEON_ASSERT("unknown fourcc\n");
2359 break;
2361 val_OV0_P3_X_START = val_OV0_P2_X_START;
2362 val_OV0_P3_X_END = val_OV0_P2_X_END;
2364 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2365 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2366 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2367 if(is_400)
2369 besr.p2_x_start_end = 0;
2370 besr.p3_x_start_end = 0;
2372 *p1_x_start = val_OV0_P1_X_START;
2373 *p2_x_start = val_OV0_P2_X_START;
2376 static void ComputeAccumInit(
2377 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2378 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2379 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2380 uint32_t CRT_V_INC,
2381 uint32_t P1GroupSize, uint32_t P23GroupSize,
2382 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2383 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2385 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2386 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2387 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2388 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2389 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2390 /* the distance (in source pixel coordinates) to the center of the first */
2391 /* destination pixel. Need to add additional pixels depending on how many pixels */
2392 /* are fetched at a time and how many pixels in a set are masked. */
2393 /* P23 values are always fetched in groups of two or four. If the start */
2394 /* pixel does not fall on the boundary, then we need to shift preshift for */
2395 /* some additional pixels */
2398 double ExtraHalfPixel;
2399 double tempAdditionalShift;
2400 double tempP1HStartPoint;
2401 double tempP23HStartPoint;
2402 double tempP1Init;
2403 double tempP23Init;
2405 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2406 else ExtraHalfPixel = 0.0;
2407 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2408 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2409 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2411 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2412 /* need to shift an additional pixel */
2413 /* Note that if the pitch is a multiple of two, and if we store fields using */
2414 /* the traditional planer format where the V plane and the U plane share the */
2415 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2416 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2417 /* it is a requirement that the U and V start on the same polarity byte */
2418 /* (even or odd). */
2419 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2420 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2421 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2422 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2423 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2424 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2425 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2428 /* ************************************************************** */
2429 /* ** Calculate values for initializing the vertical accumulators */
2430 /* ************************************************************** */
2433 double ExtraHalfLine;
2434 double ExtraFullLine;
2435 double tempP1VStartPoint;
2436 double tempP23VStartPoint;
2438 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2439 else ExtraHalfLine = 0.0;
2441 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2442 else ExtraFullLine = 0.0;
2444 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2445 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2447 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2449 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2451 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2452 else ExtraFullLine = 0.0;
2454 switch (besr.surf_id)
2456 case 10:
2457 case 13:
2458 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2459 ((float)CRT_V_INC / (1<<0xe));
2460 break;
2461 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2462 ((float)CRT_V_INC / (1<<0xf));
2463 break;
2464 case 3:
2465 case 4:
2466 case 6:
2467 case 11:
2468 case 12: tempP23VStartPoint = 0;
2469 break;
2470 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2471 break;
2474 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2476 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2479 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2481 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2482 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2483 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2484 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2487 typedef struct RangeAndCoefSet {
2488 double Range;
2489 signed char CoefSet[5][4];
2490 } RANGEANDCOEFSET;
2492 /* Filter Setup Routine */
2493 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2495 static RANGEANDCOEFSET ArrayOfSets[] = {
2496 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2497 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2498 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2499 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2500 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2501 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2502 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2503 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2504 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2505 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2506 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2507 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2508 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2509 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2510 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2511 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2512 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2513 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2514 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2515 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2516 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2517 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2518 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2519 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2520 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2521 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2522 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2523 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2524 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2525 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2526 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2527 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2528 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2529 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2530 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2531 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2532 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2533 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2534 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2535 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2536 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2537 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2538 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2539 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2540 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2541 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2542 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2543 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2544 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2545 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2546 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2547 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2548 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2549 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2550 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2551 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2552 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2553 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2554 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2555 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2556 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2557 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2558 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2559 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2560 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2561 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2562 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2563 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2564 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2565 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2566 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2567 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2568 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2569 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2570 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2571 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2574 double DSR;
2576 unsigned ArrayElement;
2578 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2579 if (DSR<.25) DSR=.25;
2580 if (DSR>1) DSR=1;
2582 ArrayElement = (int)((DSR-0.25) * 100);
2583 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2584 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2585 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2586 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2587 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2588 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2589 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2590 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2591 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2592 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2593 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2594 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2595 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2596 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2597 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2598 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2599 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2600 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2601 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2602 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2604 For more details, refer to Microsoft's draft of PC99.
2608 /* The minimal value of horizontal scale ratio when hard coded coefficients
2609 are suitable for the best quality. */
2610 /* FIXME: Should it be 0.9 for Rage128 ??? */
2611 static const double MinHScaleHard=0.75;
2613 static int radeon_vid_init_video( vidix_playback_t *config )
2615 double V_scale_ratio;
2616 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2617 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;
2618 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2619 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2620 uint32_t CRT_V_INC;
2621 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2622 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2623 uint32_t PageSizeInBytes,OV0LB_Rows;
2624 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2625 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2626 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2627 int is_400,is_410,is_420,best_pitch,mpitch;
2628 int horz_repl_factor,interlace_factor;
2629 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2630 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2632 radeon_vid_stop_video();
2633 left = config->src.x << 16;
2634 top = config->src.y << 16;
2635 src_h = config->src.h;
2636 src_w = config->src.w;
2637 is_400 = is_410 = is_420 = 0;
2638 if(config->fourcc == IMGFMT_YV12 ||
2639 config->fourcc == IMGFMT_I420 ||
2640 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2641 if(config->fourcc == IMGFMT_YVU9 ||
2642 config->fourcc == IMGFMT_IF09) is_410 = 1;
2643 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2644 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2645 mpitch = best_pitch-1;
2646 BytesPerOctWord = 16;
2647 LogMemWordsInBytes = 4;
2648 MemWordsInBytes = 1<<LogMemWordsInBytes;
2649 LogTileWidthInMemWords = 2;
2650 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2651 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2652 LogTileHeight = 4;
2653 TileHeight = 1<<LogTileHeight;
2654 PageSizeInBytes = 64*MemWordsInBytes;
2655 OV0LB_Rows = 96;
2656 h_inc = 1;
2657 switch(config->fourcc)
2659 /* 4:0:0*/
2660 case IMGFMT_Y800:
2661 /* 4:1:0*/
2662 case IMGFMT_YVU9:
2663 case IMGFMT_IF09:
2664 /* 4:2:0 */
2665 case IMGFMT_IYUV:
2666 case IMGFMT_YV12:
2667 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2668 config->dest.pitch.y =
2669 config->dest.pitch.u =
2670 config->dest.pitch.v = best_pitch;
2671 break;
2672 /* RGB 4:4:4:4 */
2673 case IMGFMT_RGB32:
2674 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2675 config->dest.pitch.y =
2676 config->dest.pitch.u =
2677 config->dest.pitch.v = best_pitch;
2678 break;
2679 /* 4:2:2 */
2681 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2682 pitch = ((src_w*2) + mpitch) & ~mpitch;
2683 config->dest.pitch.y =
2684 config->dest.pitch.u =
2685 config->dest.pitch.v = best_pitch;
2686 break;
2688 besr.load_prg_start=0;
2689 besr.swap_uv=0;
2690 switch(config->fourcc)
2692 case IMGFMT_RGB15:
2693 besr.swap_uv=1;
2694 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2695 besr.load_prg_start = 1;
2696 break;
2697 case IMGFMT_RGB16:
2698 besr.swap_uv=1;
2699 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2700 besr.load_prg_start = 1;
2701 break;
2702 case IMGFMT_RGB32:
2703 besr.swap_uv=1;
2704 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2705 besr.load_prg_start = 1;
2706 break;
2707 /* 4:1:0*/
2708 case IMGFMT_IF09:
2709 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2710 break;
2711 /* 4:0:0*/
2712 case IMGFMT_Y800:
2713 /* 4:2:0 */
2714 case IMGFMT_IYUV:
2715 case IMGFMT_I420:
2716 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2717 break;
2718 /* 4:2:2 */
2719 case IMGFMT_YVYU:
2720 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2721 break;
2722 case IMGFMT_YUY2:
2723 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2724 break;
2726 switch (besr.surf_id)
2728 case 3:
2729 case 4:
2730 case 11:
2731 case 12: BytesPerPixel = 2;
2732 break;
2733 case 6: BytesPerPixel = 4;
2734 break;
2735 case 9:
2736 case 10:
2737 case 13:
2738 case 14: BytesPerPixel = 1;
2739 break;
2740 default: BytesPerPixel = 0;/*insert a debug statement here. */
2741 break;
2743 switch (besr.surf_id)
2745 case 3:
2746 case 4: BytesPerUVPixel = 0;
2747 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2748 case 11:
2749 case 12: BytesPerUVPixel = 2;
2750 break;
2751 case 6: BytesPerUVPixel = 0;
2752 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2753 case 9:
2754 case 10: BytesPerUVPixel = 1;
2755 break;
2756 case 13:
2757 case 14: BytesPerUVPixel = 2;
2758 break;
2759 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2760 break;
2763 switch (besr.surf_id)
2765 case 3:
2766 case 4:
2767 case 6: HorzUVSubSample = 1;
2768 break;
2769 case 9: HorzUVSubSample = 4;
2770 break;
2771 case 10:
2772 case 11:
2773 case 12:
2774 case 13:
2775 case 14: HorzUVSubSample = 2;
2776 break;
2777 default: HorzUVSubSample = 0;/* insert debug statement here. */
2778 break;
2780 switch (besr.surf_id)
2782 case 3:
2783 case 4:
2784 case 6:
2785 case 11:
2786 case 12: VertUVSubSample = 1;
2787 break;
2788 case 9: VertUVSubSample = 4;
2789 break;
2790 case 10:
2791 case 13:
2792 case 14: VertUVSubSample = 2;
2793 break;
2794 default: VertUVSubSample = 0;/* insert debug statment here. */
2795 break;
2797 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2798 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2799 LeftPixel = config->src.x;
2800 RightPixel = config->src.w-1;
2801 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2802 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2803 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2804 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2805 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2806 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2807 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2808 SourceWidthInPixels = (int)(config->src.w + 1);
2809 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2811 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2812 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2813 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2814 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2815 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2816 MemWordsInBytes) + 1);
2818 switch (besr.surf_id)
2820 case 9:
2821 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2823 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2825 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2827 DisallowFourTapVertFiltering = 1;
2830 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2832 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2834 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2836 DisallowFourTapUVVertFiltering = 1;
2839 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2841 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2843 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2845 DisallowFourTapUVVertFiltering = 1;
2847 break;
2848 case 13:
2849 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2851 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2853 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2855 DisallowFourTapVertFiltering = 1;
2858 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2860 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2862 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2864 DisallowFourTapUVVertFiltering = 1;
2866 break;
2867 case 3:
2868 case 4:
2869 case 6:
2870 case 11:
2871 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2873 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2875 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2877 DisallowFourTapVertFiltering = 1;
2879 break;
2880 default: /* insert debug statement here. */
2881 break;
2883 dest_w = config->dest.w;
2884 dest_h = config->dest.h;
2885 if(radeon_is_dbl_scan()) dest_h *= 2;
2886 besr.dest_bpp = radeon_vid_get_dbpp();
2887 besr.fourcc = config->fourcc;
2888 if(radeon_is_interlace()) interlace_factor = 2;
2889 else interlace_factor = 1;
2890 /* TODO: must be checked in doublescan mode!!! */
2891 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2893 /* Force the overlay clock on for integrated chips */
2894 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2896 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2897 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2898 V_scale_ratio = (double)(dest_h+1)/src_h;
2899 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2901 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2902 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2904 else
2905 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2907 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2908 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2910 else
2912 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2913 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2915 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2916 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2917 CRT_V_INC = besr.v_inc/interlace_factor;
2918 besr.v_inc <<= 8;
2920 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2921 int P1GroupSize = 0;
2922 int P23GroupSize;
2923 int P1StepSize = 0;
2924 int P23StepSize = 0;
2926 Calc_H_INC_STEP_BY(
2927 besr.surf_id,
2928 H_scale_ratio,
2929 DisallowFourTapVertFiltering,
2930 DisallowFourTapUVVertFiltering,
2931 &val_OV0_P1_H_INC,
2932 &val_OV0_P1_H_STEP_BY,
2933 &val_OV0_P23_H_INC,
2934 &val_OV0_P23_H_STEP_BY,
2935 &P1GroupSize,
2936 &P1StepSize,
2937 &P23StepSize);
2939 if(H_scale_ratio > MinHScaleHard)
2941 h_inc = (src_w << 12) / dest_w;
2942 besr.step_by = 0x0101;
2943 switch (besr.surf_id)
2945 case 3:
2946 case 4:
2947 case 6:
2948 besr.h_inc = (h_inc)|(h_inc<<16);
2949 break;
2950 case 9:
2951 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2952 break;
2953 default:
2954 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2955 break;
2959 P23GroupSize = 2; /* Current vaue for all modes */
2961 besr.horz_pick_nearest=0;
2962 DoNotUseMostRecentlyFetchedLine=0;
2963 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2964 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2965 besr.vert_pick_nearest = 1;
2966 else
2967 besr.vert_pick_nearest = 0;
2969 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2970 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2971 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2973 if(H_scale_ratio > MinHScaleHard)
2975 unsigned tmp;
2976 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2977 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2978 ((tmp << 12) & 0xf0000000);
2980 tmp = (top & 0x0000ffff) + 0x00018000;
2981 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2982 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2983 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2984 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2985 ((tmp << 12) & 0x70000000);
2987 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2988 besr.p23_v_accum_init = (is_420||is_410) ?
2989 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2990 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2992 else
2993 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2994 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2995 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2996 CRT_V_INC,P1GroupSize,P23GroupSize,
2997 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2998 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
3001 /* keep everything in 16.16 */
3002 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
3003 config->offsets[0] = 0;
3004 for(i=1;i<besr.vid_nbufs;i++)
3005 config->offsets[i] = config->offsets[i-1]+config->frame_size;
3006 if(is_420 || is_410 || is_400)
3008 uint32_t d1line,d2line,d3line;
3009 d1line = top*pitch;
3010 if(is_420)
3012 d2line = src_h*pitch+(d1line>>2);
3013 d3line = d2line+((src_h*pitch)>>2);
3015 else
3016 if(is_410)
3018 d2line = src_h*pitch+(d1line>>4);
3019 d3line = d2line+((src_h*pitch)>>4);
3021 else
3023 d2line = 0;
3024 d3line = 0;
3026 d1line += (left >> 16) & ~15;
3027 if(is_420)
3029 d2line += (left >> 17) & ~15;
3030 d3line += (left >> 17) & ~15;
3032 else /* is_410 */
3034 d2line += (left >> 18) & ~15;
3035 d3line += (left >> 18) & ~15;
3037 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
3038 if(is_400)
3040 config->offset.v = 0;
3041 config->offset.u = 0;
3043 else
3045 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
3046 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
3048 for(i=0;i<besr.vid_nbufs;i++)
3050 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
3051 if(is_400)
3053 besr.vid_buf_base_adrs_v[i]=0;
3054 besr.vid_buf_base_adrs_u[i]=0;
3056 else
3058 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
3060 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;
3061 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;
3063 else
3065 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;
3066 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;
3070 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3071 if(is_400)
3073 config->offset.v = 0;
3074 config->offset.u = 0;
3076 else
3078 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3079 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3082 else
3084 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3085 for(i=0;i<besr.vid_nbufs;i++)
3087 besr.vid_buf_base_adrs_y[i] =
3088 besr.vid_buf_base_adrs_u[i] =
3089 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3092 leftUV = (left >> (is_410?18:17)) & 15;
3093 left = (left >> 16) & 15;
3094 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3095 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3096 ComputeBorders(config,VertUVSubSample);
3097 besr.vid_buf_pitch0_value = pitch;
3098 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3099 /* ********************************************************* */
3100 /* ** Calculate programmable coefficients as needed */
3101 /* ********************************************************* */
3103 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3104 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3105 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3106 else
3108 FilterSetup (val_OV0_P1_H_INC);
3109 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3110 /* would like to do. For now, we let the test application decide. */
3111 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3112 if(DisallowFourTapVertFiltering)
3113 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3114 if(DisallowFourTapUVVertFiltering)
3115 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3117 return 0;
3120 static void radeon_compute_framesize(vidix_playback_t *info)
3122 unsigned pitch,awidth,dbpp;
3123 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3124 dbpp = radeon_vid_get_dbpp();
3125 switch(info->fourcc)
3127 case IMGFMT_Y800:
3128 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3129 info->frame_size = awidth*info->src.h;
3130 break;
3131 case IMGFMT_YVU9:
3132 case IMGFMT_IF09:
3133 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3134 info->frame_size = awidth*(info->src.h+info->src.h/8);
3135 break;
3136 case IMGFMT_I420:
3137 case IMGFMT_YV12:
3138 case IMGFMT_IYUV:
3139 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3140 info->frame_size = awidth*(info->src.h+info->src.h/2);
3141 break;
3142 case IMGFMT_RGB32:
3143 case IMGFMT_BGR32:
3144 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3145 info->frame_size = awidth*info->src.h;
3146 break;
3147 /* YUY2 YVYU, RGB15, RGB16 */
3148 default:
3149 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3150 info->frame_size = awidth*info->src.h;
3151 break;
3153 info->frame_size = (info->frame_size+4095)&~4095;
3156 static int radeon_config_playback(vidix_playback_t *info)
3158 unsigned rgb_size,nfr;
3159 uint32_t radeon_video_size;
3160 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3161 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3162 if(info->num_frames==1) besr.double_buff=0;
3163 else besr.double_buff=1;
3164 radeon_compute_framesize(info);
3166 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3167 nfr = info->num_frames;
3168 radeon_video_size = radeon_ram_size;
3169 for(;nfr>0; nfr--)
3171 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3172 #if !defined (RAGE128) && defined(HAVE_X11)
3173 radeon_overlay_off -= firegl_shift;
3174 #endif
3175 radeon_overlay_off &= 0xffff0000;
3176 if(radeon_overlay_off >= (int)rgb_size ) break;
3178 if(nfr <= 3)
3180 nfr = info->num_frames;
3181 for(;nfr>0; nfr--)
3183 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3184 #if !defined (RAGE128) && defined(HAVE_X11)
3185 radeon_overlay_off -= firegl_shift;
3186 #endif
3187 radeon_overlay_off &= 0xffff0000;
3188 if(radeon_overlay_off > 0) break;
3191 if(nfr <= 0) return EINVAL;
3192 info->num_frames = nfr;
3193 besr.vid_nbufs = info->num_frames;
3194 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3195 radeon_vid_init_video(info);
3196 return 0;
3199 static int radeon_playback_on(void)
3201 #ifdef RAGE128
3202 unsigned dw,dh;
3203 #endif
3204 radeon_vid_display_video();
3205 #ifdef RAGE128
3206 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3207 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3208 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3209 else radeon_vid_non_exclusive();
3210 #endif
3211 return 0;
3214 static int radeon_playback_off(void)
3216 radeon_vid_stop_video();
3217 return 0;
3220 static int radeon_frame_select(unsigned frame)
3222 uint32_t off[6];
3223 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3225 buf3-5 always should point onto second buffer for better
3226 deinterlacing and TV-in
3228 if(!besr.double_buff) return 0;
3229 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3230 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3231 off[0] = besr.vid_buf_base_adrs_y[frame];
3232 off[1] = besr.vid_buf_base_adrs_v[frame];
3233 off[2] = besr.vid_buf_base_adrs_u[frame];
3234 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3235 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3236 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3237 radeon_fifo_wait(8);
3238 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3239 radeon_engine_idle();
3240 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3241 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3242 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3243 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3244 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3245 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3246 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3247 OUTREG(OV0_REG_LOAD_CNTL, 0);
3248 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3249 if(__verbose > VERBOSE_LEVEL) radeon_vid_dump_regs();
3250 return 0;
3253 static vidix_video_eq_t equal =
3255 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3256 #ifndef RAGE128
3257 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3258 #endif
3260 0, 0, 0, 0, 0, 0, 0, 0 };
3262 static int radeon_get_eq(vidix_video_eq_t * eq)
3264 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3265 return 0;
3268 #ifndef RAGE128
3269 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3270 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3271 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3272 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3273 #define RTFHue(a) (((a)*3.1416)/1000.0)
3274 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3275 #endif
3277 static int radeon_set_eq(const vidix_video_eq_t * eq)
3279 #ifdef RAGE128
3280 int br,sat;
3281 #else
3282 int itu_space;
3283 #endif
3284 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3285 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3286 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3287 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3288 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3290 equal.red_intensity = eq->red_intensity;
3291 equal.green_intensity = eq->green_intensity;
3292 equal.blue_intensity = eq->blue_intensity;
3294 equal.flags = eq->flags;
3295 #ifdef RAGE128
3296 br = equal.brightness * 64 / 1000;
3297 if(br < -64) br = -64; if(br > 63) br = 63;
3298 sat = (equal.saturation*31 + 31000) / 2000;
3299 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3300 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3301 #else
3302 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3303 RTFCheckParam(equal.brightness);
3304 RTFCheckParam(equal.saturation);
3305 RTFCheckParam(equal.contrast);
3306 RTFCheckParam(equal.hue);
3307 RTFCheckParam(equal.red_intensity);
3308 RTFCheckParam(equal.green_intensity);
3309 RTFCheckParam(equal.blue_intensity);
3310 radeon_set_transform(RTFBrightness(equal.brightness),
3311 RTFContrast(equal.contrast),
3312 RTFSaturation(equal.saturation),
3313 RTFHue(equal.hue),
3314 RTFIntensity(equal.red_intensity),
3315 RTFIntensity(equal.green_intensity),
3316 RTFIntensity(equal.blue_intensity),
3317 itu_space);
3318 #endif
3319 return 0;
3322 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3324 unsigned sflg;
3325 switch(info->flags)
3327 default:
3328 case CFG_NON_INTERLACED:
3329 besr.deinterlace_on = 0;
3330 break;
3331 case CFG_EVEN_ODD_INTERLACING:
3332 case CFG_INTERLACED:
3333 besr.deinterlace_on = 1;
3334 besr.deinterlace_pattern = 0x900AAAAA;
3335 break;
3336 case CFG_ODD_EVEN_INTERLACING:
3337 besr.deinterlace_on = 1;
3338 besr.deinterlace_pattern = 0x00055555;
3339 break;
3340 case CFG_UNIQUE_INTERLACING:
3341 besr.deinterlace_on = 1;
3342 besr.deinterlace_pattern = info->deinterlace_pattern;
3343 break;
3345 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3346 radeon_engine_idle();
3347 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3348 radeon_fifo_wait(15);
3349 sflg = INREG(OV0_SCALE_CNTL);
3350 if(besr.deinterlace_on)
3352 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3353 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3355 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3356 OUTREG(OV0_REG_LOAD_CNTL, 0);
3357 return 0;
3360 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3362 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3363 else
3365 info->flags = CFG_UNIQUE_INTERLACING;
3366 info->deinterlace_pattern = besr.deinterlace_pattern;
3368 return 0;
3372 /* Graphic keys */
3373 static vidix_grkey_t radeon_grkey;
3375 static int set_gr_key( void )
3377 int result = 0;
3379 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3380 0x00ff0000; /* graphic alpha */
3381 if(radeon_grkey.ckey.op == CKEY_TRUE)
3383 int dbpp=radeon_vid_get_dbpp();
3384 besr.ckey_on=1;
3386 switch(dbpp)
3388 case 15:
3389 #ifndef RAGE128
3390 if((besr.chip_flags&R_100)!=R_100)
3391 besr.graphics_key_clr=
3392 ((radeon_grkey.ckey.blue &0xF8))
3393 | ((radeon_grkey.ckey.green&0xF8)<<8)
3394 | ((radeon_grkey.ckey.red &0xF8)<<16);
3395 else
3396 #endif
3397 besr.graphics_key_clr=
3398 ((radeon_grkey.ckey.blue &0xF8)>>3)
3399 | ((radeon_grkey.ckey.green&0xF8)<<2)
3400 | ((radeon_grkey.ckey.red &0xF8)<<7);
3401 break;
3402 case 16:
3403 #ifndef RAGE128
3404 /* This test may be too general/specific */
3405 if((besr.chip_flags&R_100)!=R_100)
3406 besr.graphics_key_clr=
3407 ((radeon_grkey.ckey.blue &0xF8))
3408 | ((radeon_grkey.ckey.green&0xFC)<<8)
3409 | ((radeon_grkey.ckey.red &0xF8)<<16);
3410 else
3411 #endif
3412 besr.graphics_key_clr=
3413 ((radeon_grkey.ckey.blue &0xF8)>>3)
3414 | ((radeon_grkey.ckey.green&0xFC)<<3)
3415 | ((radeon_grkey.ckey.red &0xF8)<<8);
3416 break;
3417 case 24:
3418 case 32:
3419 besr.graphics_key_clr=
3420 ((radeon_grkey.ckey.blue &0xFF))
3421 | ((radeon_grkey.ckey.green&0xFF)<<8)
3422 | ((radeon_grkey.ckey.red &0xFF)<<16);
3423 break;
3424 default:
3425 besr.ckey_on=0;
3426 besr.graphics_key_msk=0;
3427 besr.graphics_key_clr=0;
3429 #ifdef RAGE128
3430 besr.graphics_key_msk=(1<<dbpp)-1;
3431 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3432 #else
3433 besr.graphics_key_msk=besr.graphics_key_clr;
3434 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3435 #endif
3437 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3439 int dbpp=radeon_vid_get_dbpp();
3440 besr.ckey_on=1;
3442 switch(dbpp)
3444 case 32:
3445 besr.ckey_on=1;
3446 besr.graphics_key_msk=0;
3447 besr.graphics_key_clr=0;
3448 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3449 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3450 0x00ff0000 | /* graphic alpha */
3451 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3452 break;
3453 default:
3454 besr.ckey_on=0;
3455 besr.graphics_key_msk=0;
3456 besr.graphics_key_clr=0;
3457 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3458 result = 1;
3461 else
3463 besr.ckey_on=0;
3464 besr.graphics_key_msk=0;
3465 besr.graphics_key_clr=0;
3466 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3468 radeon_fifo_wait(3);
3469 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3470 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3471 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3472 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3473 return result;
3476 static int radeon_get_gkey(vidix_grkey_t *grkey)
3478 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3479 return(0);
3482 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3484 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3485 return (set_gr_key());
3488 #ifdef RAGE128
3489 VDXDriver rage128_drv = {
3490 "rage128",
3491 #else
3492 VDXDriver radeon_drv = {
3493 "radeon",
3494 #endif
3495 NULL,
3497 .probe = radeon_probe,
3498 .get_caps = radeon_get_caps,
3499 .query_fourcc = radeon_query_fourcc,
3500 .init = radeon_init,
3501 .destroy = radeon_destroy,
3502 .config_playback = radeon_config_playback,
3503 .playback_on = radeon_playback_on,
3504 .playback_off = radeon_playback_off,
3505 .frame_sel = radeon_frame_select,
3506 .get_eq = radeon_get_eq,
3507 .set_eq = radeon_set_eq,
3508 .get_deint = radeon_playback_get_deint,
3509 .set_deint = radeon_playback_set_deint,
3510 .get_gkey = radeon_get_gkey,
3511 .set_gkey = radeon_set_gkey,