vo_glamo: sub.h was moved to sub directory in c9026cb3210205b07e2e068467a18ee40f9259a3
[mplayer/glamo.git] / vidix / radeon_vid.c
blobee68653c2c8589b359f0beabd0c23ea0cf6047aa
1 /*
2 * VIDIX driver for ATI Rage128 and Radeon chipsets.
4 * This file is based on sources from
5 * GATOS (gatos.sf.net) and X11 (www.xfree86.org)
7 * Copyright (C) 2002 Nick Kurshev
8 * support for fglrx drivers by Marcel Naziri (zwobbl@zwobbl.de)
10 * This file is part of MPlayer.
12 * MPlayer is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * MPlayer is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License along
23 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <errno.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32 #include <inttypes.h>
34 #include "config.h"
35 #include "libavutil/common.h"
36 #include "mpbswap.h"
37 #include "pci_ids.h"
38 #include "pci_names.h"
39 #include "vidix.h"
40 #include "fourcc.h"
41 #include "dha.h"
42 #include "radeon.h"
44 #if !defined(RAGE128) && defined(CONFIG_X11)
45 #include <X11/Xlib.h>
46 static uint32_t firegl_shift = 0;
47 #endif
49 #ifdef RAGE128
50 #define RADEON_MSG "[rage128]"
51 #define X_ADJUST 0
52 #else
53 #define RADEON_MSG "[radeon]"
54 #define X_ADJUST (((besr.chip_flags&R_OVL_SHIFT)==R_OVL_SHIFT)?8:0)
55 #ifndef RADEON
56 #define RADEON
57 #endif
58 #endif
60 #define RADEON_ASSERT(msg) printf(RADEON_MSG"################# FATAL:"msg);
62 #define VERBOSE_LEVEL 0
63 static int verbosity = 0;
64 typedef struct bes_registers_s
66 /* base address of yuv framebuffer */
67 uint32_t yuv_base;
68 uint32_t fourcc;
69 uint32_t surf_id;
70 int load_prg_start;
71 int horz_pick_nearest;
72 int vert_pick_nearest;
73 int swap_uv; /* for direct support of bgr fourccs */
74 uint32_t dest_bpp;
75 /* YUV BES registers */
76 uint32_t reg_load_cntl;
77 uint32_t h_inc;
78 uint32_t step_by;
79 uint32_t y_x_start;
80 uint32_t y_x_end;
81 uint32_t v_inc;
82 uint32_t p1_blank_lines_at_top;
83 uint32_t p23_blank_lines_at_top;
84 uint32_t vid_buf_pitch0_value;
85 uint32_t vid_buf_pitch1_value;
86 uint32_t p1_x_start_end;
87 uint32_t p2_x_start_end;
88 uint32_t p3_x_start_end;
89 uint32_t base_addr;
90 uint32_t vid_buf_base_adrs_y[VID_PLAY_MAXFRAMES];
91 uint32_t vid_buf_base_adrs_u[VID_PLAY_MAXFRAMES];
92 uint32_t vid_buf_base_adrs_v[VID_PLAY_MAXFRAMES];
93 uint32_t vid_nbufs;
95 uint32_t p1_v_accum_init;
96 uint32_t p1_h_accum_init;
97 uint32_t p23_v_accum_init;
98 uint32_t p23_h_accum_init;
99 uint32_t scale_cntl;
100 uint32_t exclusive_horz;
101 uint32_t auto_flip_cntl;
102 uint32_t filter_cntl;
103 uint32_t four_tap_coeff[5];
104 uint32_t key_cntl;
105 uint32_t test;
106 /* Configurable stuff */
107 int double_buff;
109 int brightness;
110 int saturation;
112 int ckey_on;
113 uint32_t graphics_key_clr;
114 uint32_t graphics_key_msk;
115 uint32_t ckey_cntl;
116 uint32_t merge_cntl;
118 int deinterlace_on;
119 uint32_t deinterlace_pattern;
121 unsigned chip_flags;
122 } bes_registers_t;
124 typedef struct video_registers_s
126 const char * sname;
127 uint32_t name;
128 uint32_t value;
129 }video_registers_t;
131 static bes_registers_t besr;
132 #define DECLARE_VREG(name) { #name, name, 0 }
133 static const video_registers_t vregs[] =
135 DECLARE_VREG(VIDEOMUX_CNTL),
136 DECLARE_VREG(VIPPAD_MASK),
137 DECLARE_VREG(VIPPAD1_A),
138 DECLARE_VREG(VIPPAD1_EN),
139 DECLARE_VREG(VIPPAD1_Y),
140 DECLARE_VREG(OV0_Y_X_START),
141 DECLARE_VREG(OV0_Y_X_END),
142 DECLARE_VREG(OV1_Y_X_START),
143 DECLARE_VREG(OV1_Y_X_END),
144 DECLARE_VREG(OV0_PIPELINE_CNTL),
145 DECLARE_VREG(OV0_EXCLUSIVE_HORZ),
146 DECLARE_VREG(OV0_EXCLUSIVE_VERT),
147 DECLARE_VREG(OV0_REG_LOAD_CNTL),
148 DECLARE_VREG(OV0_SCALE_CNTL),
149 DECLARE_VREG(OV0_V_INC),
150 DECLARE_VREG(OV0_P1_V_ACCUM_INIT),
151 DECLARE_VREG(OV0_P23_V_ACCUM_INIT),
152 DECLARE_VREG(OV0_P1_BLANK_LINES_AT_TOP),
153 DECLARE_VREG(OV0_P23_BLANK_LINES_AT_TOP),
154 #ifdef RADEON
155 DECLARE_VREG(OV0_BASE_ADDR),
156 #endif
157 DECLARE_VREG(OV0_VID_BUF0_BASE_ADRS),
158 DECLARE_VREG(OV0_VID_BUF1_BASE_ADRS),
159 DECLARE_VREG(OV0_VID_BUF2_BASE_ADRS),
160 DECLARE_VREG(OV0_VID_BUF3_BASE_ADRS),
161 DECLARE_VREG(OV0_VID_BUF4_BASE_ADRS),
162 DECLARE_VREG(OV0_VID_BUF5_BASE_ADRS),
163 DECLARE_VREG(OV0_VID_BUF_PITCH0_VALUE),
164 DECLARE_VREG(OV0_VID_BUF_PITCH1_VALUE),
165 DECLARE_VREG(OV0_AUTO_FLIP_CNTL),
166 DECLARE_VREG(OV0_DEINTERLACE_PATTERN),
167 DECLARE_VREG(OV0_SUBMIT_HISTORY),
168 DECLARE_VREG(OV0_H_INC),
169 DECLARE_VREG(OV0_STEP_BY),
170 DECLARE_VREG(OV0_P1_H_ACCUM_INIT),
171 DECLARE_VREG(OV0_P23_H_ACCUM_INIT),
172 DECLARE_VREG(OV0_P1_X_START_END),
173 DECLARE_VREG(OV0_P2_X_START_END),
174 DECLARE_VREG(OV0_P3_X_START_END),
175 DECLARE_VREG(OV0_FILTER_CNTL),
176 DECLARE_VREG(OV0_FOUR_TAP_COEF_0),
177 DECLARE_VREG(OV0_FOUR_TAP_COEF_1),
178 DECLARE_VREG(OV0_FOUR_TAP_COEF_2),
179 DECLARE_VREG(OV0_FOUR_TAP_COEF_3),
180 DECLARE_VREG(OV0_FOUR_TAP_COEF_4),
181 DECLARE_VREG(OV0_FLAG_CNTL),
182 #ifdef RAGE128
183 DECLARE_VREG(OV0_COLOUR_CNTL),
184 #else
185 DECLARE_VREG(OV0_SLICE_CNTL),
186 #endif
187 DECLARE_VREG(OV0_VID_KEY_CLR),
188 DECLARE_VREG(OV0_VID_KEY_MSK),
189 DECLARE_VREG(OV0_GRAPHICS_KEY_CLR),
190 DECLARE_VREG(OV0_GRAPHICS_KEY_MSK),
191 DECLARE_VREG(OV0_KEY_CNTL),
192 DECLARE_VREG(OV0_TEST),
193 DECLARE_VREG(OV0_LIN_TRANS_A),
194 DECLARE_VREG(OV0_LIN_TRANS_B),
195 DECLARE_VREG(OV0_LIN_TRANS_C),
196 DECLARE_VREG(OV0_LIN_TRANS_D),
197 DECLARE_VREG(OV0_LIN_TRANS_E),
198 DECLARE_VREG(OV0_LIN_TRANS_F),
199 DECLARE_VREG(OV0_GAMMA_0_F),
200 DECLARE_VREG(OV0_GAMMA_10_1F),
201 DECLARE_VREG(OV0_GAMMA_20_3F),
202 DECLARE_VREG(OV0_GAMMA_40_7F),
203 DECLARE_VREG(OV0_GAMMA_380_3BF),
204 DECLARE_VREG(OV0_GAMMA_3C0_3FF),
205 DECLARE_VREG(SUBPIC_CNTL),
206 DECLARE_VREG(SUBPIC_DEFCOLCON),
207 DECLARE_VREG(SUBPIC_Y_X_START),
208 DECLARE_VREG(SUBPIC_Y_X_END),
209 DECLARE_VREG(SUBPIC_V_INC),
210 DECLARE_VREG(SUBPIC_H_INC),
211 DECLARE_VREG(SUBPIC_BUF0_OFFSET),
212 DECLARE_VREG(SUBPIC_BUF1_OFFSET),
213 DECLARE_VREG(SUBPIC_LC0_OFFSET),
214 DECLARE_VREG(SUBPIC_LC1_OFFSET),
215 DECLARE_VREG(SUBPIC_PITCH),
216 DECLARE_VREG(SUBPIC_BTN_HLI_COLCON),
217 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_START),
218 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_END),
219 DECLARE_VREG(SUBPIC_PALETTE_INDEX),
220 DECLARE_VREG(SUBPIC_PALETTE_DATA),
221 DECLARE_VREG(SUBPIC_H_ACCUM_INIT),
222 DECLARE_VREG(SUBPIC_V_ACCUM_INIT),
223 DECLARE_VREG(IDCT_RUNS),
224 DECLARE_VREG(IDCT_LEVELS),
225 DECLARE_VREG(IDCT_AUTH_CONTROL),
226 DECLARE_VREG(IDCT_AUTH),
227 DECLARE_VREG(IDCT_CONTROL),
228 #ifdef RAGE128
229 DECLARE_VREG(BM_FRAME_BUF_OFFSET),
230 DECLARE_VREG(BM_SYSTEM_MEM_ADDR),
231 DECLARE_VREG(BM_COMMAND),
232 DECLARE_VREG(BM_STATUS),
233 DECLARE_VREG(BM_QUEUE_STATUS),
234 DECLARE_VREG(BM_QUEUE_FREE_STATUS),
235 DECLARE_VREG(BM_CHUNK_0_VAL),
236 DECLARE_VREG(BM_CHUNK_1_VAL),
237 DECLARE_VREG(BM_VIP0_BUF),
238 DECLARE_VREG(BM_VIP0_ACTIVE),
239 DECLARE_VREG(BM_VIP1_BUF),
240 DECLARE_VREG(BM_VIP1_ACTIVE),
241 DECLARE_VREG(BM_VIP2_BUF),
242 DECLARE_VREG(BM_VIP2_ACTIVE),
243 DECLARE_VREG(BM_VIP3_BUF),
244 DECLARE_VREG(BM_VIP3_ACTIVE),
245 DECLARE_VREG(BM_VIDCAP_BUF0),
246 DECLARE_VREG(BM_VIDCAP_BUF1),
247 DECLARE_VREG(BM_VIDCAP_BUF2),
248 DECLARE_VREG(BM_VIDCAP_ACTIVE),
249 DECLARE_VREG(BM_GUI),
250 DECLARE_VREG(BM_ABORT)
251 #else
252 DECLARE_VREG(DISP_MERGE_CNTL),
253 DECLARE_VREG(DMA_GUI_TABLE_ADDR),
254 DECLARE_VREG(DMA_GUI_SRC_ADDR),
255 DECLARE_VREG(DMA_GUI_DST_ADDR),
256 DECLARE_VREG(DMA_GUI_COMMAND),
257 DECLARE_VREG(DMA_GUI_STATUS),
258 DECLARE_VREG(DMA_GUI_ACT_DSCRPTR),
259 DECLARE_VREG(DMA_VID_SRC_ADDR),
260 DECLARE_VREG(DMA_VID_DST_ADDR),
261 DECLARE_VREG(DMA_VID_COMMAND),
262 DECLARE_VREG(DMA_VID_STATUS),
263 DECLARE_VREG(DMA_VID_ACT_DSCRPTR),
264 #endif
267 #define R_FAMILY 0x000000FF
268 #define R_100 0x00000001
269 #define R_120 0x00000002
270 #define R_150 0x00000004
271 #define R_200 0x00000008
272 #define R_250 0x00000010
273 #define R_280 0x00000020
274 #define R_300 0x00000040
275 #define R_350 0x00000080
276 #define R_370 0x00000100
277 #define R_380 0x00000200
278 #define R_420 0x00000400
279 #define R_430 0x00000800
280 #define R_480 0x00001000
281 #define R_OVL_SHIFT 0x01000000
282 #define R_INTEGRATED 0x02000000
283 #define R_PCIE 0x04000000
285 typedef struct ati_card_ids_s
287 unsigned short id;
288 unsigned flags;
289 }ati_card_ids_t;
291 static const ati_card_ids_t ati_card_ids[] =
293 #ifdef RAGE128
295 This driver should be compatible with Rage128 (pro) chips.
296 (include adaptive deinterlacing!!!).
297 Moreover: the same logic can be used with Mach64 chips.
298 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
299 but they are incompatible by i/o ports. So if enthusiasts will want
300 then they can redefine OUTREG and INREG macros and redefine OV0_*
301 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
302 fourccs (422 and 420 formats only).
304 /* Rage128 Pro GL */
305 { DEVICE_ATI_RAGE_128_PA_PRO, 0 },
306 { DEVICE_ATI_RAGE_128_PB_PRO, 0 },
307 { DEVICE_ATI_RAGE_128_PC_PRO, 0 },
308 { DEVICE_ATI_RAGE_128_PD_PRO, 0 },
309 { DEVICE_ATI_RAGE_128_PE_PRO, 0 },
310 { DEVICE_ATI_RAGE_128_PF_PRO, 0 },
311 /* Rage128 Pro VR */
312 { DEVICE_ATI_RAGE_128_PG_PRO, 0 },
313 { DEVICE_ATI_RAGE_128_PH_PRO, 0 },
314 { DEVICE_ATI_RAGE_128_PI_PRO, 0 },
315 { DEVICE_ATI_RAGE_128_PJ_PRO, 0 },
316 { DEVICE_ATI_RAGE_128_PK_PRO, 0 },
317 { DEVICE_ATI_RAGE_128_PL_PRO, 0 },
318 { DEVICE_ATI_RAGE_128_PM_PRO, 0 },
319 { DEVICE_ATI_RAGE_128_PN_PRO, 0 },
320 { DEVICE_ATI_RAGE_128_PO_PRO, 0 },
321 { DEVICE_ATI_RAGE_128_PP_PRO, 0 },
322 { DEVICE_ATI_RAGE_128_PQ_PRO, 0 },
323 { DEVICE_ATI_RAGE_128_PR_PRO, 0 },
324 { DEVICE_ATI_RAGE_128_PS_PRO, 0 },
325 { DEVICE_ATI_RAGE_128_PT_PRO, 0 },
326 { DEVICE_ATI_RAGE_128_PU_PRO, 0 },
327 { DEVICE_ATI_RAGE_128_PV_PRO, 0 },
328 { DEVICE_ATI_RAGE_128_PW_PRO, 0 },
329 { DEVICE_ATI_RAGE_128_PX_PRO, 0 },
330 /* Rage128 GL */
331 { DEVICE_ATI_RAGE_128_RE_SG, 0 },
332 { DEVICE_ATI_RAGE_128_RF_SG, 0 },
333 { DEVICE_ATI_RAGE_128_RG, 0 },
334 { DEVICE_ATI_RAGE_128_RK_VR, 0 },
335 { DEVICE_ATI_RAGE_128_RL_VR, 0 },
336 { DEVICE_ATI_RAGE_128_SE_4X, 0 },
337 { DEVICE_ATI_RAGE_128_SF_4X, 0 },
338 { DEVICE_ATI_RAGE_128_SG_4X, 0 },
339 { DEVICE_ATI_RAGE_128_SH, 0 },
340 { DEVICE_ATI_RAGE_128_SK_4X, 0 },
341 { DEVICE_ATI_RAGE_128_SL_4X, 0 },
342 { DEVICE_ATI_RAGE_128_SM_4X, 0 },
343 { DEVICE_ATI_RAGE_128_4X, 0 },
344 { DEVICE_ATI_RAGE_128_PRO, 0 },
345 { DEVICE_ATI_RAGE_128_PRO2, 0 },
346 { DEVICE_ATI_RAGE_128_PRO3, 0 },
347 /* these seem to be based on rage 128 instead of mach64 */
348 { DEVICE_ATI_RAGE_MOBILITY_M3, 0 },
349 { DEVICE_ATI_RAGE_MOBILITY_M32, 0 },
350 #else
351 /* Radeon1 (indeed: Rage 256 Pro ;) */
352 { DEVICE_ATI_RADEON_R100_QD, R_100|R_OVL_SHIFT },
353 { DEVICE_ATI_RADEON_R100_QE, R_100|R_OVL_SHIFT },
354 { DEVICE_ATI_RADEON_R100_QF, R_100|R_OVL_SHIFT },
355 { DEVICE_ATI_RADEON_R100_QG, R_100|R_OVL_SHIFT },
356 { DEVICE_ATI_RADEON_IGP_320, R_150|R_OVL_SHIFT|R_INTEGRATED },
357 { DEVICE_ATI_RADEON_MOBILITY_U1, R_150|R_OVL_SHIFT|R_INTEGRATED },
358 { DEVICE_ATI_RADEON_RV100_QY, R_120|R_OVL_SHIFT },
359 { DEVICE_ATI_RADEON_RV100_QZ, R_120|R_OVL_SHIFT },
360 { DEVICE_ATI_RADEON_MOBILITY_M7, R_150|R_OVL_SHIFT },
361 { DEVICE_ATI_RADEON_RV200_LX, R_150|R_OVL_SHIFT },
362 { DEVICE_ATI_RADEON_MOBILITY_M6, R_120|R_OVL_SHIFT },
363 { DEVICE_ATI_RADEON_MOBILITY_M62, R_120|R_OVL_SHIFT },
364 /* Radeon2 (indeed: Rage 512 Pro ;) */
365 { DEVICE_ATI_R200_BB_RADEON, R_200 },
366 { DEVICE_ATI_R200_BC_RADEON, R_200 },
367 { DEVICE_ATI_RADEON_R200_QH, R_200 },
368 { DEVICE_ATI_RADEON_R200_QI, R_200 },
369 { DEVICE_ATI_RADEON_R200_QJ, R_200 },
370 { DEVICE_ATI_RADEON_R200_QK, R_200 },
371 { DEVICE_ATI_RADEON_R200_QL, R_200 },
372 { DEVICE_ATI_RADEON_R200_QM, R_200 },
373 { DEVICE_ATI_RADEON_R200_QN, R_200 },
374 { DEVICE_ATI_RADEON_R200_QO, R_200 },
375 { DEVICE_ATI_RADEON_R200_QH2, R_200 },
376 { DEVICE_ATI_RADEON_R200_QI2, R_200 },
377 { DEVICE_ATI_RADEON_R200_QJ2, R_200 },
378 { DEVICE_ATI_RADEON_R200_QK2, R_200 },
379 { DEVICE_ATI_RADEON_R200_QL2, R_200 },
380 { DEVICE_ATI_RADEON_RV200_QW, R_150|R_OVL_SHIFT },
381 { DEVICE_ATI_RADEON_RV200_QX, R_150|R_OVL_SHIFT },
382 { DEVICE_ATI_RADEON_IGP330_340_350,R_200|R_INTEGRATED },
383 { DEVICE_ATI_RADEON_IGP_330M_340M_350M,R_200|R_INTEGRATED },
384 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
385 { DEVICE_ATI_RADEON_7000_IGP, R_250|R_OVL_SHIFT|R_INTEGRATED },
386 { DEVICE_ATI_RADEON_MOBILITY_7000, R_250|R_OVL_SHIFT|R_INTEGRATED },
387 { DEVICE_ATI_RADEON_RV250_ID, R_250|R_OVL_SHIFT },
388 { DEVICE_ATI_RADEON_RV250_IE, R_250|R_OVL_SHIFT },
389 { DEVICE_ATI_RADEON_RV250_IF, R_250|R_OVL_SHIFT },
390 { DEVICE_ATI_RADEON_RV250_IG, R_250|R_OVL_SHIFT },
391 { DEVICE_ATI_RADEON_R250_LD, R_250|R_OVL_SHIFT },
392 { DEVICE_ATI_RADEON_R250_LE, R_250|R_OVL_SHIFT },
393 { DEVICE_ATI_RADEON_R250_MOBILITY, R_250|R_OVL_SHIFT },
394 { DEVICE_ATI_RADEON_R250_LG, R_250|R_OVL_SHIFT },
395 { DEVICE_ATI_RV250_RADEON_9000, R_250|R_OVL_SHIFT },
396 { DEVICE_ATI_RADEON_RV250_RADEON2, R_250|R_OVL_SHIFT },
397 // Only 92006 and 92007 tested to actually require this
398 { DEVICE_ATI_RV280_RADEON_9200, R_280|R_OVL_SHIFT },
399 { DEVICE_ATI_RV280_RADEON_92002, R_280|R_OVL_SHIFT },
400 { DEVICE_ATI_RV280_RADEON_92003, R_280|R_OVL_SHIFT },
401 { DEVICE_ATI_RV280_RADEON_92004, R_280|R_OVL_SHIFT },
402 { DEVICE_ATI_RV280_RADEON_92005, R_280|R_OVL_SHIFT },
403 { DEVICE_ATI_RV280_RADEON_92006, R_280|R_OVL_SHIFT },
404 { DEVICE_ATI_RV280_RADEON_92007, R_280|R_OVL_SHIFT },
405 { DEVICE_ATI_M9_5C61_RADEON, R_280|R_OVL_SHIFT },
406 { DEVICE_ATI_M9_5C63_RADEON, R_280|R_OVL_SHIFT },
407 /* Radeon3 (indeed: Rage 1024 Pro ;) */
408 { DEVICE_ATI_R300_AG_FIREGL, R_300 },
409 { DEVICE_ATI_RADEON_R300_ND, R_300 },
410 { DEVICE_ATI_RADEON_R300_NE, R_300 },
411 { DEVICE_ATI_RADEON_R300_NG, R_300 },
412 { DEVICE_ATI_R300_AD_RADEON, R_300 },
413 { DEVICE_ATI_R300_AE_RADEON, R_300 },
414 { DEVICE_ATI_R300_AF_RADEON, R_300 },
415 { DEVICE_ATI_RADEON_9100_IGP2, R_300|R_OVL_SHIFT|R_INTEGRATED },
416 { DEVICE_ATI_RS300M_AGP_RADEON, R_300|R_INTEGRATED },
417 { DEVICE_ATI_RS482_RADEON_XPRESS, R_350|R_INTEGRATED },
418 { DEVICE_ATI_R350_AH_RADEON, R_350 },
419 { DEVICE_ATI_R350_AI_RADEON, R_350 },
420 { DEVICE_ATI_R350_AJ_RADEON, R_350 },
421 { DEVICE_ATI_R350_AK_FIRE, R_350 },
422 { DEVICE_ATI_RADEON_R350_RADEON2, R_350 },
423 { DEVICE_ATI_RADEON_R350_RADEON3, R_350 },
424 { DEVICE_ATI_RV350_NJ_RADEON, R_350 },
425 { DEVICE_ATI_R350_NK_FIRE, R_350 },
426 { DEVICE_ATI_RV350_AP_RADEON, R_350 },
427 { DEVICE_ATI_RV350_AQ_RADEON, R_350 },
428 { DEVICE_ATI_RV350_AR_RADEON, R_350 },
429 { DEVICE_ATI_RV350_AS_RADEON, R_350 },
430 { DEVICE_ATI_RV350_AT_FIRE, R_350 },
431 { DEVICE_ATI_RV350_AU_FIRE, R_350 },
432 { DEVICE_ATI_RV350_AV_FIRE, R_350 },
433 { DEVICE_ATI_RV350_AW_FIRE, R_350 },
434 { DEVICE_ATI_RV350_MOBILITY_RADEON, R_350 },
435 { DEVICE_ATI_RV350_NF_RADEON, R_300 },
436 { DEVICE_ATI_RV350_NJ_RADEON, R_300 },
437 { DEVICE_ATI_RV350_AS_RADEON2, R_350 },
438 { DEVICE_ATI_M10_NQ_RADEON, R_350 },
439 { DEVICE_ATI_M10_NQ_RADEON2, R_350 },
440 { DEVICE_ATI_RV350_MOBILITY_RADEON2, R_350 },
441 { DEVICE_ATI_M10_NS_RADEON, R_350 },
442 { DEVICE_ATI_M10_NT_FIREGL, R_350 },
443 { DEVICE_ATI_M11_NV_FIREGL, R_350 },
444 { DEVICE_ATI_RV370_5B60_RADEON, R_370|R_PCIE },
445 { DEVICE_ATI_RV370_SAPPHIRE_X550, R_370 },
446 { DEVICE_ATI_RV370_5B64_FIREGL, R_370|R_PCIE },
447 { DEVICE_ATI_RV370_5B65_FIREGL, R_370|R_PCIE },
448 { DEVICE_ATI_M24_1P_RADEON, R_370 },
449 { DEVICE_ATI_M22_RADEON_MOBILITY, R_370 },
450 { DEVICE_ATI_M24_1T_FIREGL, R_370 },
451 { DEVICE_ATI_M24_RADEON_MOBILITY, R_370 },
452 { DEVICE_ATI_RV370_RADEON_X300SE, R_370 },
453 { DEVICE_ATI_RV370_SECONDARY_SAPPHIRE, R_370 },
454 { DEVICE_ATI_RV370_5B64_FIREGL2, R_370 },
455 { DEVICE_ATI_RV380_0X3E50_RADEON, R_380|R_PCIE },
456 { DEVICE_ATI_RV380_0X3E54_FIREGL, R_380|R_PCIE },
457 { DEVICE_ATI_RV380_RADEON_X600, R_380|R_PCIE },
458 { DEVICE_ATI_RV380_RADEON_X6002, R_380 },
459 { DEVICE_ATI_RV380_RADEON_X6003, R_380 },
460 { DEVICE_ATI_RV410_FIREGL_V5000, R_420 },
461 { DEVICE_ATI_RV410_FIREGL_V3300, R_420 },
462 { DEVICE_ATI_RV410_RADEON_X700XT, R_420 },
463 { DEVICE_ATI_RV410_RADEON_X700, R_420|R_PCIE },
464 { DEVICE_ATI_RV410_RADEON_X700SE, R_420 },
465 { DEVICE_ATI_RV410_RADEON_X7002, R_420|R_PCIE },
466 { DEVICE_ATI_RV410_RADEON_X7003, R_420 },
467 { DEVICE_ATI_RV410_RADEON_X7004, R_420|R_PCIE },
468 { DEVICE_ATI_RV410_RADEON_X7005, R_420|R_PCIE },
469 { DEVICE_ATI_M26_MOBILITY_FIREGL, R_420 },
470 { DEVICE_ATI_M26_MOBILITY_FIREGL2, R_420 },
471 { DEVICE_ATI_M26_RADEON_MOBILITY, R_420 },
472 { DEVICE_ATI_M26_RADEON_MOBILITY2, R_420 },
473 { DEVICE_ATI_RADEON_MOBILITY_X700, R_420 },
474 { DEVICE_ATI_R420_JH_RADEON, R_420|R_PCIE },
475 { DEVICE_ATI_R420_JI_RADEON, R_420|R_PCIE },
476 { DEVICE_ATI_R420_JJ_RADEON, R_420|R_PCIE },
477 { DEVICE_ATI_R420_JK_RADEON, R_420|R_PCIE },
478 { DEVICE_ATI_R420_JL_RADEON, R_420|R_PCIE },
479 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
480 { DEVICE_ATI_M18_JN_RADEON, R_420|R_PCIE },
481 { DEVICE_ATI_R420_JP_RADEON, R_420|R_PCIE },
482 { DEVICE_ATI_R420_RADEON_X800, R_420|R_PCIE },
483 { DEVICE_ATI_R420_RADEON_X8002, R_420|R_PCIE },
484 { DEVICE_ATI_R420_RADEON_X8003, R_420|R_PCIE },
485 { DEVICE_ATI_R420_RADEON_X8004, R_420|R_PCIE },
486 { DEVICE_ATI_R420_RADEON_X8005, R_420|R_PCIE },
487 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
488 { DEVICE_ATI_R423_5F57_RADEON, R_420|R_PCIE },
489 { DEVICE_ATI_R423_5F57_RADEON2, R_420|R_PCIE },
490 { DEVICE_ATI_R423_UH_RADEON, R_420|R_PCIE },
491 { DEVICE_ATI_R423_UI_RADEON, R_420|R_PCIE },
492 { DEVICE_ATI_R423_UJ_RADEON, R_420|R_PCIE },
493 { DEVICE_ATI_R423_UK_RADEON, R_420|R_PCIE },
494 { DEVICE_ATI_R423_FIRE_GL, R_420|R_PCIE },
495 { DEVICE_ATI_R423_UQ_FIREGL, R_420|R_PCIE },
496 { DEVICE_ATI_R423_UR_FIREGL, R_420|R_PCIE },
497 { DEVICE_ATI_R423_UT_FIREGL, R_420|R_PCIE },
498 { DEVICE_ATI_R423_UI_RADEON2, R_420|R_PCIE },
499 { DEVICE_ATI_R423GL_SE_ATI_FIREGL, R_420|R_PCIE },
500 { DEVICE_ATI_R423_RADEON_X800XT, R_420|R_PCIE },
501 { DEVICE_ATI_RADEON_R423_UK, R_420|R_PCIE },
502 { DEVICE_ATI_M28_RADEON_MOBILITY, R_420 },
503 { DEVICE_ATI_M28_MOBILITY_FIREGL, R_420 },
504 { DEVICE_ATI_MOBILITY_RADEON_X800, R_420 },
505 { DEVICE_ATI_R430_RADEON_X800, R_430|R_PCIE },
506 { DEVICE_ATI_R430_RADEON_X8002, R_430|R_PCIE },
507 { DEVICE_ATI_R430_RADEON_X8003, R_430|R_PCIE },
508 { DEVICE_ATI_R430_RADEON_X8004, R_430|R_PCIE },
509 { DEVICE_ATI_R480_RADEON_X800, R_480 },
510 { DEVICE_ATI_R480_RADEON_X8002, R_480 },
511 { DEVICE_ATI_R480_RADEON_X850XT, R_480 },
512 { DEVICE_ATI_R480_RADEON_X850PRO, R_480 },
513 { DEVICE_ATI_R481_RADEON_X850XT_PE, R_480|R_PCIE },
514 { DEVICE_ATI_R480_RADEON_X850XT2, R_480 },
515 { DEVICE_ATI_R480_RADEON_X850PRO2, R_480 },
516 { DEVICE_ATI_R481_RADEON_X850XT_PE2, R_480|R_PCIE },
517 { DEVICE_ATI_R480_RADEON_X850XT3, R_480|R_PCIE },
518 { DEVICE_ATI_R480_RADEON_X850XT4, R_480|R_PCIE },
519 { DEVICE_ATI_R480_RADEON_X850XT5, R_480|R_PCIE },
520 { DEVICE_ATI_R480_RADEON_X850XT6, R_480|R_PCIE },
521 #endif
525 static void * radeon_mmio_base = 0;
526 static void * radeon_mem_base = 0;
527 static int32_t radeon_overlay_off = 0;
528 static uint32_t radeon_ram_size = 0;
530 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
531 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
533 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr)
534 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr,val)
535 static inline uint32_t INREG (uint32_t addr) {
536 uint32_t tmp = GETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr);
537 return le2me_32(tmp);
539 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr,le2me_32(val))
540 #define OUTREGP(addr,val,mask) \
541 do { \
542 unsigned int _tmp = INREG(addr); \
543 _tmp &= (mask); \
544 _tmp |= (val); \
545 OUTREG(addr, _tmp); \
546 } while (0)
548 static __inline__ uint32_t INPLL(uint32_t addr)
550 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f);
551 return INREG(CLOCK_CNTL_DATA);
554 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \
555 OUTREG(CLOCK_CNTL_DATA, val)
556 #define OUTPLLP(addr,val,mask) \
557 do { \
558 unsigned int _tmp = INPLL(addr); \
559 _tmp &= (mask); \
560 _tmp |= (val); \
561 OUTPLL(addr, _tmp); \
562 } while (0)
564 #ifndef RAGE128
565 enum radeon_montype
567 MT_NONE,
568 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */
569 MT_LCD, /* Liquid Crystal Display */
570 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */
571 MT_CTV, /* Composite TV out (not in VE) */
572 MT_STV /* S-Video TV out (probably in VE only) */
575 typedef struct radeon_info_s
577 int hasCRTC2;
578 int crtDispType;
579 int dviDispType;
580 }rinfo_t;
582 static rinfo_t rinfo;
584 static char * GET_MON_NAME(int type)
586 char *pret;
587 switch(type)
589 case MT_NONE: pret = "no"; break;
590 case MT_CRT: pret = "CRT"; break;
591 case MT_DFP: pret = "DFP"; break;
592 case MT_LCD: pret = "LCD"; break;
593 case MT_CTV: pret = "CTV"; break;
594 case MT_STV: pret = "STV"; break;
595 default: pret = "Unknown";
597 return pret;
600 static void radeon_get_moninfo (rinfo_t *rinfo)
602 unsigned int tmp;
604 tmp = INREG(RADEON_BIOS_4_SCRATCH);
606 if (rinfo->hasCRTC2) {
607 /* primary DVI port */
608 if (tmp & 0x08)
609 rinfo->dviDispType = MT_DFP;
610 else if (tmp & 0x4)
611 rinfo->dviDispType = MT_LCD;
612 else if (tmp & 0x200)
613 rinfo->dviDispType = MT_CRT;
614 else if (tmp & 0x10)
615 rinfo->dviDispType = MT_CTV;
616 else if (tmp & 0x20)
617 rinfo->dviDispType = MT_STV;
619 /* secondary CRT port */
620 if (tmp & 0x2)
621 rinfo->crtDispType = MT_CRT;
622 else if (tmp & 0x800)
623 rinfo->crtDispType = MT_DFP;
624 else if (tmp & 0x400)
625 rinfo->crtDispType = MT_LCD;
626 else if (tmp & 0x1000)
627 rinfo->crtDispType = MT_CTV;
628 else if (tmp & 0x2000)
629 rinfo->crtDispType = MT_STV;
630 } else {
631 rinfo->dviDispType = MT_NONE;
633 tmp = INREG(FP_GEN_CNTL);
635 if (tmp & FP_EN_TMDS)
636 rinfo->crtDispType = MT_DFP;
637 else
638 rinfo->crtDispType = MT_CRT;
641 #endif
643 static uint32_t radeon_vid_get_dbpp( void )
645 uint32_t dbpp,retval;
646 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF;
647 switch(dbpp)
649 case DST_8BPP: retval = 8; break;
650 case DST_15BPP: retval = 15; break;
651 case DST_16BPP: retval = 16; break;
652 case DST_24BPP: retval = 24; break;
653 default: retval=32; break;
655 return retval;
658 static int radeon_is_dbl_scan( void )
660 return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN;
663 static int radeon_is_interlace( void )
665 return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN;
668 static uint32_t radeon_get_xres( void )
670 uint32_t xres,h_total;
671 #ifndef RAGE128
672 if(rinfo.hasCRTC2 &&
673 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
674 h_total = INREG(CRTC2_H_TOTAL_DISP);
675 else
676 #endif
677 h_total = INREG(CRTC_H_TOTAL_DISP);
678 xres = (h_total >> 16) & 0xffff;
679 return (xres + 1)*8;
682 static uint32_t radeon_get_yres( void )
684 uint32_t yres,v_total;
685 #ifndef RAGE128
686 if(rinfo.hasCRTC2 &&
687 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
688 v_total = INREG(CRTC2_V_TOTAL_DISP);
689 else
690 #endif
691 v_total = INREG(CRTC_V_TOTAL_DISP);
692 yres = (v_total >> 16) & 0xffff;
693 return yres + 1;
696 static void radeon_wait_vsync(void)
698 int i;
700 OUTREG(GEN_INT_STATUS, VSYNC_INT_AK);
701 for (i = 0; i < 2000000; i++)
703 if (INREG(GEN_INT_STATUS) & VSYNC_INT) break;
707 #ifdef RAGE128
708 static void _radeon_engine_idle(void);
709 static void _radeon_fifo_wait(unsigned);
710 #define radeon_engine_idle() _radeon_engine_idle()
711 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
712 /* Flush all dirty data in the Pixel Cache to memory. */
713 static __inline__ void radeon_engine_flush ( void )
715 unsigned i;
717 OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL);
718 for (i = 0; i < 2000000; i++) {
719 if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break;
723 /* Reset graphics card to known state. */
724 static void radeon_engine_reset( void )
726 uint32_t clock_cntl_index;
727 uint32_t mclk_cntl;
728 uint32_t gen_reset_cntl;
730 radeon_engine_flush();
732 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
733 mclk_cntl = INPLL(MCLK_CNTL);
735 OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP);
737 gen_reset_cntl = INREG(GEN_RESET_CNTL);
739 OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
740 INREG(GEN_RESET_CNTL);
741 OUTREG(GEN_RESET_CNTL,
742 gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI));
743 INREG(GEN_RESET_CNTL);
745 OUTPLL(MCLK_CNTL, mclk_cntl);
746 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
747 OUTREG(GEN_RESET_CNTL, gen_reset_cntl);
749 #else
751 static __inline__ void radeon_engine_flush ( void )
753 int i;
755 /* initiate flush */
756 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
757 ~RB2D_DC_FLUSH_ALL);
759 for (i=0; i < 2000000; i++) {
760 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
761 break;
765 static void _radeon_engine_idle(void);
766 static void _radeon_fifo_wait(unsigned);
767 #define radeon_engine_idle() _radeon_engine_idle()
768 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
770 static void radeon_engine_reset( void )
772 uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
774 radeon_engine_flush ();
776 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
777 mclk_cntl = INPLL(MCLK_CNTL);
779 OUTPLL(MCLK_CNTL, (mclk_cntl |
780 FORCEON_MCLKA |
781 FORCEON_MCLKB |
782 FORCEON_YCLKA |
783 FORCEON_YCLKB |
784 FORCEON_MC |
785 FORCEON_AIC));
786 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
788 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
789 SOFT_RESET_CP |
790 SOFT_RESET_HI |
791 SOFT_RESET_SE |
792 SOFT_RESET_RE |
793 SOFT_RESET_PP |
794 SOFT_RESET_E2 |
795 SOFT_RESET_RB |
796 SOFT_RESET_HDP);
797 INREG(RBBM_SOFT_RESET);
798 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t)
799 ~(SOFT_RESET_CP |
800 SOFT_RESET_HI |
801 SOFT_RESET_SE |
802 SOFT_RESET_RE |
803 SOFT_RESET_PP |
804 SOFT_RESET_E2 |
805 SOFT_RESET_RB |
806 SOFT_RESET_HDP));
807 INREG(RBBM_SOFT_RESET);
809 OUTPLL(MCLK_CNTL, mclk_cntl);
810 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
811 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
813 return;
815 #endif
816 static void radeon_engine_restore( void )
818 #ifndef RAGE128
819 int pitch64;
820 uint32_t xres,yres,bpp;
821 radeon_fifo_wait(1);
822 xres = radeon_get_xres();
823 yres = radeon_get_yres();
824 bpp = radeon_vid_get_dbpp();
825 /* turn of all automatic flushing - we'll do it all */
826 OUTREG(RB2D_DSTCACHE_MODE, 0);
828 pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6;
830 radeon_fifo_wait(1);
831 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) |
832 (pitch64 << 22));
834 radeon_fifo_wait(1);
835 #if HAVE_BIGENDIAN
836 OUTREGP(DP_DATATYPE,
837 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
838 #else
839 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
840 #endif
842 radeon_fifo_wait(1);
843 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX
844 | DEFAULT_SC_BOTTOM_MAX));
845 radeon_fifo_wait(1);
846 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL)
847 | GMC_BRUSH_SOLID_COLOR
848 | GMC_SRC_DATATYPE_COLOR));
850 radeon_fifo_wait(7);
851 OUTREG(DST_LINE_START, 0);
852 OUTREG(DST_LINE_END, 0);
853 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
854 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
855 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
856 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
857 OUTREG(DP_WRITE_MASK, 0xffffffff);
859 radeon_engine_idle();
860 #endif
862 #ifdef RAGE128
863 static void _radeon_fifo_wait (unsigned entries)
865 unsigned i;
867 for(;;)
869 for (i=0; i<2000000; i++)
870 if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries)
871 return;
872 radeon_engine_reset();
873 radeon_engine_restore();
877 static void _radeon_engine_idle ( void )
879 unsigned i;
881 /* ensure FIFO is empty before waiting for idle */
882 radeon_fifo_wait (64);
883 for(;;)
885 for (i=0; i<2000000; i++) {
886 if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) {
887 radeon_engine_flush ();
888 return;
891 radeon_engine_reset();
892 radeon_engine_restore();
895 #else
896 static void _radeon_fifo_wait (unsigned entries)
898 unsigned i;
900 for(;;)
902 for (i=0; i<2000000; i++)
903 if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries)
904 return;
905 radeon_engine_reset();
906 radeon_engine_restore();
909 static void _radeon_engine_idle ( void )
911 int i;
913 /* ensure FIFO is empty before waiting for idle */
914 radeon_fifo_wait (64);
915 for(;;)
917 for (i=0; i<2000000; i++) {
918 if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) {
919 radeon_engine_flush ();
920 return;
923 radeon_engine_reset();
924 radeon_engine_restore();
927 #endif
929 #ifndef RAGE128
930 /* Reference color space transform data */
931 typedef struct tagREF_TRANSFORM
933 float RefLuma;
934 float RefRCb;
935 float RefRCr;
936 float RefGCb;
937 float RefGCr;
938 float RefBCb;
939 float RefBCr;
940 } REF_TRANSFORM;
942 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
943 static const REF_TRANSFORM trans[2] =
945 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
946 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
948 /****************************************************************************
949 * SetTransform *
950 * Function: Calculates and sets color space transform from supplied *
951 * reference transform, gamma, brightness, contrast, hue and *
952 * saturation. *
953 * Inputs: bright - brightness *
954 * cont - contrast *
955 * sat - saturation *
956 * hue - hue *
957 * red_intensity - intense of red component *
958 * green_intensity - intense of green component *
959 * blue_intensity - intense of blue component *
960 * ref - index to the table of refernce transforms *
961 * Outputs: NONE *
962 ****************************************************************************/
964 static void radeon_set_transform(float bright, float cont, float sat,
965 float hue, float red_intensity,
966 float green_intensity,float blue_intensity,
967 unsigned ref)
969 float OvHueSin, OvHueCos;
970 float CAdjLuma, CAdjOff;
971 float RedAdj,GreenAdj,BlueAdj;
972 float CAdjRCb, CAdjRCr;
973 float CAdjGCb, CAdjGCr;
974 float CAdjBCb, CAdjBCr;
975 float OvLuma, OvROff, OvGOff, OvBOff;
976 float OvRCb, OvRCr;
977 float OvGCb, OvGCr;
978 float OvBCb, OvBCr;
979 float Loff = 64.0;
980 float Coff = 512.0f;
982 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
983 uint32_t dwOvRCb, dwOvRCr;
984 uint32_t dwOvGCb, dwOvGCr;
985 uint32_t dwOvBCb, dwOvBCr;
987 if (ref >= 2) return;
989 OvHueSin = sin((double)hue);
990 OvHueCos = cos((double)hue);
992 CAdjLuma = cont * trans[ref].RefLuma;
993 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
994 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
995 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
996 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
998 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
999 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
1000 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1001 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1002 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1003 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1005 OvLuma = CAdjLuma;
1006 OvRCb = CAdjRCb;
1007 OvRCr = CAdjRCr;
1008 OvGCb = CAdjGCb;
1009 OvGCr = CAdjGCr;
1010 OvBCb = CAdjBCb;
1011 OvBCr = CAdjBCr;
1012 OvROff = RedAdj + CAdjOff -
1013 OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1014 OvGOff = GreenAdj + CAdjOff -
1015 OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1016 OvBOff = BlueAdj + CAdjOff -
1017 OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1019 dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff;
1020 dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff;
1021 dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff;
1022 /* Whatever docs say about R200 having 3.8 format instead of 3.11
1023 as in Radeon is a lie */
1025 dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17;
1026 dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1;
1027 dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17;
1028 dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1;
1029 dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17;
1030 dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1;
1031 dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17;
1033 OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1034 OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1035 OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1036 OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1037 OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1038 OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1041 /* Gamma curve definition */
1042 typedef struct
1044 unsigned int gammaReg;
1045 unsigned int gammaSlope;
1046 unsigned int gammaOffset;
1047 }GAMMA_SETTINGS;
1049 /* Recommended gamma curve parameters */
1050 static const GAMMA_SETTINGS r200_def_gamma[18] =
1052 {OV0_GAMMA_0_F, 0x100, 0x0000},
1053 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1054 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1055 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1056 {OV0_GAMMA_80_BF, 0x100, 0x0100},
1057 {OV0_GAMMA_C0_FF, 0x100, 0x0100},
1058 {OV0_GAMMA_100_13F, 0x100, 0x0200},
1059 {OV0_GAMMA_140_17F, 0x100, 0x0200},
1060 {OV0_GAMMA_180_1BF, 0x100, 0x0300},
1061 {OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
1062 {OV0_GAMMA_200_23F, 0x100, 0x0400},
1063 {OV0_GAMMA_240_27F, 0x100, 0x0400},
1064 {OV0_GAMMA_280_2BF, 0x100, 0x0500},
1065 {OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
1066 {OV0_GAMMA_300_33F, 0x100, 0x0600},
1067 {OV0_GAMMA_340_37F, 0x100, 0x0600},
1068 {OV0_GAMMA_380_3BF, 0x100, 0x0700},
1069 {OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
1072 static const GAMMA_SETTINGS r100_def_gamma[6] =
1074 {OV0_GAMMA_0_F, 0x100, 0x0000},
1075 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1076 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1077 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1078 {OV0_GAMMA_380_3BF, 0x100, 0x0100},
1079 {OV0_GAMMA_3C0_3FF, 0x100, 0x0100}
1082 static void make_default_gamma_correction( void )
1084 size_t i;
1085 if((besr.chip_flags & R_100)==R_100||
1086 (besr.chip_flags & R_120)==R_120||
1087 (besr.chip_flags & R_150)==R_150){
1088 OUTREG(OV0_LIN_TRANS_A, 0x12A00000);
1089 OUTREG(OV0_LIN_TRANS_B, 0x199018FE);
1090 OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0);
1091 OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B);
1092 OUTREG(OV0_LIN_TRANS_E, 0x12A02050);
1093 OUTREG(OV0_LIN_TRANS_F, 0x0000174E);
1094 for(i=0; i<6; i++){
1095 OUTREG(r100_def_gamma[i].gammaReg,
1096 (r100_def_gamma[i].gammaSlope<<16) |
1097 r100_def_gamma[i].gammaOffset);
1100 else{
1101 OUTREG(OV0_LIN_TRANS_A, 0x12a20000);
1102 OUTREG(OV0_LIN_TRANS_B, 0x198a190e);
1103 OUTREG(OV0_LIN_TRANS_C, 0x12a2f9da);
1104 OUTREG(OV0_LIN_TRANS_D, 0xf2fe0442);
1105 OUTREG(OV0_LIN_TRANS_E, 0x12a22046);
1106 OUTREG(OV0_LIN_TRANS_F, 0x175f);
1107 /* Default Gamma,
1108 Of 18 segments for gamma cure, all segments in R200 are programmable,
1109 while only lower 4 and upper 2 segments are programmable in Radeon*/
1110 for(i=0; i<18; i++){
1111 OUTREG(r200_def_gamma[i].gammaReg,
1112 (r200_def_gamma[i].gammaSlope<<16) |
1113 r200_def_gamma[i].gammaOffset);
1117 #endif
1119 static void radeon_vid_make_default(void)
1121 #ifdef RAGE128
1122 besr.saturation = 0x0F;
1123 besr.brightness = 0;
1124 OUTREG(OV0_COLOUR_CNTL,0x000F0F00UL); /* Default brihgtness and saturation for Rage128 */
1125 #else
1126 make_default_gamma_correction();
1127 #endif
1128 besr.deinterlace_pattern = 0x900AAAAA;
1129 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1130 besr.deinterlace_on=1;
1131 besr.double_buff=1;
1132 besr.ckey_on=0;
1133 besr.graphics_key_msk=0;
1134 besr.graphics_key_clr=0;
1135 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
1138 static int find_chip(unsigned chip_id)
1140 unsigned i;
1141 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1143 if(chip_id == ati_card_ids[i].id) return i;
1145 return -1;
1148 static pciinfo_t pci_info;
1149 static int probed=0;
1151 static vidix_capability_t def_cap =
1153 #ifdef RAGE128
1154 "BES driver for Rage128 cards",
1155 #else
1156 "BES driver for Radeon cards",
1157 #endif
1158 "Nick Kurshev",
1159 TYPE_OUTPUT | TYPE_FX,
1160 { 0, 0, 0, 0 },
1161 2048,
1162 2048,
1166 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1167 VENDOR_ATI,
1169 { 0, 0, 0, 0}
1172 #if !defined(RAGE128) && defined(CONFIG_X11)
1173 static void probe_fireGL_driver(void) {
1174 Display *dp = XOpenDisplay ((void*)0);
1175 int n = 0;
1176 char **extlist;
1177 if (dp==NULL) {
1178 return;
1180 extlist = XListExtensions (dp, &n);
1181 XCloseDisplay (dp);
1182 if (extlist) {
1183 int i;
1184 int ext_fgl = 0, ext_fglrx = 0;
1185 for (i = 0; i < n; i++) {
1186 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1187 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1189 if (ext_fgl) {
1190 printf(RADEON_MSG" ATI FireGl driver detected");
1191 firegl_shift = 0x500000;
1192 if (!ext_fglrx) {
1193 printf(", but DRI seems not to be activated\n");
1194 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1196 printf("\n");
1200 #endif
1202 static int radeon_probe(int verbose, int force)
1204 pciinfo_t lst[MAX_PCI_DEVICES];
1205 unsigned i,num_pci;
1206 int err;
1207 verbosity = verbose;
1208 err = pci_scan(lst,&num_pci);
1209 if(err)
1211 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1212 return err;
1214 else
1216 err = ENXIO;
1217 for(i=0;i<num_pci;i++)
1219 if(lst[i].vendor == VENDOR_ATI)
1221 int idx;
1222 const char *dname;
1223 idx = find_chip(lst[i].device);
1224 if(idx == -1 && force == PROBE_NORMAL) continue;
1225 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1226 dname = dname ? dname : "Unknown chip";
1227 printf(RADEON_MSG" Found chip: %s\n",dname);
1228 #if 0
1229 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1231 printf("[radeon] Device is disabled, ignoring\n");
1232 continue;
1234 #endif
1235 memset(&besr,0,sizeof(bes_registers_t));
1236 if(force > PROBE_NORMAL)
1238 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1239 if(idx == -1)
1240 #ifdef RAGE128
1241 printf(RADEON_MSG" Assuming it as Rage128\n");
1242 #else
1243 printf(RADEON_MSG" Assuming it as Radeon1\n");
1244 #endif
1245 besr.chip_flags=R_100|R_OVL_SHIFT;
1247 #if !defined(RAGE128) && defined(CONFIG_X11)
1248 probe_fireGL_driver();
1249 #endif
1250 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1251 def_cap.device_id = lst[i].device;
1252 err = 0;
1253 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1254 probed=1;
1255 break;
1259 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1260 return err;
1263 typedef struct saved_regs_s
1265 uint32_t ov0_vid_key_clr;
1266 uint32_t ov0_vid_key_msk;
1267 uint32_t ov0_graphics_key_clr;
1268 uint32_t ov0_graphics_key_msk;
1269 uint32_t ov0_key_cntl;
1270 uint32_t disp_merge_cntl;
1271 uint32_t config_cntl;
1272 }saved_regs_t;
1273 static saved_regs_t savreg;
1275 static void save_regs( void )
1277 radeon_fifo_wait(6);
1278 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1279 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1280 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1281 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1282 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1283 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1284 #if HAVE_BIGENDIAN
1285 #ifdef RAGE128
1286 savreg.config_cntl = INREG(CONFIG_CNTL);
1287 #else
1288 savreg.config_cntl = INREG(SURFACE_CNTL);
1289 #endif
1290 #endif
1293 static void restore_regs( void )
1295 radeon_fifo_wait(6);
1296 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1297 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1298 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1299 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1300 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1301 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1302 #if HAVE_BIGENDIAN
1303 #ifdef RAGE128
1304 OUTREG(CONFIG_CNTL, savreg.config_cntl);
1305 #else
1306 OUTREG(SURFACE_CNTL, savreg.config_cntl);
1307 #endif
1308 #endif
1312 * Clear swap bits of surface data control regs for bigendian
1314 static void clear_swap(void)
1316 #if HAVE_BIGENDIAN
1317 #ifdef RAGE128
1318 OUTREG(CONFIG_CNTL,
1319 savreg.config_cntl &
1320 ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP));
1321 #else
1322 OUTREG(SURFACE_CNTL,
1323 savreg.config_cntl &
1324 ~(NONSURF_AP0_SWP_32BPP | NONSURF_AP0_SWP_16BPP));
1325 #endif
1326 #endif
1329 static int radeon_init(void)
1331 int err;
1333 if(!probed)
1335 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1336 return EINTR;
1338 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1339 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1340 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1341 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1342 #ifdef RADEON
1343 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1344 if (radeon_ram_size == 0 &&
1345 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1346 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1348 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1349 radeon_ram_size = 8192*1024;
1351 else if (radeon_ram_size == 0 &&
1352 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1354 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1355 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1356 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1358 #else
1359 /* Rage Mobility (rage128) also has memsize bug */
1360 if (radeon_ram_size == 0 &&
1361 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1362 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1364 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1365 radeon_ram_size = 8192*1024;
1367 #endif
1368 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1369 radeon_vid_make_default();
1370 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1371 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1372 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1373 #ifndef RAGE128
1375 memset(&rinfo,0,sizeof(rinfo_t));
1376 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1378 radeon_get_moninfo(&rinfo);
1379 if(rinfo.hasCRTC2) {
1380 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1381 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1383 else
1384 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1386 #endif
1387 save_regs();
1388 clear_swap();
1389 return 0;
1392 static void radeon_destroy(void)
1394 restore_regs();
1395 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1396 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1399 static int radeon_get_caps(vidix_capability_t *to)
1401 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1402 return 0;
1406 Full list of fourcc which are supported by Win2K radeon driver:
1407 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1408 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1410 typedef struct fourcc_desc_s
1412 uint32_t fourcc;
1413 unsigned max_srcw;
1414 }fourcc_desc_t;
1416 static const fourcc_desc_t supported_fourcc[] =
1418 { IMGFMT_Y800, 1567 },
1419 { IMGFMT_YVU9, 1567 },
1420 { IMGFMT_IF09, 1567 },
1421 { IMGFMT_YV12, 1567 },
1422 { IMGFMT_I420, 1567 },
1423 { IMGFMT_IYUV, 1567 },
1424 { IMGFMT_UYVY, 1551 },
1425 { IMGFMT_YUY2, 1551 },
1426 { IMGFMT_YVYU, 1551 },
1427 { IMGFMT_RGB15, 1551 },
1428 { IMGFMT_BGR15, 1551 },
1429 { IMGFMT_RGB16, 1551 },
1430 { IMGFMT_BGR16, 1551 },
1431 { IMGFMT_RGB32, 775 },
1432 { IMGFMT_BGR32, 775 }
1435 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1437 unsigned i;
1438 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1440 if(fourcc==supported_fourcc[i].fourcc)
1441 return 1;
1443 return 0;
1446 static int radeon_query_fourcc(vidix_fourcc_t *to)
1448 if(is_supported_fourcc(to->fourcc))
1450 to->depth = VID_DEPTH_ALL;
1451 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1452 VID_CAP_BLEND;
1453 return 0;
1455 else to->depth = to->flags = 0;
1456 return ENOSYS;
1459 static double H_scale_ratio;
1460 static void radeon_vid_dump_regs( void )
1462 size_t i;
1463 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1464 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1465 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1466 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1467 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1468 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1469 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1470 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1471 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1472 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1473 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1476 static void radeon_vid_stop_video( void )
1478 radeon_engine_idle();
1479 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1480 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1481 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1482 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1483 #ifdef RAGE128
1484 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1485 #else
1486 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1487 #endif
1488 OUTREG(OV0_TEST, 0);
1491 static void radeon_vid_display_video( void )
1493 int bes_flags,force_second;
1494 radeon_fifo_wait(2);
1495 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1496 radeon_engine_idle();
1497 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1498 radeon_fifo_wait(15);
1500 force_second=0;
1502 /* Shutdown capturing */
1503 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1504 OUTREG(CAP0_TRIG_CNTL, 0);
1506 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1507 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1509 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1511 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1512 #ifdef RAGE128
1513 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1514 (besr.saturation << 8) |
1515 (besr.saturation << 16));
1516 #endif
1517 radeon_fifo_wait(2);
1518 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1519 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1520 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1522 OUTREG(OV0_H_INC, besr.h_inc);
1523 OUTREG(OV0_STEP_BY, besr.step_by);
1524 if(force_second)
1526 OUTREG(OV1_Y_X_START, besr.y_x_start);
1527 OUTREG(OV1_Y_X_END, besr.y_x_end);
1529 else
1531 OUTREG(OV0_Y_X_START, besr.y_x_start);
1532 OUTREG(OV0_Y_X_END, besr.y_x_end);
1534 OUTREG(OV0_V_INC, besr.v_inc);
1535 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1536 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1537 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1538 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1539 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1540 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1541 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1542 #ifdef RADEON
1543 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1544 #endif
1545 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1546 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1547 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1548 radeon_fifo_wait(9);
1549 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1550 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1551 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1552 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1553 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1554 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1555 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1557 bes_flags = SCALER_ENABLE |
1558 SCALER_SMART_SWITCH |
1559 SCALER_Y2R_TEMP |
1560 SCALER_PIX_EXPAND;
1561 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1562 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1563 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1564 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1565 #ifdef RAGE128
1566 bes_flags |= SCALER_BURST_PER_PLANE;
1567 #endif
1568 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1569 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1570 if(force_second) bes_flags |= SCALER_USE_OV1;
1571 else bes_flags &= ~SCALER_USE_OV1;
1572 OUTREG(OV0_SCALE_CNTL, bes_flags);
1573 radeon_fifo_wait(6);
1574 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1575 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1576 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1577 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1578 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1579 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1580 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1581 OUTREG(OV0_REG_LOAD_CNTL, 0);
1582 if(verbosity > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1583 if(verbosity > VERBOSE_LEVEL) radeon_vid_dump_regs();
1586 /* Goal of this function: hide RGB background and provide black screen around movie.
1587 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1588 Reverse effect to colorkey */
1589 #ifdef RAGE128
1590 static void radeon_vid_exclusive( void )
1592 /* this function works only with Rage128.
1593 Radeon should has something the same */
1594 unsigned screenw,screenh;
1595 screenw = radeon_get_xres();
1596 screenh = radeon_get_yres();
1597 radeon_fifo_wait(2);
1598 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1599 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1602 static void radeon_vid_non_exclusive( void )
1604 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1606 #endif
1608 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1610 unsigned pitch,spy,spv,spu;
1611 spy = spv = spu = 0;
1612 switch(spitch->y)
1614 case 16:
1615 case 32:
1616 case 64:
1617 case 128:
1618 case 256: spy = spitch->y; break;
1619 default: break;
1621 switch(spitch->u)
1623 case 16:
1624 case 32:
1625 case 64:
1626 case 128:
1627 case 256: spu = spitch->u; break;
1628 default: break;
1630 switch(spitch->v)
1632 case 16:
1633 case 32:
1634 case 64:
1635 case 128:
1636 case 256: spv = spitch->v; break;
1637 default: break;
1639 switch(fourcc)
1641 /* 4:2:0 */
1642 case IMGFMT_IYUV:
1643 case IMGFMT_YV12:
1644 case IMGFMT_I420:
1645 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1646 else pitch = 32;
1647 break;
1648 case IMGFMT_IF09:
1649 case IMGFMT_YVU9:
1650 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1651 else pitch = 64;
1652 break;
1653 default:
1654 if(spy >= 16) pitch = spy;
1655 else pitch = 16;
1656 break;
1658 return pitch;
1661 static void Calc_H_INC_STEP_BY (
1662 int fieldvalue_OV0_SURFACE_FORMAT,
1663 double H_scale_ratio,
1664 int DisallowFourTapVertFiltering,
1665 int DisallowFourTapUVVertFiltering,
1666 uint32_t *val_OV0_P1_H_INC,
1667 uint32_t *val_OV0_P1_H_STEP_BY,
1668 uint32_t *val_OV0_P23_H_INC,
1669 uint32_t *val_OV0_P23_H_STEP_BY,
1670 int *P1GroupSize,
1671 int *P1StepSize,
1672 int *P23StepSize )
1675 double ClocksNeededFor16Pixels;
1677 switch (fieldvalue_OV0_SURFACE_FORMAT)
1679 case 3:
1680 case 4: /*16BPP (ARGB1555 and RGB565) */
1681 /* All colour components are fetched in pairs */
1682 *P1GroupSize = 2;
1683 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1684 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1685 if (H_scale_ratio>=.5)
1687 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1688 /* until we reach .5. P1 and P23 are the same. */
1689 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1690 *val_OV0_P1_H_STEP_BY = 1;
1691 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1692 *val_OV0_P23_H_STEP_BY = 1;
1693 *P1StepSize = 1;
1694 *P23StepSize = 1;
1696 else if (H_scale_ratio>=.25)
1698 /* Step by two */
1699 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1700 *val_OV0_P1_H_STEP_BY = 2;
1701 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1702 *val_OV0_P23_H_STEP_BY = 2;
1703 *P1StepSize = 2;
1704 *P23StepSize = 2;
1706 else if (H_scale_ratio>=.125)
1708 /* Step by four */
1709 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1710 *val_OV0_P1_H_STEP_BY = 3;
1711 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1712 *val_OV0_P23_H_STEP_BY = 3;
1713 *P1StepSize = 4;
1714 *P23StepSize = 4;
1716 else if (H_scale_ratio>=.0625)
1718 /* Step by eight */
1719 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1720 *val_OV0_P1_H_STEP_BY = 4;
1721 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1722 *val_OV0_P23_H_STEP_BY = 4;
1723 *P1StepSize = 8;
1724 *P23StepSize = 8;
1726 else if (H_scale_ratio>=0.03125)
1728 /* Step by sixteen */
1729 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1730 *val_OV0_P1_H_STEP_BY = 5;
1731 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1732 *val_OV0_P23_H_STEP_BY = 5;
1733 *P1StepSize = 16;
1734 *P23StepSize = 16;
1736 else
1738 H_scale_ratio=0.03125;
1739 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1740 *val_OV0_P1_H_STEP_BY = 5;
1741 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1742 *val_OV0_P23_H_STEP_BY = 5;
1743 *P1StepSize = 16;
1744 *P23StepSize = 16;
1746 break;
1747 case 6: /*32BPP RGB */
1748 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1750 /* All colour components are fetched in pairs */
1751 *P1GroupSize = 2;
1752 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1753 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1754 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1755 *val_OV0_P1_H_STEP_BY = 0;
1756 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1757 *val_OV0_P23_H_STEP_BY = 0;
1758 *P1StepSize = 1;
1759 *P23StepSize = 1;
1761 else if (H_scale_ratio>=0.75)
1763 /* Four G colour components are fetched at once */
1764 *P1GroupSize = 4;
1765 /* R and B colour components are fetched in pairs */
1766 /* With two tap filtering, we can generate four colour components every clock. */
1767 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1768 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1769 *val_OV0_P1_H_STEP_BY = 1;
1770 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1771 *val_OV0_P23_H_STEP_BY = 1;
1772 *P1StepSize = 1;
1773 *P23StepSize = 1;
1775 else if (H_scale_ratio>=0.375)
1777 /* Step by two. */
1778 /* Four G colour components are fetched at once */
1779 *P1GroupSize = 4;
1780 /* R and B colour components are fetched in pairs */
1781 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1782 *val_OV0_P1_H_STEP_BY = 2;
1783 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1784 *val_OV0_P23_H_STEP_BY = 2;
1785 *P1StepSize = 2;
1786 *P23StepSize = 2;
1788 else if (H_scale_ratio>=0.25)
1790 /* Step by two. */
1791 /* Four G colour components are fetched at once */
1792 *P1GroupSize = 4;
1793 /* R and B colour components are fetched in pairs */
1794 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1795 *val_OV0_P1_H_STEP_BY = 2;
1796 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1797 *val_OV0_P23_H_STEP_BY = 3;
1798 *P1StepSize = 2;
1799 *P23StepSize = 4;
1801 else if (H_scale_ratio>=0.1875)
1803 /* Step by four */
1804 /* Four G colour components are fetched at once */
1805 *P1GroupSize = 4;
1806 /* R and B colour components are fetched in pairs */
1807 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1808 *val_OV0_P1_H_STEP_BY = 3;
1809 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1810 *val_OV0_P23_H_STEP_BY = 3;
1811 *P1StepSize = 4;
1812 *P23StepSize = 4;
1814 else if (H_scale_ratio>=0.125)
1816 /* Step by four */
1817 /* Four G colour components are fetched at once */
1818 *P1GroupSize = 4;
1819 /* R and B colour components are fetched in pairs */
1820 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1821 *val_OV0_P1_H_STEP_BY = 3;
1822 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1823 *val_OV0_P23_H_STEP_BY = 4;
1824 *P1StepSize = 4;
1825 *P23StepSize = 8;
1827 else if (H_scale_ratio>=0.09375)
1829 /* Step by eight */
1830 /* Four G colour components are fetched at once */
1831 *P1GroupSize = 4;
1832 /* R and B colour components are fetched in pairs */
1833 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1834 *val_OV0_P1_H_STEP_BY = 4;
1835 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1836 *val_OV0_P23_H_STEP_BY = 4;
1837 *P1StepSize = 8;
1838 *P23StepSize = 8;
1840 else if (H_scale_ratio>=0.0625)
1842 /* Step by eight */
1843 /* Four G colour components are fetched at once */
1844 *P1GroupSize = 4;
1845 /* R and B colour components are fetched in pairs */
1846 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1847 *val_OV0_P1_H_STEP_BY = 5;
1848 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1849 *val_OV0_P23_H_STEP_BY = 5;
1850 *P1StepSize = 16;
1851 *P23StepSize = 16;
1853 else
1855 H_scale_ratio=0.0625;
1856 *P1GroupSize = 4;
1857 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1858 *val_OV0_P1_H_STEP_BY = 5;
1859 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1860 *val_OV0_P23_H_STEP_BY = 5;
1861 *P1StepSize = 16;
1862 *P23StepSize = 16;
1864 break;
1865 case 9:
1866 /*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. */
1867 /* four tap on both (unless Y is too wide) */
1868 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1869 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1870 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1871 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1872 { /*0.75 */
1873 /* Colour components are fetched in pairs */
1874 *P1GroupSize = 2;
1875 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1876 *val_OV0_P1_H_STEP_BY = 0;
1877 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1878 *val_OV0_P23_H_STEP_BY = 0;
1879 *P1StepSize = 1;
1880 *P23StepSize = 1;
1882 /* two tap on Y (because it is too big for four tap), four tap on UV */
1883 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1884 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1885 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1886 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1887 { /*0.75 */
1888 *P1GroupSize = 4;
1889 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1890 *val_OV0_P1_H_STEP_BY = 1;
1891 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1892 *val_OV0_P23_H_STEP_BY = 0;
1893 *P1StepSize = 1;
1894 *P23StepSize = 1;
1896 /* We scale the Y with the four tap filters, but UV's are generated
1897 with dual two tap configuration. */
1898 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1899 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1900 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1901 !DisallowFourTapVertFiltering)
1902 { /*0.625 */
1903 *P1GroupSize = 2;
1904 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1905 *val_OV0_P1_H_STEP_BY = 0;
1906 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1907 *val_OV0_P23_H_STEP_BY = 1;
1908 *P1StepSize = 1;
1909 *P23StepSize = 1;
1911 /* We scale the Y, U, and V with the two tap filters */
1912 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1913 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1914 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1915 { /*0.375 */
1916 *P1GroupSize = 4;
1917 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1918 *val_OV0_P1_H_STEP_BY = 1;
1919 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1920 *val_OV0_P23_H_STEP_BY = 1;
1921 *P1StepSize = 1;
1922 *P23StepSize = 1;
1924 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1925 thus we won't drop Y's yet. */
1926 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1927 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1928 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1929 { /*>=0.3125 and >.333333~ */
1930 *P1GroupSize = 4;
1931 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1932 *val_OV0_P1_H_STEP_BY = 1;
1933 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1934 *val_OV0_P23_H_STEP_BY = 2;
1935 *P1StepSize = 1;
1936 *P23StepSize = 2;
1938 /* We step the Y, U, and V by two. */
1939 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1940 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1941 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1943 *P1GroupSize = 4;
1944 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1945 *val_OV0_P1_H_STEP_BY = 2;
1946 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1947 *val_OV0_P23_H_STEP_BY = 2;
1948 *P1StepSize = 2;
1949 *P23StepSize = 2;
1951 /* We step the Y by two and the U and V by four. */
1952 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1953 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1954 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1956 *P1GroupSize = 4;
1957 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1958 *val_OV0_P1_H_STEP_BY = 2;
1959 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1960 *val_OV0_P23_H_STEP_BY = 3;
1961 *P1StepSize = 2;
1962 *P23StepSize = 4;
1964 /* We step the Y, U, and V by four. */
1965 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
1966 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
1967 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1969 *P1GroupSize = 4;
1970 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1971 *val_OV0_P1_H_STEP_BY = 3;
1972 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1973 *val_OV0_P23_H_STEP_BY = 3;
1974 *P1StepSize = 4;
1975 *P23StepSize = 4;
1977 /* 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 */
1979 /* We step the Y, U, and V by eight. */
1980 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
1981 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1982 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
1984 *P1GroupSize = 4;
1985 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1986 *val_OV0_P1_H_STEP_BY = 4;
1987 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
1988 *val_OV0_P23_H_STEP_BY = 4;
1989 *P1StepSize = 8;
1990 *P23StepSize = 8;
1992 /* We step the Y by eight and the U and V by sixteen. */
1993 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
1994 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1995 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1997 *P1GroupSize = 4;
1998 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1999 *val_OV0_P1_H_STEP_BY = 4;
2000 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2001 *val_OV0_P23_H_STEP_BY = 5;
2002 *P1StepSize = 8;
2003 *P23StepSize = 16;
2005 /* We step the Y, U, and V by sixteen. */
2006 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
2007 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
2008 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
2010 *P1GroupSize = 4;
2011 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2012 *val_OV0_P1_H_STEP_BY = 5;
2013 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2014 *val_OV0_P23_H_STEP_BY = 5;
2015 *P1StepSize = 16;
2016 *P23StepSize = 16;
2018 else
2020 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
2021 *P1GroupSize = 4;
2022 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2023 *val_OV0_P1_H_STEP_BY = 5;
2024 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
2025 *val_OV0_P23_H_STEP_BY = 5;
2026 *P1StepSize = 16;
2027 *P23StepSize = 16;
2029 break;
2030 case 10:
2031 case 11:
2032 case 12:
2033 case 13:
2034 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2035 /* We scale the Y, U, and V with the four tap filters */
2036 /* four tap on both (unless Y is too wide) */
2037 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2038 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2039 { /*0.75 */
2040 *P1GroupSize = 2;
2041 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2042 *val_OV0_P1_H_STEP_BY = 0;
2043 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2044 *val_OV0_P23_H_STEP_BY = 0;
2045 *P1StepSize = 1;
2046 *P23StepSize = 1;
2048 /* two tap on Y (because it is too big for four tap), four tap on UV */
2049 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2050 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2051 { /*0.75 */
2052 *P1GroupSize = 4;
2053 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2054 *val_OV0_P1_H_STEP_BY = 1;
2055 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2056 *val_OV0_P23_H_STEP_BY = 0;
2057 *P1StepSize = 1;
2058 *P23StepSize = 1;
2060 /* We scale the Y with the four tap filters, but UV's are generated
2061 with dual two tap configuration. */
2062 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2063 !DisallowFourTapVertFiltering)
2064 { /*0.625 */
2065 *P1GroupSize = 2;
2066 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2067 *val_OV0_P1_H_STEP_BY = 0;
2068 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2069 *val_OV0_P23_H_STEP_BY = 1;
2070 *P1StepSize = 1;
2071 *P23StepSize = 1;
2073 /* We scale the Y, U, and V with the two tap filters */
2074 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2075 { /*0.375 */
2076 *P1GroupSize = 4;
2077 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2078 *val_OV0_P1_H_STEP_BY = 1;
2079 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2080 *val_OV0_P23_H_STEP_BY = 1;
2081 *P1StepSize = 1;
2082 *P23StepSize = 1;
2084 /* We scale step the U and V by two to allow more bandwidth for
2085 fetching Y's, thus we won't drop Y's yet. */
2086 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2087 { /*0.312 */
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*2)) * (1<<0xc) + 0.5);
2092 *val_OV0_P23_H_STEP_BY = 2;
2093 *P1StepSize = 1;
2094 *P23StepSize = 2;
2096 /* We step the Y, U, and V by two. */
2097 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2099 *P1GroupSize = 4;
2100 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2101 *val_OV0_P1_H_STEP_BY = 2;
2102 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2103 *val_OV0_P23_H_STEP_BY = 2;
2104 *P1StepSize = 2;
2105 *P23StepSize = 2;
2107 /* We step the Y by two and the U and V by four. */
2108 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2110 *P1GroupSize = 4;
2111 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2112 *val_OV0_P1_H_STEP_BY = 2;
2113 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2114 *val_OV0_P23_H_STEP_BY = 3;
2115 *P1StepSize = 2;
2116 *P23StepSize = 4;
2118 /* We step the Y, U, and V by four. */
2119 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2121 *P1GroupSize = 4;
2122 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2123 *val_OV0_P1_H_STEP_BY = 3;
2124 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2125 *val_OV0_P23_H_STEP_BY = 3;
2126 *P1StepSize = 4;
2127 *P23StepSize = 4;
2129 /* We step the Y by four and the U and V by eight. */
2130 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2131 (fieldvalue_OV0_SURFACE_FORMAT==10))
2133 *P1GroupSize = 4;
2134 /* Can't mix step by 3 and step by 4 for packed modes */
2135 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2136 *val_OV0_P1_H_STEP_BY = 3;
2137 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2138 *val_OV0_P23_H_STEP_BY = 4;
2139 *P1StepSize = 4;
2140 *P23StepSize = 8;
2142 /* We step the Y, U, and V by eight. */
2143 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2145 *P1GroupSize = 4;
2146 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2147 *val_OV0_P1_H_STEP_BY = 4;
2148 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2149 *val_OV0_P23_H_STEP_BY = 4;
2150 *P1StepSize = 8;
2151 *P23StepSize = 8;
2153 /* We step the Y by eight and the U and V by sixteen. */
2154 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2156 *P1GroupSize = 4;
2157 /* Step by 5 not supported for packed modes */
2158 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2159 *val_OV0_P1_H_STEP_BY = 4;
2160 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2161 *val_OV0_P23_H_STEP_BY = 5;
2162 *P1StepSize = 8;
2163 *P23StepSize = 16;
2165 /* We step the Y, U, and V by sixteen. */
2166 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2167 (fieldvalue_OV0_SURFACE_FORMAT==10))
2169 *P1GroupSize = 4;
2170 /* Step by 5 not supported for packed modes */
2171 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2172 *val_OV0_P1_H_STEP_BY = 5;
2173 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2174 *val_OV0_P23_H_STEP_BY = 5;
2175 *P1StepSize = 16;
2176 *P23StepSize = 16;
2178 else
2180 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2182 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2183 *P1GroupSize = 4;
2184 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2185 *val_OV0_P1_H_STEP_BY = 5;
2186 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2187 *val_OV0_P23_H_STEP_BY = 5;
2188 *P1StepSize = 16;
2189 *P23StepSize = 16;
2191 else
2193 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2194 *P1GroupSize = 4;
2195 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2196 *val_OV0_P1_H_STEP_BY = 4;
2197 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2198 *val_OV0_P23_H_STEP_BY = 4;
2199 *P1StepSize = 8;
2200 *P23StepSize = 8;
2203 break;
2204 default: break;
2207 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2208 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2211 /* ********************************************************* */
2212 /* ** Setup Black Bordering */
2213 /* ********************************************************* */
2215 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2217 double tempBLANK_LINES_AT_TOP;
2218 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2219 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2220 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2222 if (floor(config->src.y)<0) {
2223 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2224 TopLine = 0;
2226 else {
2227 tempBLANK_LINES_AT_TOP = 0;
2228 TopLine = (int)floor(config->src.y);
2230 /* Round rSrcBottom up and subtract one */
2231 if (ceil(config->src.y+config->src.h) > config->src.h)
2233 BottomLine = config->src.h - 1;
2235 else
2237 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2240 if (BottomLine >= TopLine)
2242 SourceLinesUsed = BottomLine - TopLine + 1;
2244 else
2246 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2247 SourceLinesUsed = 1;
2251 int SourceHeightInPixels;
2252 SourceHeightInPixels = BottomLine - TopLine + 1;
2255 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2256 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2258 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2259 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2260 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2262 if (BottomUVLine >= TopUVLine)
2264 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2266 else
2268 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2269 SourceUVLinesUsed = 1;
2271 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2272 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2273 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2274 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2275 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2276 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2280 static void ComputeXStartEnd(
2281 int is_400,
2282 uint32_t LeftPixel,uint32_t LeftUVPixel,
2283 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2284 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2285 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2286 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2288 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2289 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2290 /* 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. */
2292 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2293 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2295 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2296 switch (besr.surf_id)
2298 case 9:
2299 case 10:
2300 case 13:
2301 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2302 /* a multiple of a power of two when decimating */
2303 val_OV0_P2_X_START = (int)LeftUVPixel %
2304 (MemWordsInBytes/BytesPerUVPixel);
2305 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2306 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2307 break;
2308 case 11:
2309 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2310 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2311 break;
2312 case 3:
2313 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2314 /* This value is needed only to allow proper setting of */
2315 /* val_OV0_PRESHIFT_P23_TO */
2316 /* val_OV0_P2_X_END = 0; */
2317 break;
2318 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2319 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2320 break;
2321 default: /* insert debug statement here. */
2322 RADEON_ASSERT("unknown fourcc\n");
2323 break;
2325 val_OV0_P3_X_START = val_OV0_P2_X_START;
2326 val_OV0_P3_X_END = val_OV0_P2_X_END;
2328 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2329 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2330 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2331 if(is_400)
2333 besr.p2_x_start_end = 0;
2334 besr.p3_x_start_end = 0;
2336 *p1_x_start = val_OV0_P1_X_START;
2337 *p2_x_start = val_OV0_P2_X_START;
2340 static void ComputeAccumInit(
2341 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2342 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2343 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2344 uint32_t CRT_V_INC,
2345 uint32_t P1GroupSize, uint32_t P23GroupSize,
2346 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2347 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2349 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2350 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2351 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2352 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2353 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2354 /* the distance (in source pixel coordinates) to the center of the first */
2355 /* destination pixel. Need to add additional pixels depending on how many pixels */
2356 /* are fetched at a time and how many pixels in a set are masked. */
2357 /* P23 values are always fetched in groups of two or four. If the start */
2358 /* pixel does not fall on the boundary, then we need to shift preshift for */
2359 /* some additional pixels */
2362 double ExtraHalfPixel;
2363 double tempAdditionalShift;
2364 double tempP1HStartPoint;
2365 double tempP23HStartPoint;
2366 double tempP1Init;
2367 double tempP23Init;
2369 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2370 else ExtraHalfPixel = 0.0;
2371 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2372 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2373 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2375 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2376 /* need to shift an additional pixel */
2377 /* Note that if the pitch is a multiple of two, and if we store fields using */
2378 /* the traditional planer format where the V plane and the U plane share the */
2379 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2380 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2381 /* it is a requirement that the U and V start on the same polarity byte */
2382 /* (even or odd). */
2383 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2384 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2385 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2386 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2387 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2388 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2389 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2392 /* ************************************************************** */
2393 /* ** Calculate values for initializing the vertical accumulators */
2394 /* ************************************************************** */
2397 double ExtraHalfLine;
2398 double ExtraFullLine;
2399 double tempP1VStartPoint;
2400 double tempP23VStartPoint;
2402 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2403 else ExtraHalfLine = 0.0;
2405 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2406 else ExtraFullLine = 0.0;
2408 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2409 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2411 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2413 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2415 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2416 else ExtraFullLine = 0.0;
2418 switch (besr.surf_id)
2420 case 10:
2421 case 13:
2422 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2423 ((float)CRT_V_INC / (1<<0xe));
2424 break;
2425 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2426 ((float)CRT_V_INC / (1<<0xf));
2427 break;
2428 case 3:
2429 case 4:
2430 case 6:
2431 case 11:
2432 case 12: tempP23VStartPoint = 0;
2433 break;
2434 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2435 break;
2438 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2440 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2443 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2445 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2446 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2447 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2448 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2451 typedef struct RangeAndCoefSet {
2452 double Range;
2453 signed char CoefSet[5][4];
2454 } RANGEANDCOEFSET;
2456 /* Filter Setup Routine */
2457 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2459 static const RANGEANDCOEFSET ArrayOfSets[] = {
2460 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2461 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2462 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2463 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2464 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2465 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2466 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2467 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2468 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2469 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2470 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2471 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2472 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2473 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2474 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2475 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2476 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2477 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2478 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2479 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2480 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2481 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2482 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2483 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2484 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2485 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2486 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2487 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2488 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2489 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2490 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2491 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2492 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2493 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2494 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2495 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2496 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2497 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2498 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2499 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2500 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2501 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2502 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2503 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2504 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2505 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2506 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2507 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2508 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2509 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2510 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2511 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2512 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2513 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2514 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2515 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2516 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2517 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2518 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2519 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2520 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2521 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2522 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2523 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2524 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2525 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2526 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2527 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2528 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2529 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2530 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2531 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2532 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2533 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2534 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2535 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2538 double DSR;
2540 unsigned ArrayElement;
2542 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2543 if (DSR<.25) DSR=.25;
2544 if (DSR>1) DSR=1;
2546 ArrayElement = (int)((DSR-0.25) * 100);
2547 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2548 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2549 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2550 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2551 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2552 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2553 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2554 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2555 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2556 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2557 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2558 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2559 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2560 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2561 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2562 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2563 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2564 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2565 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2566 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2568 For more details, refer to Microsoft's draft of PC99.
2572 /* The minimal value of horizontal scale ratio when hard coded coefficients
2573 are suitable for the best quality. */
2574 /* FIXME: Should it be 0.9 for Rage128 ??? */
2575 static const double MinHScaleHard=0.75;
2577 static int radeon_vid_init_video( vidix_playback_t *config )
2579 double V_scale_ratio;
2580 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2581 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;
2582 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2583 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2584 uint32_t CRT_V_INC;
2585 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2586 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2587 uint32_t PageSizeInBytes,OV0LB_Rows;
2588 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2589 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2590 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2591 int is_400,is_410,is_420,best_pitch,mpitch;
2592 int horz_repl_factor,interlace_factor;
2593 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2594 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2596 radeon_vid_stop_video();
2597 left = config->src.x << 16;
2598 top = config->src.y << 16;
2599 src_h = config->src.h;
2600 src_w = config->src.w;
2601 is_400 = is_410 = is_420 = 0;
2602 if(config->fourcc == IMGFMT_YV12 ||
2603 config->fourcc == IMGFMT_I420 ||
2604 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2605 if(config->fourcc == IMGFMT_YVU9 ||
2606 config->fourcc == IMGFMT_IF09) is_410 = 1;
2607 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2608 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2609 mpitch = best_pitch-1;
2610 BytesPerOctWord = 16;
2611 LogMemWordsInBytes = 4;
2612 MemWordsInBytes = 1<<LogMemWordsInBytes;
2613 LogTileWidthInMemWords = 2;
2614 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2615 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2616 LogTileHeight = 4;
2617 TileHeight = 1<<LogTileHeight;
2618 PageSizeInBytes = 64*MemWordsInBytes;
2619 OV0LB_Rows = 96;
2620 h_inc = 1;
2621 switch(config->fourcc)
2623 /* 4:0:0*/
2624 case IMGFMT_Y800:
2625 /* 4:1:0*/
2626 case IMGFMT_YVU9:
2627 case IMGFMT_IF09:
2628 /* 4:2:0 */
2629 case IMGFMT_IYUV:
2630 case IMGFMT_YV12:
2631 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2632 config->dest.pitch.y =
2633 config->dest.pitch.u =
2634 config->dest.pitch.v = best_pitch;
2635 break;
2636 /* RGB 4:4:4:4 */
2637 case IMGFMT_RGB32:
2638 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2639 config->dest.pitch.y =
2640 config->dest.pitch.u =
2641 config->dest.pitch.v = best_pitch;
2642 break;
2643 /* 4:2:2 */
2645 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2646 pitch = ((src_w*2) + mpitch) & ~mpitch;
2647 config->dest.pitch.y =
2648 config->dest.pitch.u =
2649 config->dest.pitch.v = best_pitch;
2650 break;
2652 besr.load_prg_start=0;
2653 besr.swap_uv=0;
2654 switch(config->fourcc)
2656 case IMGFMT_RGB15:
2657 besr.swap_uv=1;
2658 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2659 besr.load_prg_start = 1;
2660 break;
2661 case IMGFMT_RGB16:
2662 besr.swap_uv=1;
2663 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2664 besr.load_prg_start = 1;
2665 break;
2666 case IMGFMT_RGB32:
2667 besr.swap_uv=1;
2668 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2669 besr.load_prg_start = 1;
2670 break;
2671 /* 4:1:0*/
2672 case IMGFMT_IF09:
2673 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2674 break;
2675 /* 4:0:0*/
2676 case IMGFMT_Y800:
2677 /* 4:2:0 */
2678 case IMGFMT_IYUV:
2679 case IMGFMT_I420:
2680 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2681 break;
2682 /* 4:2:2 */
2683 case IMGFMT_YVYU:
2684 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2685 break;
2686 case IMGFMT_YUY2:
2687 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2688 break;
2690 switch (besr.surf_id)
2692 case 3:
2693 case 4:
2694 case 11:
2695 case 12: BytesPerPixel = 2;
2696 break;
2697 case 6: BytesPerPixel = 4;
2698 break;
2699 case 9:
2700 case 10:
2701 case 13:
2702 case 14: BytesPerPixel = 1;
2703 break;
2704 default: BytesPerPixel = 0;/*insert a debug statement here. */
2705 break;
2707 switch (besr.surf_id)
2709 case 3:
2710 case 4: BytesPerUVPixel = 0;
2711 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2712 case 11:
2713 case 12: BytesPerUVPixel = 2;
2714 break;
2715 case 6: BytesPerUVPixel = 0;
2716 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2717 case 9:
2718 case 10: BytesPerUVPixel = 1;
2719 break;
2720 case 13:
2721 case 14: BytesPerUVPixel = 2;
2722 break;
2723 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2724 break;
2727 switch (besr.surf_id)
2729 case 3:
2730 case 4:
2731 case 6: HorzUVSubSample = 1;
2732 break;
2733 case 9: HorzUVSubSample = 4;
2734 break;
2735 case 10:
2736 case 11:
2737 case 12:
2738 case 13:
2739 case 14: HorzUVSubSample = 2;
2740 break;
2741 default: HorzUVSubSample = 0;/* insert debug statement here. */
2742 break;
2744 switch (besr.surf_id)
2746 case 3:
2747 case 4:
2748 case 6:
2749 case 11:
2750 case 12: VertUVSubSample = 1;
2751 break;
2752 case 9: VertUVSubSample = 4;
2753 break;
2754 case 10:
2755 case 13:
2756 case 14: VertUVSubSample = 2;
2757 break;
2758 default: VertUVSubSample = 0;/* insert debug statment here. */
2759 break;
2761 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2762 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2763 LeftPixel = config->src.x;
2764 RightPixel = config->src.w-1;
2765 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2766 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2767 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2768 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2769 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2770 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2771 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2772 SourceWidthInPixels = (int)(config->src.w + 1);
2773 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2775 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2776 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2777 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2778 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2779 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2780 MemWordsInBytes) + 1);
2782 switch (besr.surf_id)
2784 case 9:
2785 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2787 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2789 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2791 DisallowFourTapVertFiltering = 1;
2794 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2796 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2798 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2800 DisallowFourTapUVVertFiltering = 1;
2803 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2805 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2807 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2809 DisallowFourTapUVVertFiltering = 1;
2811 break;
2812 case 13:
2813 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2815 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2817 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2819 DisallowFourTapVertFiltering = 1;
2822 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2824 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2826 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2828 DisallowFourTapUVVertFiltering = 1;
2830 break;
2831 case 3:
2832 case 4:
2833 case 6:
2834 case 11:
2835 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2837 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2839 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2841 DisallowFourTapVertFiltering = 1;
2843 break;
2844 default: /* insert debug statement here. */
2845 break;
2847 dest_w = config->dest.w;
2848 dest_h = config->dest.h;
2849 if(radeon_is_dbl_scan()) dest_h *= 2;
2850 besr.dest_bpp = radeon_vid_get_dbpp();
2851 besr.fourcc = config->fourcc;
2852 if(radeon_is_interlace()) interlace_factor = 2;
2853 else interlace_factor = 1;
2854 /* TODO: must be checked in doublescan mode!!! */
2855 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2857 /* Force the overlay clock on for integrated chips */
2858 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2860 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2861 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2862 V_scale_ratio = (double)(dest_h+1)/src_h;
2863 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2865 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2866 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2868 else
2869 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2871 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2872 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2874 else
2876 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2877 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2879 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2880 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2881 CRT_V_INC = besr.v_inc/interlace_factor;
2882 besr.v_inc <<= 8;
2884 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2885 int P1GroupSize = 0;
2886 int P23GroupSize;
2887 int P1StepSize = 0;
2888 int P23StepSize = 0;
2890 Calc_H_INC_STEP_BY(
2891 besr.surf_id,
2892 H_scale_ratio,
2893 DisallowFourTapVertFiltering,
2894 DisallowFourTapUVVertFiltering,
2895 &val_OV0_P1_H_INC,
2896 &val_OV0_P1_H_STEP_BY,
2897 &val_OV0_P23_H_INC,
2898 &val_OV0_P23_H_STEP_BY,
2899 &P1GroupSize,
2900 &P1StepSize,
2901 &P23StepSize);
2903 if(H_scale_ratio > MinHScaleHard)
2905 h_inc = (src_w << 12) / dest_w;
2906 besr.step_by = 0x0101;
2907 switch (besr.surf_id)
2909 case 3:
2910 case 4:
2911 case 6:
2912 besr.h_inc = (h_inc)|(h_inc<<16);
2913 break;
2914 case 9:
2915 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2916 break;
2917 default:
2918 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2919 break;
2923 P23GroupSize = 2; /* Current vaue for all modes */
2925 besr.horz_pick_nearest=0;
2926 DoNotUseMostRecentlyFetchedLine=0;
2927 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2928 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2929 besr.vert_pick_nearest = 1;
2930 else
2931 besr.vert_pick_nearest = 0;
2933 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2934 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2935 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2937 if(H_scale_ratio > MinHScaleHard)
2939 unsigned tmp;
2940 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2941 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2942 ((tmp << 12) & 0xf0000000);
2944 tmp = (top & 0x0000ffff) + 0x00018000;
2945 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2946 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2947 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2948 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2949 ((tmp << 12) & 0x70000000);
2951 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2952 besr.p23_v_accum_init = (is_420||is_410) ?
2953 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2954 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2956 else
2957 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2958 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2959 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2960 CRT_V_INC,P1GroupSize,P23GroupSize,
2961 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2962 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
2965 /* keep everything in 16.16 */
2966 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
2967 config->offsets[0] = 0;
2968 for(i=1;i<besr.vid_nbufs;i++)
2969 config->offsets[i] = config->offsets[i-1]+config->frame_size;
2970 if(is_420 || is_410 || is_400)
2972 uint32_t d1line,d2line,d3line;
2973 d1line = top*pitch;
2974 if(is_420)
2976 d2line = src_h*pitch+(d1line>>2);
2977 d3line = d2line+((src_h*pitch)>>2);
2979 else
2980 if(is_410)
2982 d2line = src_h*pitch+(d1line>>4);
2983 d3line = d2line+((src_h*pitch)>>4);
2985 else
2987 d2line = 0;
2988 d3line = 0;
2990 d1line += (left >> 16) & ~15;
2991 if(is_420)
2993 d2line += (left >> 17) & ~15;
2994 d3line += (left >> 17) & ~15;
2996 else /* is_410 */
2998 d2line += (left >> 18) & ~15;
2999 d3line += (left >> 18) & ~15;
3001 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
3002 if(is_400)
3004 config->offset.v = 0;
3005 config->offset.u = 0;
3007 else
3009 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
3010 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
3012 for(i=0;i<besr.vid_nbufs;i++)
3014 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
3015 if(is_400)
3017 besr.vid_buf_base_adrs_v[i]=0;
3018 besr.vid_buf_base_adrs_u[i]=0;
3020 else
3022 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
3024 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;
3025 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;
3027 else
3029 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;
3030 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;
3034 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3035 if(is_400)
3037 config->offset.v = 0;
3038 config->offset.u = 0;
3040 else
3042 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3043 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3046 else
3048 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3049 for(i=0;i<besr.vid_nbufs;i++)
3051 besr.vid_buf_base_adrs_y[i] =
3052 besr.vid_buf_base_adrs_u[i] =
3053 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3056 leftUV = (left >> (is_410?18:17)) & 15;
3057 left = (left >> 16) & 15;
3058 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3059 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3060 ComputeBorders(config,VertUVSubSample);
3061 besr.vid_buf_pitch0_value = pitch;
3062 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3063 /* ********************************************************* */
3064 /* ** Calculate programmable coefficients as needed */
3065 /* ********************************************************* */
3067 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3068 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3069 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3070 else
3072 FilterSetup (val_OV0_P1_H_INC);
3073 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3074 /* would like to do. For now, we let the test application decide. */
3075 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3076 if(DisallowFourTapVertFiltering)
3077 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3078 if(DisallowFourTapUVVertFiltering)
3079 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3081 return 0;
3084 static void radeon_compute_framesize(vidix_playback_t *info)
3086 unsigned pitch,awidth,dbpp;
3087 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3088 dbpp = radeon_vid_get_dbpp();
3089 switch(info->fourcc)
3091 case IMGFMT_Y800:
3092 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3093 info->frame_size = awidth*info->src.h;
3094 break;
3095 case IMGFMT_YVU9:
3096 case IMGFMT_IF09:
3097 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3098 info->frame_size = awidth*(info->src.h+info->src.h/8);
3099 break;
3100 case IMGFMT_I420:
3101 case IMGFMT_YV12:
3102 case IMGFMT_IYUV:
3103 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3104 info->frame_size = awidth*(info->src.h+info->src.h/2);
3105 break;
3106 case IMGFMT_RGB32:
3107 case IMGFMT_BGR32:
3108 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3109 info->frame_size = awidth*info->src.h;
3110 break;
3111 /* YUY2 YVYU, RGB15, RGB16 */
3112 default:
3113 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3114 info->frame_size = awidth*info->src.h;
3115 break;
3117 info->frame_size = (info->frame_size+4095)&~4095;
3120 static int radeon_config_playback(vidix_playback_t *info)
3122 unsigned rgb_size,nfr;
3123 uint32_t radeon_video_size;
3124 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3125 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3126 if(info->num_frames==1) besr.double_buff=0;
3127 else besr.double_buff=1;
3128 radeon_compute_framesize(info);
3130 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3131 nfr = info->num_frames;
3132 radeon_video_size = radeon_ram_size;
3133 for(;nfr>0; nfr--)
3135 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3136 #if !defined (RAGE128) && defined(CONFIG_X11)
3137 radeon_overlay_off -= firegl_shift;
3138 #endif
3139 radeon_overlay_off &= 0xffff0000;
3140 if(radeon_overlay_off >= (int)rgb_size ) break;
3142 if(nfr <= 3)
3144 nfr = info->num_frames;
3145 for(;nfr>0; nfr--)
3147 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3148 #if !defined (RAGE128) && defined(CONFIG_X11)
3149 radeon_overlay_off -= firegl_shift;
3150 #endif
3151 radeon_overlay_off &= 0xffff0000;
3152 if(radeon_overlay_off > 0) break;
3155 if(nfr <= 0) return EINVAL;
3156 info->num_frames = nfr;
3157 besr.vid_nbufs = info->num_frames;
3158 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3159 radeon_vid_init_video(info);
3160 return 0;
3163 static int radeon_playback_on(void)
3165 #ifdef RAGE128
3166 unsigned dw,dh;
3167 #endif
3168 radeon_vid_display_video();
3169 #ifdef RAGE128
3170 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3171 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3172 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3173 else radeon_vid_non_exclusive();
3174 #endif
3175 return 0;
3178 static int radeon_playback_off(void)
3180 radeon_vid_stop_video();
3181 return 0;
3184 static int radeon_frame_select(unsigned frame)
3186 uint32_t off[6];
3187 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3188 // This really only needs to be set during data writes,
3189 // however we don't have a hook there.
3190 // The setup at startup is not enough since X11 regularly
3191 // resets this to values to the wrong values for us.
3192 clear_swap();
3194 buf3-5 always should point onto second buffer for better
3195 deinterlacing and TV-in
3197 if(!besr.double_buff) return 0;
3198 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3199 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3200 off[0] = besr.vid_buf_base_adrs_y[frame];
3201 off[1] = besr.vid_buf_base_adrs_v[frame];
3202 off[2] = besr.vid_buf_base_adrs_u[frame];
3203 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3204 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3205 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3206 radeon_fifo_wait(8);
3207 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3208 radeon_engine_idle();
3209 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3210 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3211 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3212 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3213 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3214 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3215 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3216 OUTREG(OV0_REG_LOAD_CNTL, 0);
3217 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3218 if(verbosity > VERBOSE_LEVEL) radeon_vid_dump_regs();
3219 return 0;
3222 static vidix_video_eq_t equal =
3224 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3225 #ifndef RAGE128
3226 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3227 #endif
3229 0, 0, 0, 0, 0, 0, 0, 0 };
3231 static int radeon_get_eq(vidix_video_eq_t * eq)
3233 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3234 return 0;
3237 #ifndef RAGE128
3238 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3239 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3240 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3241 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3242 #define RTFHue(a) (((a)*3.1416)/1000.0)
3243 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3244 #endif
3246 static int radeon_set_eq(const vidix_video_eq_t * eq)
3248 #ifdef RAGE128
3249 int br,sat;
3250 #else
3251 int itu_space;
3252 #endif
3253 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3254 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3255 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3256 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3257 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3259 equal.red_intensity = eq->red_intensity;
3260 equal.green_intensity = eq->green_intensity;
3261 equal.blue_intensity = eq->blue_intensity;
3263 equal.flags = eq->flags;
3264 #ifdef RAGE128
3265 br = equal.brightness * 64 / 1000;
3266 if(br < -64) br = -64; if(br > 63) br = 63;
3267 sat = (equal.saturation*31 + 31000) / 2000;
3268 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3269 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3270 #else
3271 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3272 RTFCheckParam(equal.brightness);
3273 RTFCheckParam(equal.saturation);
3274 RTFCheckParam(equal.contrast);
3275 RTFCheckParam(equal.hue);
3276 RTFCheckParam(equal.red_intensity);
3277 RTFCheckParam(equal.green_intensity);
3278 RTFCheckParam(equal.blue_intensity);
3279 radeon_set_transform(RTFBrightness(equal.brightness),
3280 RTFContrast(equal.contrast),
3281 RTFSaturation(equal.saturation),
3282 RTFHue(equal.hue),
3283 RTFIntensity(equal.red_intensity),
3284 RTFIntensity(equal.green_intensity),
3285 RTFIntensity(equal.blue_intensity),
3286 itu_space);
3287 #endif
3288 return 0;
3291 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3293 unsigned sflg;
3294 switch(info->flags)
3296 default:
3297 case CFG_NON_INTERLACED:
3298 besr.deinterlace_on = 0;
3299 break;
3300 case CFG_EVEN_ODD_INTERLACING:
3301 case CFG_INTERLACED:
3302 besr.deinterlace_on = 1;
3303 besr.deinterlace_pattern = 0x900AAAAA;
3304 break;
3305 case CFG_ODD_EVEN_INTERLACING:
3306 besr.deinterlace_on = 1;
3307 besr.deinterlace_pattern = 0x00055555;
3308 break;
3309 case CFG_UNIQUE_INTERLACING:
3310 besr.deinterlace_on = 1;
3311 besr.deinterlace_pattern = info->deinterlace_pattern;
3312 break;
3314 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3315 radeon_engine_idle();
3316 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3317 radeon_fifo_wait(15);
3318 sflg = INREG(OV0_SCALE_CNTL);
3319 if(besr.deinterlace_on)
3321 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3322 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3324 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3325 OUTREG(OV0_REG_LOAD_CNTL, 0);
3326 return 0;
3329 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3331 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3332 else
3334 info->flags = CFG_UNIQUE_INTERLACING;
3335 info->deinterlace_pattern = besr.deinterlace_pattern;
3337 return 0;
3341 /* Graphic keys */
3342 static vidix_grkey_t radeon_grkey;
3344 static int set_gr_key( void )
3346 int result = 0;
3348 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3349 0x00ff0000; /* graphic alpha */
3350 if(radeon_grkey.ckey.op == CKEY_TRUE)
3352 int dbpp=radeon_vid_get_dbpp();
3353 besr.ckey_on=1;
3355 switch(dbpp)
3357 case 15:
3358 #ifndef RAGE128
3359 if((besr.chip_flags&R_100)!=R_100)
3360 besr.graphics_key_clr=
3361 ((radeon_grkey.ckey.blue &0xF8))
3362 | ((radeon_grkey.ckey.green&0xF8)<<8)
3363 | ((radeon_grkey.ckey.red &0xF8)<<16);
3364 else
3365 #endif
3366 besr.graphics_key_clr=
3367 ((radeon_grkey.ckey.blue &0xF8)>>3)
3368 | ((radeon_grkey.ckey.green&0xF8)<<2)
3369 | ((radeon_grkey.ckey.red &0xF8)<<7);
3370 break;
3371 case 16:
3372 #ifndef RAGE128
3373 /* This test may be too general/specific */
3374 if((besr.chip_flags&R_100)!=R_100)
3375 besr.graphics_key_clr=
3376 ((radeon_grkey.ckey.blue &0xF8))
3377 | ((radeon_grkey.ckey.green&0xFC)<<8)
3378 | ((radeon_grkey.ckey.red &0xF8)<<16);
3379 else
3380 #endif
3381 besr.graphics_key_clr=
3382 ((radeon_grkey.ckey.blue &0xF8)>>3)
3383 | ((radeon_grkey.ckey.green&0xFC)<<3)
3384 | ((radeon_grkey.ckey.red &0xF8)<<8);
3385 break;
3386 case 24:
3387 case 32:
3388 besr.graphics_key_clr=
3389 ((radeon_grkey.ckey.blue &0xFF))
3390 | ((radeon_grkey.ckey.green&0xFF)<<8)
3391 | ((radeon_grkey.ckey.red &0xFF)<<16);
3392 break;
3393 default:
3394 besr.ckey_on=0;
3395 besr.graphics_key_msk=0;
3396 besr.graphics_key_clr=0;
3398 #ifdef RAGE128
3399 besr.graphics_key_msk=(1<<dbpp)-1;
3400 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3401 #else
3402 besr.graphics_key_msk=besr.graphics_key_clr;
3403 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3404 #endif
3406 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3408 int dbpp=radeon_vid_get_dbpp();
3409 besr.ckey_on=1;
3411 switch(dbpp)
3413 case 32:
3414 besr.ckey_on=1;
3415 besr.graphics_key_msk=0;
3416 besr.graphics_key_clr=0;
3417 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3418 besr.merge_cntl |= 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3419 break;
3420 default:
3421 besr.ckey_on=0;
3422 besr.graphics_key_msk=0;
3423 besr.graphics_key_clr=0;
3424 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3425 result = 1;
3428 else
3430 besr.ckey_on=0;
3431 besr.graphics_key_msk=0;
3432 besr.graphics_key_clr=0;
3433 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3434 besr.merge_cntl |= 0x00000100; /* DISP_RGB_OFFSET_EN */
3436 radeon_fifo_wait(3);
3437 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3438 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3439 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3440 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3441 return result;
3444 static int radeon_get_gkey(vidix_grkey_t *grkey)
3446 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3447 return 0;
3450 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3452 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3453 return set_gr_key();
3456 #ifdef RAGE128
3457 VDXDriver rage128_drv = {
3458 "rage128",
3459 #else
3460 VDXDriver radeon_drv = {
3461 "radeon",
3462 #endif
3463 NULL,
3465 .probe = radeon_probe,
3466 .get_caps = radeon_get_caps,
3467 .query_fourcc = radeon_query_fourcc,
3468 .init = radeon_init,
3469 .destroy = radeon_destroy,
3470 .config_playback = radeon_config_playback,
3471 .playback_on = radeon_playback_on,
3472 .playback_off = radeon_playback_off,
3473 .frame_sel = radeon_frame_select,
3474 .get_eq = radeon_get_eq,
3475 .set_eq = radeon_set_eq,
3476 .get_deint = radeon_playback_get_deint,
3477 .set_deint = radeon_playback_set_deint,
3478 .get_gkey = radeon_get_gkey,
3479 .set_gkey = radeon_set_gkey,