Commit files by Steinar Gunderson, forgotten in r30866.
[mplayer/glamo.git] / vidix / radeon_vid.c
blobee8aa23109cdca0091a3793b88e3563ea7706f6d
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 { DEVICE_ATI_RV280_RADEON_9200, R_280 },
398 { DEVICE_ATI_RV280_RADEON_92002, R_280 },
399 { DEVICE_ATI_RV280_RADEON_92003, R_280 },
400 { DEVICE_ATI_RV280_RADEON_92004, R_280 },
401 { DEVICE_ATI_RV280_RADEON_92005, R_280 },
402 { DEVICE_ATI_RV280_RADEON_92006, R_280 },
403 { DEVICE_ATI_RV280_RADEON_92007, R_280 },
404 { DEVICE_ATI_M9_5C61_RADEON, R_280 },
405 { DEVICE_ATI_M9_5C63_RADEON, R_280 },
406 /* Radeon3 (indeed: Rage 1024 Pro ;) */
407 { DEVICE_ATI_R300_AG_FIREGL, R_300 },
408 { DEVICE_ATI_RADEON_R300_ND, R_300 },
409 { DEVICE_ATI_RADEON_R300_NE, R_300 },
410 { DEVICE_ATI_RADEON_R300_NG, R_300 },
411 { DEVICE_ATI_R300_AD_RADEON, R_300 },
412 { DEVICE_ATI_R300_AE_RADEON, R_300 },
413 { DEVICE_ATI_R300_AF_RADEON, R_300 },
414 { DEVICE_ATI_RADEON_9100_IGP2, R_300|R_OVL_SHIFT|R_INTEGRATED },
415 { DEVICE_ATI_RS300M_AGP_RADEON, R_300|R_INTEGRATED },
416 { DEVICE_ATI_RS482_RADEON_XPRESS, R_350|R_INTEGRATED },
417 { DEVICE_ATI_R350_AH_RADEON, R_350 },
418 { DEVICE_ATI_R350_AI_RADEON, R_350 },
419 { DEVICE_ATI_R350_AJ_RADEON, R_350 },
420 { DEVICE_ATI_R350_AK_FIRE, R_350 },
421 { DEVICE_ATI_RADEON_R350_RADEON2, R_350 },
422 { DEVICE_ATI_RADEON_R350_RADEON3, R_350 },
423 { DEVICE_ATI_RV350_NJ_RADEON, R_350 },
424 { DEVICE_ATI_R350_NK_FIRE, R_350 },
425 { DEVICE_ATI_RV350_AP_RADEON, R_350 },
426 { DEVICE_ATI_RV350_AQ_RADEON, R_350 },
427 { DEVICE_ATI_RV350_AR_RADEON, R_350 },
428 { DEVICE_ATI_RV350_AS_RADEON, R_350 },
429 { DEVICE_ATI_RV350_AT_FIRE, R_350 },
430 { DEVICE_ATI_RV350_AU_FIRE, R_350 },
431 { DEVICE_ATI_RV350_AV_FIRE, R_350 },
432 { DEVICE_ATI_RV350_AW_FIRE, R_350 },
433 { DEVICE_ATI_RV350_MOBILITY_RADEON, R_350 },
434 { DEVICE_ATI_RV350_NF_RADEON, R_300 },
435 { DEVICE_ATI_RV350_NJ_RADEON, R_300 },
436 { DEVICE_ATI_RV350_AS_RADEON2, R_350 },
437 { DEVICE_ATI_M10_NQ_RADEON, R_350 },
438 { DEVICE_ATI_M10_NQ_RADEON2, R_350 },
439 { DEVICE_ATI_RV350_MOBILITY_RADEON2, R_350 },
440 { DEVICE_ATI_M10_NS_RADEON, R_350 },
441 { DEVICE_ATI_M10_NT_FIREGL, R_350 },
442 { DEVICE_ATI_M11_NV_FIREGL, R_350 },
443 { DEVICE_ATI_RV370_5B60_RADEON, R_370|R_PCIE },
444 { DEVICE_ATI_RV370_SAPPHIRE_X550, R_370 },
445 { DEVICE_ATI_RV370_5B64_FIREGL, R_370|R_PCIE },
446 { DEVICE_ATI_RV370_5B65_FIREGL, R_370|R_PCIE },
447 { DEVICE_ATI_M24_1P_RADEON, R_370 },
448 { DEVICE_ATI_M22_RADEON_MOBILITY, R_370 },
449 { DEVICE_ATI_M24_1T_FIREGL, R_370 },
450 { DEVICE_ATI_M24_RADEON_MOBILITY, R_370 },
451 { DEVICE_ATI_RV370_RADEON_X300SE, R_370 },
452 { DEVICE_ATI_RV370_SECONDARY_SAPPHIRE, R_370 },
453 { DEVICE_ATI_RV370_5B64_FIREGL2, R_370 },
454 { DEVICE_ATI_RV380_0X3E50_RADEON, R_380|R_PCIE },
455 { DEVICE_ATI_RV380_0X3E54_FIREGL, R_380|R_PCIE },
456 { DEVICE_ATI_RV380_RADEON_X600, R_380|R_PCIE },
457 { DEVICE_ATI_RV380_RADEON_X6002, R_380 },
458 { DEVICE_ATI_RV380_RADEON_X6003, R_380 },
459 { DEVICE_ATI_RV410_FIREGL_V5000, R_420 },
460 { DEVICE_ATI_RV410_FIREGL_V3300, R_420 },
461 { DEVICE_ATI_RV410_RADEON_X700XT, R_420 },
462 { DEVICE_ATI_RV410_RADEON_X700, R_420|R_PCIE },
463 { DEVICE_ATI_RV410_RADEON_X700SE, R_420 },
464 { DEVICE_ATI_RV410_RADEON_X7002, R_420|R_PCIE },
465 { DEVICE_ATI_RV410_RADEON_X7003, R_420 },
466 { DEVICE_ATI_RV410_RADEON_X7004, R_420|R_PCIE },
467 { DEVICE_ATI_RV410_RADEON_X7005, R_420|R_PCIE },
468 { DEVICE_ATI_M26_MOBILITY_FIREGL, R_420 },
469 { DEVICE_ATI_M26_MOBILITY_FIREGL2, R_420 },
470 { DEVICE_ATI_M26_RADEON_MOBILITY, R_420 },
471 { DEVICE_ATI_M26_RADEON_MOBILITY2, R_420 },
472 { DEVICE_ATI_RADEON_MOBILITY_X700, R_420 },
473 { DEVICE_ATI_R420_JH_RADEON, R_420|R_PCIE },
474 { DEVICE_ATI_R420_JI_RADEON, R_420|R_PCIE },
475 { DEVICE_ATI_R420_JJ_RADEON, R_420|R_PCIE },
476 { DEVICE_ATI_R420_JK_RADEON, R_420|R_PCIE },
477 { DEVICE_ATI_R420_JL_RADEON, R_420|R_PCIE },
478 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
479 { DEVICE_ATI_M18_JN_RADEON, R_420|R_PCIE },
480 { DEVICE_ATI_R420_JP_RADEON, R_420|R_PCIE },
481 { DEVICE_ATI_R420_RADEON_X800, R_420|R_PCIE },
482 { DEVICE_ATI_R420_RADEON_X8002, R_420|R_PCIE },
483 { DEVICE_ATI_R420_RADEON_X8003, R_420|R_PCIE },
484 { DEVICE_ATI_R420_RADEON_X8004, R_420|R_PCIE },
485 { DEVICE_ATI_R420_RADEON_X8005, R_420|R_PCIE },
486 { DEVICE_ATI_R420_JM_FIREGL, R_420|R_PCIE },
487 { DEVICE_ATI_R423_5F57_RADEON, R_420|R_PCIE },
488 { DEVICE_ATI_R423_5F57_RADEON2, R_420|R_PCIE },
489 { DEVICE_ATI_R423_UH_RADEON, R_420|R_PCIE },
490 { DEVICE_ATI_R423_UI_RADEON, R_420|R_PCIE },
491 { DEVICE_ATI_R423_UJ_RADEON, R_420|R_PCIE },
492 { DEVICE_ATI_R423_UK_RADEON, R_420|R_PCIE },
493 { DEVICE_ATI_R423_FIRE_GL, R_420|R_PCIE },
494 { DEVICE_ATI_R423_UQ_FIREGL, R_420|R_PCIE },
495 { DEVICE_ATI_R423_UR_FIREGL, R_420|R_PCIE },
496 { DEVICE_ATI_R423_UT_FIREGL, R_420|R_PCIE },
497 { DEVICE_ATI_R423_UI_RADEON2, R_420|R_PCIE },
498 { DEVICE_ATI_R423GL_SE_ATI_FIREGL, R_420|R_PCIE },
499 { DEVICE_ATI_R423_RADEON_X800XT, R_420|R_PCIE },
500 { DEVICE_ATI_RADEON_R423_UK, R_420|R_PCIE },
501 { DEVICE_ATI_M28_RADEON_MOBILITY, R_420 },
502 { DEVICE_ATI_M28_MOBILITY_FIREGL, R_420 },
503 { DEVICE_ATI_MOBILITY_RADEON_X800, R_420 },
504 { DEVICE_ATI_R430_RADEON_X800, R_430|R_PCIE },
505 { DEVICE_ATI_R430_RADEON_X8002, R_430|R_PCIE },
506 { DEVICE_ATI_R430_RADEON_X8003, R_430|R_PCIE },
507 { DEVICE_ATI_R430_RADEON_X8004, R_430|R_PCIE },
508 { DEVICE_ATI_R480_RADEON_X800, R_480 },
509 { DEVICE_ATI_R480_RADEON_X8002, R_480 },
510 { DEVICE_ATI_R480_RADEON_X850XT, R_480 },
511 { DEVICE_ATI_R480_RADEON_X850PRO, R_480 },
512 { DEVICE_ATI_R481_RADEON_X850XT_PE, R_480|R_PCIE },
513 { DEVICE_ATI_R480_RADEON_X850XT2, R_480 },
514 { DEVICE_ATI_R480_RADEON_X850PRO2, R_480 },
515 { DEVICE_ATI_R481_RADEON_X850XT_PE2, R_480|R_PCIE },
516 { DEVICE_ATI_R480_RADEON_X850XT3, R_480|R_PCIE },
517 { DEVICE_ATI_R480_RADEON_X850XT4, R_480|R_PCIE },
518 { DEVICE_ATI_R480_RADEON_X850XT5, R_480|R_PCIE },
519 { DEVICE_ATI_R480_RADEON_X850XT6, R_480|R_PCIE },
520 #endif
524 static void * radeon_mmio_base = 0;
525 static void * radeon_mem_base = 0;
526 static int32_t radeon_overlay_off = 0;
527 static uint32_t radeon_ram_size = 0;
529 #define GETREG(TYPE,PTR,OFFZ) (*((volatile TYPE*)((PTR)+(OFFZ))))
530 #define SETREG(TYPE,PTR,OFFZ,VAL) (*((volatile TYPE*)((PTR)+(OFFZ))))=VAL
532 #define INREG8(addr) GETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr)
533 #define OUTREG8(addr,val) SETREG(uint8_t,(uint8_t *)(radeon_mmio_base),addr,val)
534 static inline uint32_t INREG (uint32_t addr) {
535 uint32_t tmp = GETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr);
536 return le2me_32(tmp);
538 #define OUTREG(addr,val) SETREG(uint32_t,(uint8_t *)(radeon_mmio_base),addr,le2me_32(val))
539 #define OUTREGP(addr,val,mask) \
540 do { \
541 unsigned int _tmp = INREG(addr); \
542 _tmp &= (mask); \
543 _tmp |= (val); \
544 OUTREG(addr, _tmp); \
545 } while (0)
547 static __inline__ uint32_t INPLL(uint32_t addr)
549 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000001f);
550 return INREG(CLOCK_CNTL_DATA);
553 #define OUTPLL(addr,val) OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000001f) | 0x00000080); \
554 OUTREG(CLOCK_CNTL_DATA, val)
555 #define OUTPLLP(addr,val,mask) \
556 do { \
557 unsigned int _tmp = INPLL(addr); \
558 _tmp &= (mask); \
559 _tmp |= (val); \
560 OUTPLL(addr, _tmp); \
561 } while (0)
563 #ifndef RAGE128
564 enum radeon_montype
566 MT_NONE,
567 MT_CRT, /* CRT-(cathode ray tube) analog monitor. (15-pin VGA connector) */
568 MT_LCD, /* Liquid Crystal Display */
569 MT_DFP, /* DFP-digital flat panel monitor. (24-pin DVI-I connector) */
570 MT_CTV, /* Composite TV out (not in VE) */
571 MT_STV /* S-Video TV out (probably in VE only) */
574 typedef struct radeon_info_s
576 int hasCRTC2;
577 int crtDispType;
578 int dviDispType;
579 }rinfo_t;
581 static rinfo_t rinfo;
583 static char * GET_MON_NAME(int type)
585 char *pret;
586 switch(type)
588 case MT_NONE: pret = "no"; break;
589 case MT_CRT: pret = "CRT"; break;
590 case MT_DFP: pret = "DFP"; break;
591 case MT_LCD: pret = "LCD"; break;
592 case MT_CTV: pret = "CTV"; break;
593 case MT_STV: pret = "STV"; break;
594 default: pret = "Unknown";
596 return pret;
599 static void radeon_get_moninfo (rinfo_t *rinfo)
601 unsigned int tmp;
603 tmp = INREG(RADEON_BIOS_4_SCRATCH);
605 if (rinfo->hasCRTC2) {
606 /* primary DVI port */
607 if (tmp & 0x08)
608 rinfo->dviDispType = MT_DFP;
609 else if (tmp & 0x4)
610 rinfo->dviDispType = MT_LCD;
611 else if (tmp & 0x200)
612 rinfo->dviDispType = MT_CRT;
613 else if (tmp & 0x10)
614 rinfo->dviDispType = MT_CTV;
615 else if (tmp & 0x20)
616 rinfo->dviDispType = MT_STV;
618 /* secondary CRT port */
619 if (tmp & 0x2)
620 rinfo->crtDispType = MT_CRT;
621 else if (tmp & 0x800)
622 rinfo->crtDispType = MT_DFP;
623 else if (tmp & 0x400)
624 rinfo->crtDispType = MT_LCD;
625 else if (tmp & 0x1000)
626 rinfo->crtDispType = MT_CTV;
627 else if (tmp & 0x2000)
628 rinfo->crtDispType = MT_STV;
629 } else {
630 rinfo->dviDispType = MT_NONE;
632 tmp = INREG(FP_GEN_CNTL);
634 if (tmp & FP_EN_TMDS)
635 rinfo->crtDispType = MT_DFP;
636 else
637 rinfo->crtDispType = MT_CRT;
640 #endif
642 static uint32_t radeon_vid_get_dbpp( void )
644 uint32_t dbpp,retval;
645 dbpp = (INREG(CRTC_GEN_CNTL)>>8)& 0xF;
646 switch(dbpp)
648 case DST_8BPP: retval = 8; break;
649 case DST_15BPP: retval = 15; break;
650 case DST_16BPP: retval = 16; break;
651 case DST_24BPP: retval = 24; break;
652 default: retval=32; break;
654 return retval;
657 static int radeon_is_dbl_scan( void )
659 return (INREG(CRTC_GEN_CNTL))&CRTC_DBL_SCAN_EN;
662 static int radeon_is_interlace( void )
664 return (INREG(CRTC_GEN_CNTL))&CRTC_INTERLACE_EN;
667 static uint32_t radeon_get_xres( void )
669 uint32_t xres,h_total;
670 #ifndef RAGE128
671 if(rinfo.hasCRTC2 &&
672 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
673 h_total = INREG(CRTC2_H_TOTAL_DISP);
674 else
675 #endif
676 h_total = INREG(CRTC_H_TOTAL_DISP);
677 xres = (h_total >> 16) & 0xffff;
678 return (xres + 1)*8;
681 static uint32_t radeon_get_yres( void )
683 uint32_t yres,v_total;
684 #ifndef RAGE128
685 if(rinfo.hasCRTC2 &&
686 (rinfo.dviDispType == MT_CTV || rinfo.dviDispType == MT_STV))
687 v_total = INREG(CRTC2_V_TOTAL_DISP);
688 else
689 #endif
690 v_total = INREG(CRTC_V_TOTAL_DISP);
691 yres = (v_total >> 16) & 0xffff;
692 return yres + 1;
695 static void radeon_wait_vsync(void)
697 int i;
699 OUTREG(GEN_INT_STATUS, VSYNC_INT_AK);
700 for (i = 0; i < 2000000; i++)
702 if (INREG(GEN_INT_STATUS) & VSYNC_INT) break;
706 #ifdef RAGE128
707 static void _radeon_engine_idle(void);
708 static void _radeon_fifo_wait(unsigned);
709 #define radeon_engine_idle() _radeon_engine_idle()
710 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
711 /* Flush all dirty data in the Pixel Cache to memory. */
712 static __inline__ void radeon_engine_flush ( void )
714 unsigned i;
716 OUTREGP(PC_NGUI_CTLSTAT, PC_FLUSH_ALL, ~PC_FLUSH_ALL);
717 for (i = 0; i < 2000000; i++) {
718 if (!(INREG(PC_NGUI_CTLSTAT) & PC_BUSY)) break;
722 /* Reset graphics card to known state. */
723 static void radeon_engine_reset( void )
725 uint32_t clock_cntl_index;
726 uint32_t mclk_cntl;
727 uint32_t gen_reset_cntl;
729 radeon_engine_flush();
731 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
732 mclk_cntl = INPLL(MCLK_CNTL);
734 OUTPLL(MCLK_CNTL, mclk_cntl | FORCE_GCP | FORCE_PIPE3D_CP);
736 gen_reset_cntl = INREG(GEN_RESET_CNTL);
738 OUTREG(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
739 INREG(GEN_RESET_CNTL);
740 OUTREG(GEN_RESET_CNTL,
741 gen_reset_cntl & (uint32_t)(~SOFT_RESET_GUI));
742 INREG(GEN_RESET_CNTL);
744 OUTPLL(MCLK_CNTL, mclk_cntl);
745 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
746 OUTREG(GEN_RESET_CNTL, gen_reset_cntl);
748 #else
750 static __inline__ void radeon_engine_flush ( void )
752 int i;
754 /* initiate flush */
755 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL,
756 ~RB2D_DC_FLUSH_ALL);
758 for (i=0; i < 2000000; i++) {
759 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
760 break;
764 static void _radeon_engine_idle(void);
765 static void _radeon_fifo_wait(unsigned);
766 #define radeon_engine_idle() _radeon_engine_idle()
767 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
769 static void radeon_engine_reset( void )
771 uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
773 radeon_engine_flush ();
775 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
776 mclk_cntl = INPLL(MCLK_CNTL);
778 OUTPLL(MCLK_CNTL, (mclk_cntl |
779 FORCEON_MCLKA |
780 FORCEON_MCLKB |
781 FORCEON_YCLKA |
782 FORCEON_YCLKB |
783 FORCEON_MC |
784 FORCEON_AIC));
785 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
787 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
788 SOFT_RESET_CP |
789 SOFT_RESET_HI |
790 SOFT_RESET_SE |
791 SOFT_RESET_RE |
792 SOFT_RESET_PP |
793 SOFT_RESET_E2 |
794 SOFT_RESET_RB |
795 SOFT_RESET_HDP);
796 INREG(RBBM_SOFT_RESET);
797 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (uint32_t)
798 ~(SOFT_RESET_CP |
799 SOFT_RESET_HI |
800 SOFT_RESET_SE |
801 SOFT_RESET_RE |
802 SOFT_RESET_PP |
803 SOFT_RESET_E2 |
804 SOFT_RESET_RB |
805 SOFT_RESET_HDP));
806 INREG(RBBM_SOFT_RESET);
808 OUTPLL(MCLK_CNTL, mclk_cntl);
809 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
810 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
812 return;
814 #endif
815 static void radeon_engine_restore( void )
817 #ifndef RAGE128
818 int pitch64;
819 uint32_t xres,yres,bpp;
820 radeon_fifo_wait(1);
821 xres = radeon_get_xres();
822 yres = radeon_get_yres();
823 bpp = radeon_vid_get_dbpp();
824 /* turn of all automatic flushing - we'll do it all */
825 OUTREG(RB2D_DSTCACHE_MODE, 0);
827 pitch64 = ((xres * (bpp / 8) + 0x3f)) >> 6;
829 radeon_fifo_wait(1);
830 OUTREG(DEFAULT_OFFSET, (INREG(DEFAULT_OFFSET) & 0xC0000000) |
831 (pitch64 << 22));
833 radeon_fifo_wait(1);
834 #if HAVE_BIGENDIAN
835 OUTREGP(DP_DATATYPE,
836 HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN);
837 #else
838 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
839 #endif
841 radeon_fifo_wait(1);
842 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX
843 | DEFAULT_SC_BOTTOM_MAX));
844 radeon_fifo_wait(1);
845 OUTREG(DP_GUI_MASTER_CNTL, (INREG(DP_GUI_MASTER_CNTL)
846 | GMC_BRUSH_SOLID_COLOR
847 | GMC_SRC_DATATYPE_COLOR));
849 radeon_fifo_wait(7);
850 OUTREG(DST_LINE_START, 0);
851 OUTREG(DST_LINE_END, 0);
852 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
853 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
854 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
855 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
856 OUTREG(DP_WRITE_MASK, 0xffffffff);
858 radeon_engine_idle();
859 #endif
861 #ifdef RAGE128
862 static void _radeon_fifo_wait (unsigned entries)
864 unsigned i;
866 for(;;)
868 for (i=0; i<2000000; i++)
869 if ((INREG(GUI_STAT) & GUI_FIFOCNT_MASK) >= entries)
870 return;
871 radeon_engine_reset();
872 radeon_engine_restore();
876 static void _radeon_engine_idle ( void )
878 unsigned i;
880 /* ensure FIFO is empty before waiting for idle */
881 radeon_fifo_wait (64);
882 for(;;)
884 for (i=0; i<2000000; i++) {
885 if ((INREG(GUI_STAT) & GUI_ACTIVE) == 0) {
886 radeon_engine_flush ();
887 return;
890 radeon_engine_reset();
891 radeon_engine_restore();
894 #else
895 static void _radeon_fifo_wait (unsigned entries)
897 unsigned i;
899 for(;;)
901 for (i=0; i<2000000; i++)
902 if ((INREG(RBBM_STATUS) & RBBM_FIFOCNT_MASK) >= entries)
903 return;
904 radeon_engine_reset();
905 radeon_engine_restore();
908 static void _radeon_engine_idle ( void )
910 int i;
912 /* ensure FIFO is empty before waiting for idle */
913 radeon_fifo_wait (64);
914 for(;;)
916 for (i=0; i<2000000; i++) {
917 if (((INREG(RBBM_STATUS) & RBBM_ACTIVE)) == 0) {
918 radeon_engine_flush ();
919 return;
922 radeon_engine_reset();
923 radeon_engine_restore();
926 #endif
928 #ifndef RAGE128
929 /* Reference color space transform data */
930 typedef struct tagREF_TRANSFORM
932 float RefLuma;
933 float RefRCb;
934 float RefRCr;
935 float RefGCb;
936 float RefGCr;
937 float RefBCb;
938 float RefBCr;
939 } REF_TRANSFORM;
941 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
942 static const REF_TRANSFORM trans[2] =
944 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
945 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
947 /****************************************************************************
948 * SetTransform *
949 * Function: Calculates and sets color space transform from supplied *
950 * reference transform, gamma, brightness, contrast, hue and *
951 * saturation. *
952 * Inputs: bright - brightness *
953 * cont - contrast *
954 * sat - saturation *
955 * hue - hue *
956 * red_intensity - intense of red component *
957 * green_intensity - intense of green component *
958 * blue_intensity - intense of blue component *
959 * ref - index to the table of refernce transforms *
960 * Outputs: NONE *
961 ****************************************************************************/
963 static void radeon_set_transform(float bright, float cont, float sat,
964 float hue, float red_intensity,
965 float green_intensity,float blue_intensity,
966 unsigned ref)
968 float OvHueSin, OvHueCos;
969 float CAdjLuma, CAdjOff;
970 float RedAdj,GreenAdj,BlueAdj;
971 float CAdjRCb, CAdjRCr;
972 float CAdjGCb, CAdjGCr;
973 float CAdjBCb, CAdjBCr;
974 float OvLuma, OvROff, OvGOff, OvBOff;
975 float OvRCb, OvRCr;
976 float OvGCb, OvGCr;
977 float OvBCb, OvBCr;
978 float Loff = 64.0;
979 float Coff = 512.0f;
981 uint32_t dwOvLuma, dwOvROff, dwOvGOff, dwOvBOff;
982 uint32_t dwOvRCb, dwOvRCr;
983 uint32_t dwOvGCb, dwOvGCr;
984 uint32_t dwOvBCb, dwOvBCr;
986 if (ref >= 2) return;
988 OvHueSin = sin((double)hue);
989 OvHueCos = cos((double)hue);
991 CAdjLuma = cont * trans[ref].RefLuma;
992 CAdjOff = cont * trans[ref].RefLuma * bright * 1023.0;
993 RedAdj = cont * trans[ref].RefLuma * red_intensity * 1023.0;
994 GreenAdj = cont * trans[ref].RefLuma * green_intensity * 1023.0;
995 BlueAdj = cont * trans[ref].RefLuma * blue_intensity * 1023.0;
997 CAdjRCb = sat * -OvHueSin * trans[ref].RefRCr;
998 CAdjRCr = sat * OvHueCos * trans[ref].RefRCr;
999 CAdjGCb = sat * (OvHueCos * trans[ref].RefGCb - OvHueSin * trans[ref].RefGCr);
1000 CAdjGCr = sat * (OvHueSin * trans[ref].RefGCb + OvHueCos * trans[ref].RefGCr);
1001 CAdjBCb = sat * OvHueCos * trans[ref].RefBCb;
1002 CAdjBCr = sat * OvHueSin * trans[ref].RefBCb;
1004 OvLuma = CAdjLuma;
1005 OvRCb = CAdjRCb;
1006 OvRCr = CAdjRCr;
1007 OvGCb = CAdjGCb;
1008 OvGCr = CAdjGCr;
1009 OvBCb = CAdjBCb;
1010 OvBCr = CAdjBCr;
1011 OvROff = RedAdj + CAdjOff -
1012 OvLuma * Loff - (OvRCb + OvRCr) * Coff;
1013 OvGOff = GreenAdj + CAdjOff -
1014 OvLuma * Loff - (OvGCb + OvGCr) * Coff;
1015 OvBOff = BlueAdj + CAdjOff -
1016 OvLuma * Loff - (OvBCb + OvBCr) * Coff;
1018 dwOvROff = ((int)(OvROff * 2.0)) & 0x1fff;
1019 dwOvGOff = (int)(OvGOff * 2.0) & 0x1fff;
1020 dwOvBOff = (int)(OvBOff * 2.0) & 0x1fff;
1021 /* Whatever docs say about R200 having 3.8 format instead of 3.11
1022 as in Radeon is a lie */
1024 dwOvLuma =(((int)(OvLuma * 2048.0))&0x7fff)<<17;
1025 dwOvRCb = (((int)(OvRCb * 2048.0))&0x7fff)<<1;
1026 dwOvRCr = (((int)(OvRCr * 2048.0))&0x7fff)<<17;
1027 dwOvGCb = (((int)(OvGCb * 2048.0))&0x7fff)<<1;
1028 dwOvGCr = (((int)(OvGCr * 2048.0))&0x7fff)<<17;
1029 dwOvBCb = (((int)(OvBCb * 2048.0))&0x7fff)<<1;
1030 dwOvBCr = (((int)(OvBCr * 2048.0))&0x7fff)<<17;
1032 OUTREG(OV0_LIN_TRANS_A, dwOvRCb | dwOvLuma);
1033 OUTREG(OV0_LIN_TRANS_B, dwOvROff | dwOvRCr);
1034 OUTREG(OV0_LIN_TRANS_C, dwOvGCb | dwOvLuma);
1035 OUTREG(OV0_LIN_TRANS_D, dwOvGOff | dwOvGCr);
1036 OUTREG(OV0_LIN_TRANS_E, dwOvBCb | dwOvLuma);
1037 OUTREG(OV0_LIN_TRANS_F, dwOvBOff | dwOvBCr);
1040 /* Gamma curve definition */
1041 typedef struct
1043 unsigned int gammaReg;
1044 unsigned int gammaSlope;
1045 unsigned int gammaOffset;
1046 }GAMMA_SETTINGS;
1048 /* Recommended gamma curve parameters */
1049 static const GAMMA_SETTINGS r200_def_gamma[18] =
1051 {OV0_GAMMA_0_F, 0x100, 0x0000},
1052 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1053 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1054 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1055 {OV0_GAMMA_80_BF, 0x100, 0x0100},
1056 {OV0_GAMMA_C0_FF, 0x100, 0x0100},
1057 {OV0_GAMMA_100_13F, 0x100, 0x0200},
1058 {OV0_GAMMA_140_17F, 0x100, 0x0200},
1059 {OV0_GAMMA_180_1BF, 0x100, 0x0300},
1060 {OV0_GAMMA_1C0_1FF, 0x100, 0x0300},
1061 {OV0_GAMMA_200_23F, 0x100, 0x0400},
1062 {OV0_GAMMA_240_27F, 0x100, 0x0400},
1063 {OV0_GAMMA_280_2BF, 0x100, 0x0500},
1064 {OV0_GAMMA_2C0_2FF, 0x100, 0x0500},
1065 {OV0_GAMMA_300_33F, 0x100, 0x0600},
1066 {OV0_GAMMA_340_37F, 0x100, 0x0600},
1067 {OV0_GAMMA_380_3BF, 0x100, 0x0700},
1068 {OV0_GAMMA_3C0_3FF, 0x100, 0x0700}
1071 static const GAMMA_SETTINGS r100_def_gamma[6] =
1073 {OV0_GAMMA_0_F, 0x100, 0x0000},
1074 {OV0_GAMMA_10_1F, 0x100, 0x0020},
1075 {OV0_GAMMA_20_3F, 0x100, 0x0040},
1076 {OV0_GAMMA_40_7F, 0x100, 0x0080},
1077 {OV0_GAMMA_380_3BF, 0x100, 0x0100},
1078 {OV0_GAMMA_3C0_3FF, 0x100, 0x0100}
1081 static void make_default_gamma_correction( void )
1083 size_t i;
1084 if((besr.chip_flags & R_100)==R_100||
1085 (besr.chip_flags & R_120)==R_120||
1086 (besr.chip_flags & R_150)==R_150){
1087 OUTREG(OV0_LIN_TRANS_A, 0x12A00000);
1088 OUTREG(OV0_LIN_TRANS_B, 0x199018FE);
1089 OUTREG(OV0_LIN_TRANS_C, 0x12A0F9B0);
1090 OUTREG(OV0_LIN_TRANS_D, 0xF2F0043B);
1091 OUTREG(OV0_LIN_TRANS_E, 0x12A02050);
1092 OUTREG(OV0_LIN_TRANS_F, 0x0000174E);
1093 for(i=0; i<6; i++){
1094 OUTREG(r100_def_gamma[i].gammaReg,
1095 (r100_def_gamma[i].gammaSlope<<16) |
1096 r100_def_gamma[i].gammaOffset);
1099 else{
1100 OUTREG(OV0_LIN_TRANS_A, 0x12a20000);
1101 OUTREG(OV0_LIN_TRANS_B, 0x198a190e);
1102 OUTREG(OV0_LIN_TRANS_C, 0x12a2f9da);
1103 OUTREG(OV0_LIN_TRANS_D, 0xf2fe0442);
1104 OUTREG(OV0_LIN_TRANS_E, 0x12a22046);
1105 OUTREG(OV0_LIN_TRANS_F, 0x175f);
1106 /* Default Gamma,
1107 Of 18 segments for gamma cure, all segments in R200 are programmable,
1108 while only lower 4 and upper 2 segments are programmable in Radeon*/
1109 for(i=0; i<18; i++){
1110 OUTREG(r200_def_gamma[i].gammaReg,
1111 (r200_def_gamma[i].gammaSlope<<16) |
1112 r200_def_gamma[i].gammaOffset);
1116 #endif
1118 static void radeon_vid_make_default(void)
1120 #ifdef RAGE128
1121 besr.saturation = 0x0F;
1122 besr.brightness = 0;
1123 OUTREG(OV0_COLOUR_CNTL,0x000F0F00UL); /* Default brihgtness and saturation for Rage128 */
1124 #else
1125 make_default_gamma_correction();
1126 #endif
1127 besr.deinterlace_pattern = 0x900AAAAA;
1128 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1129 besr.deinterlace_on=1;
1130 besr.double_buff=1;
1131 besr.ckey_on=0;
1132 besr.graphics_key_msk=0;
1133 besr.graphics_key_clr=0;
1134 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
1137 static int find_chip(unsigned chip_id)
1139 unsigned i;
1140 for(i = 0;i < sizeof(ati_card_ids)/sizeof(ati_card_ids_t);i++)
1142 if(chip_id == ati_card_ids[i].id) return i;
1144 return -1;
1147 static pciinfo_t pci_info;
1148 static int probed=0;
1150 static vidix_capability_t def_cap =
1152 #ifdef RAGE128
1153 "BES driver for Rage128 cards",
1154 #else
1155 "BES driver for Radeon cards",
1156 #endif
1157 "Nick Kurshev",
1158 TYPE_OUTPUT | TYPE_FX,
1159 { 0, 0, 0, 0 },
1160 2048,
1161 2048,
1165 FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
1166 VENDOR_ATI,
1168 { 0, 0, 0, 0}
1171 #if !defined(RAGE128) && defined(CONFIG_X11)
1172 static void probe_fireGL_driver(void) {
1173 Display *dp = XOpenDisplay ((void*)0);
1174 int n = 0;
1175 char **extlist;
1176 if (dp==NULL) {
1177 return;
1179 extlist = XListExtensions (dp, &n);
1180 XCloseDisplay (dp);
1181 if (extlist) {
1182 int i;
1183 int ext_fgl = 0, ext_fglrx = 0;
1184 for (i = 0; i < n; i++) {
1185 if (!strcmp(extlist[i], "ATIFGLEXTENSION")) ext_fgl = 1;
1186 if (!strcmp(extlist[i], "ATIFGLRXDRI")) ext_fglrx = 1;
1188 if (ext_fgl) {
1189 printf(RADEON_MSG" ATI FireGl driver detected");
1190 firegl_shift = 0x500000;
1191 if (!ext_fglrx) {
1192 printf(", but DRI seems not to be activated\n");
1193 printf(RADEON_MSG" Output may not work correctly, check your DRI configration!");
1195 printf("\n");
1199 #endif
1201 static int radeon_probe(int verbose, int force)
1203 pciinfo_t lst[MAX_PCI_DEVICES];
1204 unsigned i,num_pci;
1205 int err;
1206 verbosity = verbose;
1207 err = pci_scan(lst,&num_pci);
1208 if(err)
1210 printf(RADEON_MSG" Error occurred during pci scan: %s\n",strerror(err));
1211 return err;
1213 else
1215 err = ENXIO;
1216 for(i=0;i<num_pci;i++)
1218 if(lst[i].vendor == VENDOR_ATI)
1220 int idx;
1221 const char *dname;
1222 idx = find_chip(lst[i].device);
1223 if(idx == -1 && force == PROBE_NORMAL) continue;
1224 dname = pci_device_name(VENDOR_ATI,lst[i].device);
1225 dname = dname ? dname : "Unknown chip";
1226 printf(RADEON_MSG" Found chip: %s\n",dname);
1227 #if 0
1228 if ((lst[i].command & PCI_COMMAND_IO) == 0)
1230 printf("[radeon] Device is disabled, ignoring\n");
1231 continue;
1233 #endif
1234 memset(&besr,0,sizeof(bes_registers_t));
1235 if(force > PROBE_NORMAL)
1237 printf(RADEON_MSG" Driver was forced. Was found %sknown chip\n",idx == -1 ? "un" : "");
1238 if(idx == -1)
1239 #ifdef RAGE128
1240 printf(RADEON_MSG" Assuming it as Rage128\n");
1241 #else
1242 printf(RADEON_MSG" Assuming it as Radeon1\n");
1243 #endif
1244 besr.chip_flags=R_100|R_OVL_SHIFT;
1246 #if !defined(RAGE128) && defined(CONFIG_X11)
1247 probe_fireGL_driver();
1248 #endif
1249 if(idx != -1) besr.chip_flags=ati_card_ids[idx].flags;
1250 def_cap.device_id = lst[i].device;
1251 err = 0;
1252 memcpy(&pci_info,&lst[i],sizeof(pciinfo_t));
1253 probed=1;
1254 break;
1258 if(err && verbose) printf(RADEON_MSG" Can't find chip\n");
1259 return err;
1262 typedef struct saved_regs_s
1264 uint32_t ov0_vid_key_clr;
1265 uint32_t ov0_vid_key_msk;
1266 uint32_t ov0_graphics_key_clr;
1267 uint32_t ov0_graphics_key_msk;
1268 uint32_t ov0_key_cntl;
1269 uint32_t disp_merge_cntl;
1270 }saved_regs_t;
1271 static saved_regs_t savreg;
1273 static void save_regs( void )
1275 radeon_fifo_wait(6);
1276 savreg.ov0_vid_key_clr = INREG(OV0_VID_KEY_CLR);
1277 savreg.ov0_vid_key_msk = INREG(OV0_VID_KEY_MSK);
1278 savreg.ov0_graphics_key_clr = INREG(OV0_GRAPHICS_KEY_CLR);
1279 savreg.ov0_graphics_key_msk = INREG(OV0_GRAPHICS_KEY_MSK);
1280 savreg.ov0_key_cntl = INREG(OV0_KEY_CNTL);
1281 savreg.disp_merge_cntl = INREG(DISP_MERGE_CNTL);
1284 static void restore_regs( void )
1286 radeon_fifo_wait(6);
1287 OUTREG(OV0_VID_KEY_CLR,savreg.ov0_vid_key_clr);
1288 OUTREG(OV0_VID_KEY_MSK,savreg.ov0_vid_key_msk);
1289 OUTREG(OV0_GRAPHICS_KEY_CLR,savreg.ov0_graphics_key_clr);
1290 OUTREG(OV0_GRAPHICS_KEY_MSK,savreg.ov0_graphics_key_msk);
1291 OUTREG(OV0_KEY_CNTL,savreg.ov0_key_cntl);
1292 OUTREG(DISP_MERGE_CNTL,savreg.disp_merge_cntl);
1295 static int radeon_init(void)
1297 int err;
1299 if(!probed)
1301 printf(RADEON_MSG" Driver was not probed but is being initializing\n");
1302 return EINTR;
1304 if((radeon_mmio_base = map_phys_mem(pci_info.base2,0xFFFF))==(void *)-1) return ENOMEM;
1305 radeon_ram_size = INREG(CONFIG_MEMSIZE);
1306 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1307 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1308 #ifdef RADEON
1309 /* according to XFree86 4.2.0, some production M6's return 0 for 8MB */
1310 if (radeon_ram_size == 0 &&
1311 (def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M6 ||
1312 def_cap.device_id == DEVICE_ATI_RADEON_MOBILITY_M62))
1314 printf(RADEON_MSG" Working around buggy Radeon Mobility M6 (0 vs. 8MB ram)\n");
1315 radeon_ram_size = 8192*1024;
1317 else if (radeon_ram_size == 0 &&
1318 (def_cap.device_id == DEVICE_ATI_RS482_RADEON_XPRESS))
1320 printf(RADEON_MSG" Working around buggy RS482 Radeon Xpress 200 Memory Detection\n");
1321 radeon_ram_size = (INREG(CONFIG_MEMSIZE) + 0x100000) << 2;
1322 radeon_ram_size &= CONFIG_MEMSIZE_MASK;
1324 #else
1325 /* Rage Mobility (rage128) also has memsize bug */
1326 if (radeon_ram_size == 0 &&
1327 (def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M3 ||
1328 def_cap.device_id == DEVICE_ATI_RAGE_MOBILITY_M32))
1330 printf(RADEON_MSG" Working around Rage Mobility M3 (0 vs. 8MB ram)\n");
1331 radeon_ram_size = 8192*1024;
1333 #endif
1334 if((radeon_mem_base = map_phys_mem(pci_info.base0,radeon_ram_size))==(void *)-1) return ENOMEM;
1335 radeon_vid_make_default();
1336 printf(RADEON_MSG" Video memory = %uMb\n",radeon_ram_size/0x100000);
1337 err = mtrr_set_type(pci_info.base0,radeon_ram_size,MTRR_TYPE_WRCOMB);
1338 if(!err) printf(RADEON_MSG" Set write-combining type of video memory\n");
1339 #ifndef RAGE128
1341 memset(&rinfo,0,sizeof(rinfo_t));
1342 if((besr.chip_flags&R_100) != R_100) rinfo.hasCRTC2 = 1;
1344 radeon_get_moninfo(&rinfo);
1345 if(rinfo.hasCRTC2) {
1346 printf(RADEON_MSG" DVI port has %s monitor connected\n",GET_MON_NAME(rinfo.dviDispType));
1347 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1349 else
1350 printf(RADEON_MSG" CRT port has %s monitor connected\n",GET_MON_NAME(rinfo.crtDispType));
1352 #endif
1353 save_regs();
1354 return 0;
1357 static void radeon_destroy(void)
1359 restore_regs();
1360 unmap_phys_mem(radeon_mem_base,radeon_ram_size);
1361 unmap_phys_mem(radeon_mmio_base,0xFFFF);
1364 static int radeon_get_caps(vidix_capability_t *to)
1366 memcpy(to,&def_cap,sizeof(vidix_capability_t));
1367 return 0;
1371 Full list of fourcc which are supported by Win2K radeon driver:
1372 YUY2, UYVY, DDES, OGLT, OGL2, OGLS, OGLB, OGNT, OGNZ, OGNS,
1373 IF09, YVU9, IMC4, M2IA, IYUV, VBID, DXT1, DXT2, DXT3, DXT4, DXT5
1375 typedef struct fourcc_desc_s
1377 uint32_t fourcc;
1378 unsigned max_srcw;
1379 }fourcc_desc_t;
1381 static const fourcc_desc_t supported_fourcc[] =
1383 { IMGFMT_Y800, 1567 },
1384 { IMGFMT_YVU9, 1567 },
1385 { IMGFMT_IF09, 1567 },
1386 { IMGFMT_YV12, 1567 },
1387 { IMGFMT_I420, 1567 },
1388 { IMGFMT_IYUV, 1567 },
1389 { IMGFMT_UYVY, 1551 },
1390 { IMGFMT_YUY2, 1551 },
1391 { IMGFMT_YVYU, 1551 },
1392 { IMGFMT_RGB15, 1551 },
1393 { IMGFMT_BGR15, 1551 },
1394 { IMGFMT_RGB16, 1551 },
1395 { IMGFMT_BGR16, 1551 },
1396 { IMGFMT_RGB32, 775 },
1397 { IMGFMT_BGR32, 775 }
1400 __inline__ static int is_supported_fourcc(uint32_t fourcc)
1402 unsigned i;
1403 for(i=0;i<sizeof(supported_fourcc)/sizeof(fourcc_desc_t);i++)
1405 if(fourcc==supported_fourcc[i].fourcc)
1406 return 1;
1408 return 0;
1411 static int radeon_query_fourcc(vidix_fourcc_t *to)
1413 if(is_supported_fourcc(to->fourcc))
1415 to->depth = VID_DEPTH_ALL;
1416 to->flags = VID_CAP_EXPAND | VID_CAP_SHRINK | VID_CAP_COLORKEY |
1417 VID_CAP_BLEND;
1418 return 0;
1420 else to->depth = to->flags = 0;
1421 return ENOSYS;
1424 static double H_scale_ratio;
1425 static void radeon_vid_dump_regs( void )
1427 size_t i;
1428 printf(RADEON_MSG"*** Begin of DRIVER variables dump ***\n");
1429 printf(RADEON_MSG"radeon_mmio_base=%p\n",radeon_mmio_base);
1430 printf(RADEON_MSG"radeon_mem_base=%p\n",radeon_mem_base);
1431 printf(RADEON_MSG"radeon_overlay_off=%08X\n",radeon_overlay_off);
1432 printf(RADEON_MSG"radeon_ram_size=%08X\n",radeon_ram_size);
1433 printf(RADEON_MSG"video mode: %ux%u@%u\n",radeon_get_xres(),radeon_get_yres(),radeon_vid_get_dbpp());
1434 printf(RADEON_MSG"H_scale_ratio=%8.2f\n",H_scale_ratio);
1435 printf(RADEON_MSG"*** Begin of OV0 registers dump ***\n");
1436 for(i=0;i<sizeof(vregs)/sizeof(video_registers_t);i++)
1437 printf(RADEON_MSG"%s = %08X\n",vregs[i].sname,INREG(vregs[i].name));
1438 printf(RADEON_MSG"*** End of OV0 registers dump ***\n");
1441 static void radeon_vid_stop_video( void )
1443 radeon_engine_idle();
1444 OUTREG(OV0_SCALE_CNTL, SCALER_SOFT_RESET);
1445 OUTREG(OV0_EXCLUSIVE_HORZ, 0);
1446 OUTREG(OV0_AUTO_FLIP_CNTL, 0); /* maybe */
1447 OUTREG(OV0_FILTER_CNTL, FILTER_HARDCODED_COEF);
1448 #ifdef RAGE128
1449 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_NE);
1450 #else
1451 OUTREG(OV0_KEY_CNTL, GRAPHIC_KEY_FN_EQ);
1452 #endif
1453 OUTREG(OV0_TEST, 0);
1456 static void radeon_vid_display_video( void )
1458 int bes_flags,force_second;
1459 radeon_fifo_wait(2);
1460 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
1461 radeon_engine_idle();
1462 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
1463 radeon_fifo_wait(15);
1465 force_second=0;
1467 /* Shutdown capturing */
1468 OUTREG(FCP_CNTL, FCP_CNTL__GND);
1469 OUTREG(CAP0_TRIG_CNTL, 0);
1471 OUTREG(VID_BUFFER_CONTROL, (1<<16) | 0x01);
1472 OUTREG(DISP_TEST_DEBUG_CNTL, 0);
1474 OUTREG(OV0_AUTO_FLIP_CNTL,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD);
1476 if(besr.deinterlace_on) OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
1477 #ifdef RAGE128
1478 OUTREG(OV0_COLOUR_CNTL, (besr.brightness & 0x7f) |
1479 (besr.saturation << 8) |
1480 (besr.saturation << 16));
1481 #endif
1482 radeon_fifo_wait(2);
1483 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
1484 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
1485 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
1487 OUTREG(OV0_H_INC, besr.h_inc);
1488 OUTREG(OV0_STEP_BY, besr.step_by);
1489 if(force_second)
1491 OUTREG(OV1_Y_X_START, besr.y_x_start);
1492 OUTREG(OV1_Y_X_END, besr.y_x_end);
1494 else
1496 OUTREG(OV0_Y_X_START, besr.y_x_start);
1497 OUTREG(OV0_Y_X_END, besr.y_x_end);
1499 OUTREG(OV0_V_INC, besr.v_inc);
1500 OUTREG(OV0_P1_BLANK_LINES_AT_TOP, besr.p1_blank_lines_at_top);
1501 OUTREG(OV0_P23_BLANK_LINES_AT_TOP, besr.p23_blank_lines_at_top);
1502 OUTREG(OV0_VID_BUF_PITCH0_VALUE, besr.vid_buf_pitch0_value);
1503 OUTREG(OV0_VID_BUF_PITCH1_VALUE, besr.vid_buf_pitch1_value);
1504 OUTREG(OV0_P1_X_START_END, besr.p1_x_start_end);
1505 OUTREG(OV0_P2_X_START_END, besr.p2_x_start_end);
1506 OUTREG(OV0_P3_X_START_END, besr.p3_x_start_end);
1507 #ifdef RADEON
1508 OUTREG(OV0_BASE_ADDR, besr.base_addr);
1509 #endif
1510 OUTREG(OV0_VID_BUF0_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1511 OUTREG(OV0_VID_BUF1_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1512 OUTREG(OV0_VID_BUF2_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1513 radeon_fifo_wait(9);
1514 OUTREG(OV0_VID_BUF3_BASE_ADRS, besr.vid_buf_base_adrs_y[0]);
1515 OUTREG(OV0_VID_BUF4_BASE_ADRS, besr.vid_buf_base_adrs_v[0]);
1516 OUTREG(OV0_VID_BUF5_BASE_ADRS, besr.vid_buf_base_adrs_u[0]);
1517 OUTREG(OV0_P1_V_ACCUM_INIT, besr.p1_v_accum_init);
1518 OUTREG(OV0_P1_H_ACCUM_INIT, besr.p1_h_accum_init);
1519 OUTREG(OV0_P23_H_ACCUM_INIT, besr.p23_h_accum_init);
1520 OUTREG(OV0_P23_V_ACCUM_INIT, besr.p23_v_accum_init);
1522 bes_flags = SCALER_ENABLE |
1523 SCALER_SMART_SWITCH |
1524 SCALER_Y2R_TEMP |
1525 SCALER_PIX_EXPAND;
1526 if(besr.double_buff) bes_flags |= SCALER_DOUBLE_BUFFER;
1527 if(besr.deinterlace_on) bes_flags |= SCALER_ADAPTIVE_DEINT;
1528 if(besr.horz_pick_nearest) bes_flags |= SCALER_HORZ_PICK_NEAREST;
1529 if(besr.vert_pick_nearest) bes_flags |= SCALER_VERT_PICK_NEAREST;
1530 #ifdef RAGE128
1531 bes_flags |= SCALER_BURST_PER_PLANE;
1532 #endif
1533 bes_flags |= (besr.surf_id << 8) & SCALER_SURFAC_FORMAT;
1534 if(besr.load_prg_start) bes_flags |= SCALER_PRG_LOAD_START;
1535 if(force_second) bes_flags |= SCALER_USE_OV1;
1536 else bes_flags &= ~SCALER_USE_OV1;
1537 OUTREG(OV0_SCALE_CNTL, bes_flags);
1538 radeon_fifo_wait(6);
1539 OUTREG(OV0_FILTER_CNTL,besr.filter_cntl);
1540 OUTREG(OV0_FOUR_TAP_COEF_0,besr.four_tap_coeff[0]);
1541 OUTREG(OV0_FOUR_TAP_COEF_1,besr.four_tap_coeff[1]);
1542 OUTREG(OV0_FOUR_TAP_COEF_2,besr.four_tap_coeff[2]);
1543 OUTREG(OV0_FOUR_TAP_COEF_3,besr.four_tap_coeff[3]);
1544 OUTREG(OV0_FOUR_TAP_COEF_4,besr.four_tap_coeff[4]);
1545 if(besr.swap_uv) OUTREG(OV0_TEST,INREG(OV0_TEST)|OV0_SWAP_UV);
1546 OUTREG(OV0_REG_LOAD_CNTL, 0);
1547 if(verbosity > VERBOSE_LEVEL) printf(RADEON_MSG"we wanted: scaler=%08X\n",bes_flags);
1548 if(verbosity > VERBOSE_LEVEL) radeon_vid_dump_regs();
1551 /* Goal of this function: hide RGB background and provide black screen around movie.
1552 Useful in '-vo fbdev:vidix -fs -zoom' mode.
1553 Reverse effect to colorkey */
1554 #ifdef RAGE128
1555 static void radeon_vid_exclusive( void )
1557 /* this function works only with Rage128.
1558 Radeon should has something the same */
1559 unsigned screenw,screenh;
1560 screenw = radeon_get_xres();
1561 screenh = radeon_get_yres();
1562 radeon_fifo_wait(2);
1563 OUTREG(OV0_EXCLUSIVE_VERT,(((screenh-1)<<16)&EXCL_VERT_END_MASK));
1564 OUTREG(OV0_EXCLUSIVE_HORZ,(((screenw/8+1)<<8)&EXCL_HORZ_END_MASK)|EXCL_HORZ_EXCLUSIVE_EN);
1567 static void radeon_vid_non_exclusive( void )
1569 OUTREG(OV0_EXCLUSIVE_HORZ,0);
1571 #endif
1573 static unsigned radeon_query_pitch(unsigned fourcc,const vidix_yuv_t *spitch)
1575 unsigned pitch,spy,spv,spu;
1576 spy = spv = spu = 0;
1577 switch(spitch->y)
1579 case 16:
1580 case 32:
1581 case 64:
1582 case 128:
1583 case 256: spy = spitch->y; break;
1584 default: break;
1586 switch(spitch->u)
1588 case 16:
1589 case 32:
1590 case 64:
1591 case 128:
1592 case 256: spu = spitch->u; break;
1593 default: break;
1595 switch(spitch->v)
1597 case 16:
1598 case 32:
1599 case 64:
1600 case 128:
1601 case 256: spv = spitch->v; break;
1602 default: break;
1604 switch(fourcc)
1606 /* 4:2:0 */
1607 case IMGFMT_IYUV:
1608 case IMGFMT_YV12:
1609 case IMGFMT_I420:
1610 if(spy > 16 && spu == spy/2 && spv == spy/2) pitch = spy;
1611 else pitch = 32;
1612 break;
1613 case IMGFMT_IF09:
1614 case IMGFMT_YVU9:
1615 if(spy >= 64 && spu == spy/4 && spv == spy/4) pitch = spy;
1616 else pitch = 64;
1617 break;
1618 default:
1619 if(spy >= 16) pitch = spy;
1620 else pitch = 16;
1621 break;
1623 return pitch;
1626 static void Calc_H_INC_STEP_BY (
1627 int fieldvalue_OV0_SURFACE_FORMAT,
1628 double H_scale_ratio,
1629 int DisallowFourTapVertFiltering,
1630 int DisallowFourTapUVVertFiltering,
1631 uint32_t *val_OV0_P1_H_INC,
1632 uint32_t *val_OV0_P1_H_STEP_BY,
1633 uint32_t *val_OV0_P23_H_INC,
1634 uint32_t *val_OV0_P23_H_STEP_BY,
1635 int *P1GroupSize,
1636 int *P1StepSize,
1637 int *P23StepSize )
1640 double ClocksNeededFor16Pixels;
1642 switch (fieldvalue_OV0_SURFACE_FORMAT)
1644 case 3:
1645 case 4: /*16BPP (ARGB1555 and RGB565) */
1646 /* All colour components are fetched in pairs */
1647 *P1GroupSize = 2;
1648 /* We don't support four tap in this mode because G's are split between two bytes. In theory we could support it if */
1649 /* we saved part of the G when fetching the R, and then filter the G, followed by the B in the following cycles. */
1650 if (H_scale_ratio>=.5)
1652 /* We are actually generating two pixels (but 3 colour components) per tick. Thus we don't have to skip */
1653 /* until we reach .5. P1 and P23 are the same. */
1654 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1655 *val_OV0_P1_H_STEP_BY = 1;
1656 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1657 *val_OV0_P23_H_STEP_BY = 1;
1658 *P1StepSize = 1;
1659 *P23StepSize = 1;
1661 else if (H_scale_ratio>=.25)
1663 /* Step by two */
1664 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1665 *val_OV0_P1_H_STEP_BY = 2;
1666 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1667 *val_OV0_P23_H_STEP_BY = 2;
1668 *P1StepSize = 2;
1669 *P23StepSize = 2;
1671 else if (H_scale_ratio>=.125)
1673 /* Step by four */
1674 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1675 *val_OV0_P1_H_STEP_BY = 3;
1676 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1677 *val_OV0_P23_H_STEP_BY = 3;
1678 *P1StepSize = 4;
1679 *P23StepSize = 4;
1681 else if (H_scale_ratio>=.0625)
1683 /* Step by eight */
1684 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1685 *val_OV0_P1_H_STEP_BY = 4;
1686 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1687 *val_OV0_P23_H_STEP_BY = 4;
1688 *P1StepSize = 8;
1689 *P23StepSize = 8;
1691 else if (H_scale_ratio>=0.03125)
1693 /* Step by sixteen */
1694 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1695 *val_OV0_P1_H_STEP_BY = 5;
1696 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1697 *val_OV0_P23_H_STEP_BY = 5;
1698 *P1StepSize = 16;
1699 *P23StepSize = 16;
1701 else
1703 H_scale_ratio=0.03125;
1704 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1705 *val_OV0_P1_H_STEP_BY = 5;
1706 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1707 *val_OV0_P23_H_STEP_BY = 5;
1708 *P1StepSize = 16;
1709 *P23StepSize = 16;
1711 break;
1712 case 6: /*32BPP RGB */
1713 if (H_scale_ratio>=1.5 && !DisallowFourTapVertFiltering)
1715 /* All colour components are fetched in pairs */
1716 *P1GroupSize = 2;
1717 /* With four tap filtering, we can generate two colour components every clock, or two pixels every three */
1718 /* clocks. This means that we will have four tap filtering when scaling 1.5 or more. */
1719 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1720 *val_OV0_P1_H_STEP_BY = 0;
1721 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1722 *val_OV0_P23_H_STEP_BY = 0;
1723 *P1StepSize = 1;
1724 *P23StepSize = 1;
1726 else if (H_scale_ratio>=0.75)
1728 /* Four G colour components are fetched at once */
1729 *P1GroupSize = 4;
1730 /* R and B colour components are fetched in pairs */
1731 /* With two tap filtering, we can generate four colour components every clock. */
1732 /* This means that we will have two tap filtering when scaling 1.0 or more. */
1733 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1734 *val_OV0_P1_H_STEP_BY = 1;
1735 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1736 *val_OV0_P23_H_STEP_BY = 1;
1737 *P1StepSize = 1;
1738 *P23StepSize = 1;
1740 else if (H_scale_ratio>=0.375)
1742 /* Step by two. */
1743 /* Four G colour components are fetched at once */
1744 *P1GroupSize = 4;
1745 /* R and B colour components are fetched in pairs */
1746 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1747 *val_OV0_P1_H_STEP_BY = 2;
1748 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1749 *val_OV0_P23_H_STEP_BY = 2;
1750 *P1StepSize = 2;
1751 *P23StepSize = 2;
1753 else if (H_scale_ratio>=0.25)
1755 /* Step by two. */
1756 /* Four G colour components are fetched at once */
1757 *P1GroupSize = 4;
1758 /* R and B colour components are fetched in pairs */
1759 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1760 *val_OV0_P1_H_STEP_BY = 2;
1761 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1762 *val_OV0_P23_H_STEP_BY = 3;
1763 *P1StepSize = 2;
1764 *P23StepSize = 4;
1766 else if (H_scale_ratio>=0.1875)
1768 /* Step by four */
1769 /* Four G colour components are fetched at once */
1770 *P1GroupSize = 4;
1771 /* R and B colour components are fetched in pairs */
1772 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1773 *val_OV0_P1_H_STEP_BY = 3;
1774 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1775 *val_OV0_P23_H_STEP_BY = 3;
1776 *P1StepSize = 4;
1777 *P23StepSize = 4;
1779 else if (H_scale_ratio>=0.125)
1781 /* Step by four */
1782 /* Four G colour components are fetched at once */
1783 *P1GroupSize = 4;
1784 /* R and B colour components are fetched in pairs */
1785 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1786 *val_OV0_P1_H_STEP_BY = 3;
1787 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1788 *val_OV0_P23_H_STEP_BY = 4;
1789 *P1StepSize = 4;
1790 *P23StepSize = 8;
1792 else if (H_scale_ratio>=0.09375)
1794 /* Step by eight */
1795 /* Four G colour components are fetched at once */
1796 *P1GroupSize = 4;
1797 /* R and B colour components are fetched in pairs */
1798 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1799 *val_OV0_P1_H_STEP_BY = 4;
1800 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1801 *val_OV0_P23_H_STEP_BY = 4;
1802 *P1StepSize = 8;
1803 *P23StepSize = 8;
1805 else if (H_scale_ratio>=0.0625)
1807 /* Step by eight */
1808 /* Four G colour components are fetched at once */
1809 *P1GroupSize = 4;
1810 /* R and B colour components are fetched in pairs */
1811 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1812 *val_OV0_P1_H_STEP_BY = 5;
1813 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1814 *val_OV0_P23_H_STEP_BY = 5;
1815 *P1StepSize = 16;
1816 *P23StepSize = 16;
1818 else
1820 H_scale_ratio=0.0625;
1821 *P1GroupSize = 4;
1822 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1823 *val_OV0_P1_H_STEP_BY = 5;
1824 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1825 *val_OV0_P23_H_STEP_BY = 5;
1826 *P1StepSize = 16;
1827 *P23StepSize = 16;
1829 break;
1830 case 9:
1831 /*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. */
1832 /* four tap on both (unless Y is too wide) */
1833 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
1834 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1835 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1836 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1837 { /*0.75 */
1838 /* Colour components are fetched in pairs */
1839 *P1GroupSize = 2;
1840 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1841 *val_OV0_P1_H_STEP_BY = 0;
1842 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1843 *val_OV0_P23_H_STEP_BY = 0;
1844 *P1StepSize = 1;
1845 *P23StepSize = 1;
1847 /* two tap on Y (because it is too big for four tap), four tap on UV */
1848 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0) &&
1849 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1850 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1851 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
1852 { /*0.75 */
1853 *P1GroupSize = 4;
1854 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1855 *val_OV0_P1_H_STEP_BY = 1;
1856 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1857 *val_OV0_P23_H_STEP_BY = 0;
1858 *P1StepSize = 1;
1859 *P23StepSize = 1;
1861 /* We scale the Y with the four tap filters, but UV's are generated
1862 with dual two tap configuration. */
1863 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+1+1) / 16.0) &&
1864 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1865 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000) &&
1866 !DisallowFourTapVertFiltering)
1867 { /*0.625 */
1868 *P1GroupSize = 2;
1869 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1870 *val_OV0_P1_H_STEP_BY = 0;
1871 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1872 *val_OV0_P23_H_STEP_BY = 1;
1873 *P1StepSize = 1;
1874 *P23StepSize = 1;
1876 /* We scale the Y, U, and V with the two tap filters */
1877 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0) &&
1878 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1879 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x2000))
1880 { /*0.375 */
1881 *P1GroupSize = 4;
1882 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1883 *val_OV0_P1_H_STEP_BY = 1;
1884 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1885 *val_OV0_P23_H_STEP_BY = 1;
1886 *P1StepSize = 1;
1887 *P23StepSize = 1;
1889 /* We scale step the U and V by two to allow more bandwidth for fetching Y's,
1890 thus we won't drop Y's yet. */
1891 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+.5+.5) / 16.0) &&
1892 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1893 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1894 { /*>=0.3125 and >.333333~ */
1895 *P1GroupSize = 4;
1896 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
1897 *val_OV0_P1_H_STEP_BY = 1;
1898 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1899 *val_OV0_P23_H_STEP_BY = 2;
1900 *P1StepSize = 1;
1901 *P23StepSize = 2;
1903 /* We step the Y, U, and V by two. */
1904 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0) &&
1905 ((uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5)<=0x3000) &&
1906 ((uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5)<=0x2000))
1908 *P1GroupSize = 4;
1909 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1910 *val_OV0_P1_H_STEP_BY = 2;
1911 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*2)) * (1<<0xc) + 0.5);
1912 *val_OV0_P23_H_STEP_BY = 2;
1913 *P1StepSize = 2;
1914 *P23StepSize = 2;
1916 /* We step the Y by two and the U and V by four. */
1917 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=2+.25+.25) / 16.0) &&
1918 ((uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5)<=0x3000) &&
1919 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1921 *P1GroupSize = 4;
1922 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
1923 *val_OV0_P1_H_STEP_BY = 2;
1924 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1925 *val_OV0_P23_H_STEP_BY = 3;
1926 *P1StepSize = 2;
1927 *P23StepSize = 4;
1929 /* We step the Y, U, and V by four. */
1930 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
1931 ((uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5)<=0x3000) &&
1932 ((uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5)<=0x2000))
1934 *P1GroupSize = 4;
1935 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
1936 *val_OV0_P1_H_STEP_BY = 3;
1937 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*4)) * (1<<0xc) + 0.5);
1938 *val_OV0_P23_H_STEP_BY = 3;
1939 *P1StepSize = 4;
1940 *P23StepSize = 4;
1942 /* 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 */
1944 /* We step the Y, U, and V by eight. */
1945 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) &&
1946 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1947 ((uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5)<=0x2000))
1949 *P1GroupSize = 4;
1950 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1951 *val_OV0_P1_H_STEP_BY = 4;
1952 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*8)) * (1<<0xc) + 0.5);
1953 *val_OV0_P23_H_STEP_BY = 4;
1954 *P1StepSize = 8;
1955 *P23StepSize = 8;
1957 /* We step the Y by eight and the U and V by sixteen. */
1958 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.0625+.0625) / 16.0) &&
1959 ((uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5)<=0x3000) &&
1960 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1962 *P1GroupSize = 4;
1963 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
1964 *val_OV0_P1_H_STEP_BY = 4;
1965 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1966 *val_OV0_P23_H_STEP_BY = 5;
1967 *P1StepSize = 8;
1968 *P23StepSize = 16;
1970 /* We step the Y, U, and V by sixteen. */
1971 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16.0) &&
1972 ((uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5)<=0x3000) &&
1973 ((uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5)<=0x2000))
1975 *P1GroupSize = 4;
1976 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1977 *val_OV0_P1_H_STEP_BY = 5;
1978 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1979 *val_OV0_P23_H_STEP_BY = 5;
1980 *P1StepSize = 16;
1981 *P23StepSize = 16;
1983 else
1985 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.0625+.0625) / 16;
1986 *P1GroupSize = 4;
1987 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
1988 *val_OV0_P1_H_STEP_BY = 5;
1989 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*4*16)) * (1<<0xc) + 0.5);
1990 *val_OV0_P23_H_STEP_BY = 5;
1991 *P1StepSize = 16;
1992 *P23StepSize = 16;
1994 break;
1995 case 10:
1996 case 11:
1997 case 12:
1998 case 13:
1999 case 14: /* YUV12, VYUY422, YUYV422, YOverPkCRCB12, YWovenWithPkCRCB12 */
2000 /* We scale the Y, U, and V with the four tap filters */
2001 /* four tap on both (unless Y is too wide) */
2002 if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+4+4) / 16.0) &&
2003 !DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2004 { /*0.75 */
2005 *P1GroupSize = 2;
2006 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2007 *val_OV0_P1_H_STEP_BY = 0;
2008 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2009 *val_OV0_P23_H_STEP_BY = 0;
2010 *P1StepSize = 1;
2011 *P23StepSize = 1;
2013 /* two tap on Y (because it is too big for four tap), four tap on UV */
2014 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=4+4+4) / 16.0) &&
2015 DisallowFourTapVertFiltering && !DisallowFourTapUVVertFiltering)
2016 { /*0.75 */
2017 *P1GroupSize = 4;
2018 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2019 *val_OV0_P1_H_STEP_BY = 1;
2020 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2021 *val_OV0_P23_H_STEP_BY = 0;
2022 *P1StepSize = 1;
2023 *P23StepSize = 1;
2025 /* We scale the Y with the four tap filters, but UV's are generated
2026 with dual two tap configuration. */
2027 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=8+2+2) / 16.0) &&
2028 !DisallowFourTapVertFiltering)
2029 { /*0.625 */
2030 *P1GroupSize = 2;
2031 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2032 *val_OV0_P1_H_STEP_BY = 0;
2033 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2034 *val_OV0_P23_H_STEP_BY = 1;
2035 *P1StepSize = 1;
2036 *P23StepSize = 1;
2038 /* We scale the Y, U, and V with the two tap filters */
2039 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+2+2) / 16.0)
2040 { /*0.375 */
2041 *P1GroupSize = 4;
2042 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2043 *val_OV0_P1_H_STEP_BY = 1;
2044 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2045 *val_OV0_P23_H_STEP_BY = 1;
2046 *P1StepSize = 1;
2047 *P23StepSize = 1;
2049 /* We scale step the U and V by two to allow more bandwidth for
2050 fetching Y's, thus we won't drop Y's yet. */
2051 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=4+1+1) / 16.0)
2052 { /*0.312 */
2053 *P1GroupSize = 4;
2054 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio)) * (1<<0xc) + 0.5);
2055 *val_OV0_P1_H_STEP_BY = 1;
2056 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2057 *val_OV0_P23_H_STEP_BY = 2;
2058 *P1StepSize = 1;
2059 *P23StepSize = 2;
2061 /* We step the Y, U, and V by two. */
2062 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+1+1) / 16.0)
2064 *P1GroupSize = 4;
2065 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2066 *val_OV0_P1_H_STEP_BY = 2;
2067 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*2)) * (1<<0xc) + 0.5);
2068 *val_OV0_P23_H_STEP_BY = 2;
2069 *P1StepSize = 2;
2070 *P23StepSize = 2;
2072 /* We step the Y by two and the U and V by four. */
2073 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=2+.5+.5) / 16.0)
2075 *P1GroupSize = 4;
2076 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*2)) * (1<<0xc) + 0.5);
2077 *val_OV0_P1_H_STEP_BY = 2;
2078 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2079 *val_OV0_P23_H_STEP_BY = 3;
2080 *P1StepSize = 2;
2081 *P23StepSize = 4;
2083 /* We step the Y, U, and V by four. */
2084 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=1+.5+.5) / 16.0)
2086 *P1GroupSize = 4;
2087 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2088 *val_OV0_P1_H_STEP_BY = 3;
2089 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*4)) * (1<<0xc) + 0.5);
2090 *val_OV0_P23_H_STEP_BY = 3;
2091 *P1StepSize = 4;
2092 *P23StepSize = 4;
2094 /* We step the Y by four and the U and V by eight. */
2095 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=1+.25+.25) / 16.0) &&
2096 (fieldvalue_OV0_SURFACE_FORMAT==10))
2098 *P1GroupSize = 4;
2099 /* Can't mix step by 3 and step by 4 for packed modes */
2100 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*4)) * (1<<0xc) + 0.5);
2101 *val_OV0_P1_H_STEP_BY = 3;
2102 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2103 *val_OV0_P23_H_STEP_BY = 4;
2104 *P1StepSize = 4;
2105 *P23StepSize = 8;
2107 /* We step the Y, U, and V by eight. */
2108 else if (H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.25+.25) / 16.0)
2110 *P1GroupSize = 4;
2111 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2112 *val_OV0_P1_H_STEP_BY = 4;
2113 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2114 *val_OV0_P23_H_STEP_BY = 4;
2115 *P1StepSize = 8;
2116 *P23StepSize = 8;
2118 /* We step the Y by eight and the U and V by sixteen. */
2119 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.5+.125+.125) / 16.0) && (fieldvalue_OV0_SURFACE_FORMAT==10))
2121 *P1GroupSize = 4;
2122 /* Step by 5 not supported for packed modes */
2123 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2124 *val_OV0_P1_H_STEP_BY = 4;
2125 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2126 *val_OV0_P23_H_STEP_BY = 5;
2127 *P1StepSize = 8;
2128 *P23StepSize = 16;
2130 /* We step the Y, U, and V by sixteen. */
2131 else if ((H_scale_ratio>=(ClocksNeededFor16Pixels=.25+.125+.125) / 16.0) &&
2132 (fieldvalue_OV0_SURFACE_FORMAT==10))
2134 *P1GroupSize = 4;
2135 /* Step by 5 not supported for packed modes */
2136 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2137 *val_OV0_P1_H_STEP_BY = 5;
2138 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2139 *val_OV0_P23_H_STEP_BY = 5;
2140 *P1StepSize = 16;
2141 *P23StepSize = 16;
2143 else
2145 if (fieldvalue_OV0_SURFACE_FORMAT==10)
2147 H_scale_ratio=(ClocksNeededFor16Pixels=.25+.125+.125) / 16;
2148 *P1GroupSize = 4;
2149 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*16)) * (1<<0xc) + 0.5);
2150 *val_OV0_P1_H_STEP_BY = 5;
2151 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*16)) * (1<<0xc) + 0.5);
2152 *val_OV0_P23_H_STEP_BY = 5;
2153 *P1StepSize = 16;
2154 *P23StepSize = 16;
2156 else
2158 H_scale_ratio=(ClocksNeededFor16Pixels=.5+.25+.25) / 16;
2159 *P1GroupSize = 4;
2160 *val_OV0_P1_H_INC = (uint16_t)((1/(H_scale_ratio*8)) * (1<<0xc) + 0.5);
2161 *val_OV0_P1_H_STEP_BY = 4;
2162 *val_OV0_P23_H_INC = (uint16_t)((1/(H_scale_ratio*2*8)) * (1<<0xc) + 0.5);
2163 *val_OV0_P23_H_STEP_BY = 4;
2164 *P1StepSize = 8;
2165 *P23StepSize = 8;
2168 break;
2169 default: break;
2172 besr.h_inc = (*(val_OV0_P1_H_INC)&0x3fff) | ((*(val_OV0_P23_H_INC)&0x3fff)<<16);
2173 besr.step_by = (*(val_OV0_P1_H_STEP_BY)&0x7) | ((*(val_OV0_P23_H_STEP_BY)&0x7)<<8);
2176 /* ********************************************************* */
2177 /* ** Setup Black Bordering */
2178 /* ********************************************************* */
2180 static void ComputeBorders( vidix_playback_t *config, int VertUVSubSample )
2182 double tempBLANK_LINES_AT_TOP;
2183 unsigned TopLine,BottomLine,SourceLinesUsed,TopUVLine,BottomUVLine,SourceUVLinesUsed;
2184 uint32_t val_OV0_P1_ACTIVE_LINES_M1,val_OV0_P1_BLNK_LN_AT_TOP_M1;
2185 uint32_t val_OV0_P23_ACTIVE_LINES_M1,val_OV0_P23_BLNK_LN_AT_TOP_M1;
2187 if (floor(config->src.y)<0) {
2188 tempBLANK_LINES_AT_TOP = -floor(config->src.y);
2189 TopLine = 0;
2191 else {
2192 tempBLANK_LINES_AT_TOP = 0;
2193 TopLine = (int)floor(config->src.y);
2195 /* Round rSrcBottom up and subtract one */
2196 if (ceil(config->src.y+config->src.h) > config->src.h)
2198 BottomLine = config->src.h - 1;
2200 else
2202 BottomLine = (int)ceil(config->src.y+config->src.h) - 1;
2205 if (BottomLine >= TopLine)
2207 SourceLinesUsed = BottomLine - TopLine + 1;
2209 else
2211 /*CYCACC_ASSERT(0, "SourceLinesUsed less than or equal to zero.") */
2212 SourceLinesUsed = 1;
2216 int SourceHeightInPixels;
2217 SourceHeightInPixels = BottomLine - TopLine + 1;
2220 val_OV0_P1_ACTIVE_LINES_M1 = SourceLinesUsed - 1;
2221 val_OV0_P1_BLNK_LN_AT_TOP_M1 = ((int)tempBLANK_LINES_AT_TOP-1) & 0xfff;
2223 TopUVLine = ((int)(config->src.y/VertUVSubSample) < 0) ? 0: (int)(config->src.y/VertUVSubSample); /* Round rSrcTop down */
2224 BottomUVLine = (ceil(((config->src.y+config->src.h)/VertUVSubSample)) > (config->src.h/VertUVSubSample))
2225 ? (config->src.h/VertUVSubSample)-1 : (unsigned int)ceil(((config->src.y+config->src.h)/VertUVSubSample))-1;
2227 if (BottomUVLine >= TopUVLine)
2229 SourceUVLinesUsed = BottomUVLine - TopUVLine + 1;
2231 else
2233 /*CYCACC_ASSERT(0, "SourceUVLinesUsed less than or equal to zero.") */
2234 SourceUVLinesUsed = 1;
2236 val_OV0_P23_ACTIVE_LINES_M1 = SourceUVLinesUsed - 1;
2237 val_OV0_P23_BLNK_LN_AT_TOP_M1 = ((int)(tempBLANK_LINES_AT_TOP/VertUVSubSample)-1) & 0x7ff;
2238 besr.p1_blank_lines_at_top = (val_OV0_P1_BLNK_LN_AT_TOP_M1 & 0xfff) |
2239 ((val_OV0_P1_ACTIVE_LINES_M1 & 0xfff) << 16);
2240 besr.p23_blank_lines_at_top = (val_OV0_P23_BLNK_LN_AT_TOP_M1 & 0x7ff) |
2241 ((val_OV0_P23_ACTIVE_LINES_M1 & 0x7ff) << 16);
2245 static void ComputeXStartEnd(
2246 int is_400,
2247 uint32_t LeftPixel,uint32_t LeftUVPixel,
2248 uint32_t MemWordsInBytes,uint32_t BytesPerPixel,
2249 uint32_t SourceWidthInPixels, uint32_t P1StepSize,
2250 uint32_t BytesPerUVPixel,uint32_t SourceUVWidthInPixels,
2251 uint32_t P23StepSize, uint32_t *p1_x_start, uint32_t *p2_x_start )
2253 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START,val_OV0_P3_X_START;
2254 uint32_t val_OV0_P1_X_END,val_OV0_P2_X_END,val_OV0_P3_X_END;
2255 /* 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. */
2257 val_OV0_P1_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2258 val_OV0_P1_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P1StepSize) * P1StepSize;
2260 val_OV0_P2_X_START = val_OV0_P2_X_END = 0;
2261 switch (besr.surf_id)
2263 case 9:
2264 case 10:
2265 case 13:
2266 case 14: /* ToDo_Active: The driver must insure that the initial value is */
2267 /* a multiple of a power of two when decimating */
2268 val_OV0_P2_X_START = (int)LeftUVPixel %
2269 (MemWordsInBytes/BytesPerUVPixel);
2270 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START +
2271 SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2272 break;
2273 case 11:
2274 case 12: val_OV0_P2_X_START = (int)LeftUVPixel % (MemWordsInBytes/(BytesPerPixel*2));
2275 val_OV0_P2_X_END = (int)((val_OV0_P2_X_START + SourceUVWidthInPixels - 1) / P23StepSize) * P23StepSize;
2276 break;
2277 case 3:
2278 case 4: val_OV0_P2_X_START = val_OV0_P1_X_START;
2279 /* This value is needed only to allow proper setting of */
2280 /* val_OV0_PRESHIFT_P23_TO */
2281 /* val_OV0_P2_X_END = 0; */
2282 break;
2283 case 6: val_OV0_P2_X_START = (int)LeftPixel % (MemWordsInBytes/BytesPerPixel);
2284 val_OV0_P2_X_END = (int)((val_OV0_P1_X_START + SourceWidthInPixels - 1) / P23StepSize) * P23StepSize;
2285 break;
2286 default: /* insert debug statement here. */
2287 RADEON_ASSERT("unknown fourcc\n");
2288 break;
2290 val_OV0_P3_X_START = val_OV0_P2_X_START;
2291 val_OV0_P3_X_END = val_OV0_P2_X_END;
2293 besr.p1_x_start_end = (val_OV0_P1_X_END&0x7ff) | ((val_OV0_P1_X_START&0x7ff)<<16);
2294 besr.p2_x_start_end = (val_OV0_P2_X_END&0x7ff) | ((val_OV0_P2_X_START&0x7ff)<<16);
2295 besr.p3_x_start_end = (val_OV0_P3_X_END&0x7ff) | ((val_OV0_P3_X_START&0x7ff)<<16);
2296 if(is_400)
2298 besr.p2_x_start_end = 0;
2299 besr.p3_x_start_end = 0;
2301 *p1_x_start = val_OV0_P1_X_START;
2302 *p2_x_start = val_OV0_P2_X_START;
2305 static void ComputeAccumInit(
2306 uint32_t val_OV0_P1_X_START,uint32_t val_OV0_P2_X_START,
2307 uint32_t val_OV0_P1_H_INC,uint32_t val_OV0_P23_H_INC,
2308 uint32_t val_OV0_P1_H_STEP_BY,uint32_t val_OV0_P23_H_STEP_BY,
2309 uint32_t CRT_V_INC,
2310 uint32_t P1GroupSize, uint32_t P23GroupSize,
2311 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2312 uint32_t val_OV0_P23_MAX_LN_IN_PER_LN_OUT)
2314 uint32_t val_OV0_P1_H_ACCUM_INIT,val_OV0_PRESHIFT_P1_TO;
2315 uint32_t val_OV0_P23_H_ACCUM_INIT,val_OV0_PRESHIFT_P23_TO;
2316 uint32_t val_OV0_P1_V_ACCUM_INIT,val_OV0_P23_V_ACCUM_INIT;
2317 /* 2.5 puts the kernal 50% of the way between the source pixel that is off screen */
2318 /* and the first on-screen source pixel. "(float)valOV0_P?_H_INC / (1<<0xc)" is */
2319 /* the distance (in source pixel coordinates) to the center of the first */
2320 /* destination pixel. Need to add additional pixels depending on how many pixels */
2321 /* are fetched at a time and how many pixels in a set are masked. */
2322 /* P23 values are always fetched in groups of two or four. If the start */
2323 /* pixel does not fall on the boundary, then we need to shift preshift for */
2324 /* some additional pixels */
2327 double ExtraHalfPixel;
2328 double tempAdditionalShift;
2329 double tempP1HStartPoint;
2330 double tempP23HStartPoint;
2331 double tempP1Init;
2332 double tempP23Init;
2334 if (besr.horz_pick_nearest) ExtraHalfPixel = 0.5;
2335 else ExtraHalfPixel = 0.0;
2336 tempAdditionalShift = val_OV0_P1_X_START % P1GroupSize + ExtraHalfPixel;
2337 tempP1HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P1_H_INC / (1<<0xd));
2338 tempP1Init = (double)((int)(tempP1HStartPoint * (1<<0x5) + 0.5)) / (1<<0x5);
2340 /* P23 values are always fetched in pairs. If the start pixel is odd, then we */
2341 /* need to shift an additional pixel */
2342 /* Note that if the pitch is a multiple of two, and if we store fields using */
2343 /* the traditional planer format where the V plane and the U plane share the */
2344 /* same pitch, then OverlayRegFields->val_OV0_P2_X_START % P23Group */
2345 /* OverlayRegFields->val_OV0_P3_X_START % P23GroupSize. Either way */
2346 /* it is a requirement that the U and V start on the same polarity byte */
2347 /* (even or odd). */
2348 tempAdditionalShift = val_OV0_P2_X_START % P23GroupSize + ExtraHalfPixel;
2349 tempP23HStartPoint = tempAdditionalShift + 2.5 + ((float)val_OV0_P23_H_INC / (1<<0xd));
2350 tempP23Init = (double)((int)(tempP23HStartPoint * (1<<0x5) + 0.5)) / (1 << 0x5);
2351 val_OV0_P1_H_ACCUM_INIT = (int)((tempP1Init - (int)tempP1Init) * (1<<0x5));
2352 val_OV0_PRESHIFT_P1_TO = (int)tempP1Init;
2353 val_OV0_P23_H_ACCUM_INIT = (int)((tempP23Init - (int)tempP23Init) * (1<<0x5));
2354 val_OV0_PRESHIFT_P23_TO = (int)tempP23Init;
2357 /* ************************************************************** */
2358 /* ** Calculate values for initializing the vertical accumulators */
2359 /* ************************************************************** */
2362 double ExtraHalfLine;
2363 double ExtraFullLine;
2364 double tempP1VStartPoint;
2365 double tempP23VStartPoint;
2367 if (besr.vert_pick_nearest) ExtraHalfLine = 0.5;
2368 else ExtraHalfLine = 0.0;
2370 if (val_OV0_P1_H_STEP_BY==0)ExtraFullLine = 1.0;
2371 else ExtraFullLine = 0.0;
2373 tempP1VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine + ((float)CRT_V_INC / (1<<0xd));
2374 if (tempP1VStartPoint>2.5 + 2*ExtraFullLine)
2376 tempP1VStartPoint = 2.5 + 2*ExtraFullLine;
2378 val_OV0_P1_V_ACCUM_INIT = (int)(tempP1VStartPoint * (1<<0x5) + 0.5);
2380 if (val_OV0_P23_H_STEP_BY==0)ExtraFullLine = 1.0;
2381 else ExtraFullLine = 0.0;
2383 switch (besr.surf_id)
2385 case 10:
2386 case 13:
2387 case 14: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2388 ((float)CRT_V_INC / (1<<0xe));
2389 break;
2390 case 9: tempP23VStartPoint = 1.5 + ExtraFullLine + ExtraHalfLine +
2391 ((float)CRT_V_INC / (1<<0xf));
2392 break;
2393 case 3:
2394 case 4:
2395 case 6:
2396 case 11:
2397 case 12: tempP23VStartPoint = 0;
2398 break;
2399 default: tempP23VStartPoint = 0xFFFF;/* insert debug statement here */
2400 break;
2403 if (tempP23VStartPoint>2.5 + 2*ExtraFullLine)
2405 tempP23VStartPoint = 2.5 + 2*ExtraFullLine;
2408 val_OV0_P23_V_ACCUM_INIT = (int)(tempP23VStartPoint * (1<<0x5) + 0.5);
2410 besr.p1_h_accum_init = ((val_OV0_P1_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P1_TO&0xf)<<28);
2411 besr.p1_v_accum_init = (val_OV0_P1_MAX_LN_IN_PER_LN_OUT&0x3) |((val_OV0_P1_V_ACCUM_INIT&0x7ff)<<15);
2412 besr.p23_h_accum_init= ((val_OV0_P23_H_ACCUM_INIT&0x1f)<<15) |((val_OV0_PRESHIFT_P23_TO&0xf)<<28);
2413 besr.p23_v_accum_init= (val_OV0_P23_MAX_LN_IN_PER_LN_OUT&0x3)|((val_OV0_P23_V_ACCUM_INIT&0x3ff)<<15);
2416 typedef struct RangeAndCoefSet {
2417 double Range;
2418 signed char CoefSet[5][4];
2419 } RANGEANDCOEFSET;
2421 /* Filter Setup Routine */
2422 static void FilterSetup ( uint32_t val_OV0_P1_H_INC )
2424 static const RANGEANDCOEFSET ArrayOfSets[] = {
2425 {0.25, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2426 {0.26, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2427 {0.27, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2428 {0.28, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2429 {0.29, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2430 {0.30, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2431 {0.31, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2432 {0.32, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2433 {0.33, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2434 {0.34, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2435 {0.35, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2436 {0.36, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2437 {0.37, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2438 {0.38, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2439 {0.39, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2440 {0.40, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2441 {0.41, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2442 {0.42, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2443 {0.43, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2444 {0.44, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2445 {0.45, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2446 {0.46, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2447 {0.47, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2448 {0.48, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2449 {0.49, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2450 {0.50, {{ 7, 16, 9, 0}, { 7, 16, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 3, 13, 13, 3}, }},
2451 {0.51, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 15, 11, 1}, { 4, 15, 12, 1}, { 2, 14, 14, 2}, }},
2452 {0.52, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2453 {0.53, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 5, 16, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2454 {0.54, {{ 7, 17, 8, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 2, 14, 14, 2}, }},
2455 {0.55, {{ 7, 18, 7, 0}, { 6, 17, 9, 0}, { 4, 17, 11, 0}, { 3, 15, 13, 1}, { 1, 15, 15, 1}, }},
2456 {0.56, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2457 {0.57, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2458 {0.58, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2459 {0.59, {{ 7, 18, 7, 0}, { 5, 18, 9, 0}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2460 {0.60, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2461 {0.61, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2462 {0.62, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2463 {0.63, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 11, 0}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2464 {0.64, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 1, 15, 15, 1}, }},
2465 {0.65, {{ 7, 18, 8, -1}, { 6, 17, 10, -1}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2466 {0.66, {{ 7, 18, 8, -1}, { 6, 18, 10, -2}, { 4, 17, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2467 {0.67, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 18, 12, -1}, { 2, 17, 13, 0}, { 0, 16, 16, 0}, }},
2468 {0.68, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2469 {0.69, {{ 7, 20, 7, -2}, { 5, 19, 10, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2470 {0.70, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2471 {0.71, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 3, 19, 12, -2}, { 1, 18, 14, -1}, { 0, 16, 16, 0}, }},
2472 {0.72, {{ 7, 20, 7, -2}, { 5, 20, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2473 {0.73, {{ 7, 20, 7, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2474 {0.74, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 2, 20, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2475 {0.75, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2476 {0.76, {{ 6, 22, 6, -2}, { 4, 21, 9, -2}, { 1, 21, 12, -2}, { 0, 19, 15, -2}, {-1, 17, 17, -1}, }},
2477 {0.77, {{ 6, 22, 6, -2}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2478 {0.78, {{ 6, 21, 6, -1}, { 3, 22, 9, -2}, { 1, 22, 12, -3}, { 0, 19, 15, -2}, {-2, 18, 18, -2}, }},
2479 {0.79, {{ 5, 23, 5, -1}, { 3, 22, 9, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2480 {0.80, {{ 5, 23, 5, -1}, { 3, 23, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2481 {0.81, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-2, 18, 18, -2}, }},
2482 {0.82, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 12, -3}, {-1, 21, 15, -3}, {-3, 19, 19, -3}, }},
2483 {0.83, {{ 5, 23, 5, -1}, { 2, 24, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2484 {0.84, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2485 {0.85, {{ 4, 25, 4, -1}, { 1, 25, 8, -2}, { 0, 23, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2486 {0.86, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2487 {0.87, {{ 4, 24, 4, 0}, { 1, 25, 7, -1}, {-1, 24, 11, -2}, {-2, 22, 15, -3}, {-3, 19, 19, -3}, }},
2488 {0.88, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2489 {0.89, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-1, 24, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2490 {0.90, {{ 3, 26, 3, 0}, { 0, 26, 7, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2491 {0.91, {{ 3, 26, 3, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2492 {0.92, {{ 2, 28, 2, 0}, { 0, 27, 6, -1}, {-2, 25, 11, -2}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2493 {0.93, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2494 {0.94, {{ 2, 28, 2, 0}, { 0, 26, 6, 0}, {-2, 25, 10, -1}, {-3, 23, 15, -3}, {-3, 19, 19, -3}, }},
2495 {0.95, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2496 {0.96, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2497 {0.97, {{ 1, 30, 1, 0}, {-1, 28, 5, 0}, {-3, 26, 10, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2498 {0.98, {{ 1, 30, 1, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-3, 23, 14, -2}, {-3, 19, 19, -3}, }},
2499 {0.99, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }},
2500 {1.00, {{ 0, 32, 0, 0}, {-2, 29, 5, 0}, {-3, 27, 9, -1}, {-4, 24, 14, -2}, {-3, 19, 19, -3}, }}
2503 double DSR;
2505 unsigned ArrayElement;
2507 DSR = (double)(1<<0xc)/val_OV0_P1_H_INC;
2508 if (DSR<.25) DSR=.25;
2509 if (DSR>1) DSR=1;
2511 ArrayElement = (int)((DSR-0.25) * 100);
2512 besr.four_tap_coeff[0] = (ArrayOfSets[ArrayElement].CoefSet[0][0] & 0xf) |
2513 ((ArrayOfSets[ArrayElement].CoefSet[0][1] & 0x7f)<<8) |
2514 ((ArrayOfSets[ArrayElement].CoefSet[0][2] & 0x7f)<<16) |
2515 ((ArrayOfSets[ArrayElement].CoefSet[0][3] & 0xf)<<24);
2516 besr.four_tap_coeff[1] = (ArrayOfSets[ArrayElement].CoefSet[1][0] & 0xf) |
2517 ((ArrayOfSets[ArrayElement].CoefSet[1][1] & 0x7f)<<8) |
2518 ((ArrayOfSets[ArrayElement].CoefSet[1][2] & 0x7f)<<16) |
2519 ((ArrayOfSets[ArrayElement].CoefSet[1][3] & 0xf)<<24);
2520 besr.four_tap_coeff[2] = (ArrayOfSets[ArrayElement].CoefSet[2][0] & 0xf) |
2521 ((ArrayOfSets[ArrayElement].CoefSet[2][1] & 0x7f)<<8) |
2522 ((ArrayOfSets[ArrayElement].CoefSet[2][2] & 0x7f)<<16) |
2523 ((ArrayOfSets[ArrayElement].CoefSet[2][3] & 0xf)<<24);
2524 besr.four_tap_coeff[3] = (ArrayOfSets[ArrayElement].CoefSet[3][0] & 0xf) |
2525 ((ArrayOfSets[ArrayElement].CoefSet[3][1] & 0x7f)<<8) |
2526 ((ArrayOfSets[ArrayElement].CoefSet[3][2] & 0x7f)<<16) |
2527 ((ArrayOfSets[ArrayElement].CoefSet[3][3] & 0xf)<<24);
2528 besr.four_tap_coeff[4] = (ArrayOfSets[ArrayElement].CoefSet[4][0] & 0xf) |
2529 ((ArrayOfSets[ArrayElement].CoefSet[4][1] & 0x7f)<<8) |
2530 ((ArrayOfSets[ArrayElement].CoefSet[4][2] & 0x7f)<<16) |
2531 ((ArrayOfSets[ArrayElement].CoefSet[4][3] & 0xf)<<24);
2533 For more details, refer to Microsoft's draft of PC99.
2537 /* The minimal value of horizontal scale ratio when hard coded coefficients
2538 are suitable for the best quality. */
2539 /* FIXME: Should it be 0.9 for Rage128 ??? */
2540 static const double MinHScaleHard=0.75;
2542 static int radeon_vid_init_video( vidix_playback_t *config )
2544 double V_scale_ratio;
2545 uint32_t i,src_w,src_h,dest_w,dest_h,pitch,left,leftUV,top,h_inc;
2546 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;
2547 uint32_t val_OV0_P1_X_START,val_OV0_P2_X_START;
2548 uint32_t val_OV0_P1_MAX_LN_IN_PER_LN_OUT,val_OV0_P23_MAX_LN_IN_PER_LN_OUT;
2549 uint32_t CRT_V_INC;
2550 uint32_t BytesPerOctWord,LogMemWordsInBytes,MemWordsInBytes,LogTileWidthInMemWords;
2551 uint32_t TileWidthInMemWords,TileWidthInBytes,LogTileHeight,TileHeight;
2552 uint32_t PageSizeInBytes,OV0LB_Rows;
2553 uint32_t SourceWidthInMemWords,SourceUVWidthInMemWords;
2554 uint32_t SourceWidthInPixels,SourceUVWidthInPixels;
2555 uint32_t RightPixel,RightUVPixel,LeftPixel,LeftUVPixel;
2556 int is_400,is_410,is_420,best_pitch,mpitch;
2557 int horz_repl_factor,interlace_factor;
2558 int BytesPerPixel,BytesPerUVPixel,HorzUVSubSample,VertUVSubSample;
2559 int DisallowFourTapVertFiltering,DisallowFourTapUVVertFiltering;
2561 radeon_vid_stop_video();
2562 left = config->src.x << 16;
2563 top = config->src.y << 16;
2564 src_h = config->src.h;
2565 src_w = config->src.w;
2566 is_400 = is_410 = is_420 = 0;
2567 if(config->fourcc == IMGFMT_YV12 ||
2568 config->fourcc == IMGFMT_I420 ||
2569 config->fourcc == IMGFMT_IYUV) is_420 = 1;
2570 if(config->fourcc == IMGFMT_YVU9 ||
2571 config->fourcc == IMGFMT_IF09) is_410 = 1;
2572 if(config->fourcc == IMGFMT_Y800) is_400 = 1;
2573 best_pitch = radeon_query_pitch(config->fourcc,&config->src.pitch);
2574 mpitch = best_pitch-1;
2575 BytesPerOctWord = 16;
2576 LogMemWordsInBytes = 4;
2577 MemWordsInBytes = 1<<LogMemWordsInBytes;
2578 LogTileWidthInMemWords = 2;
2579 TileWidthInMemWords = 1<<LogTileWidthInMemWords;
2580 TileWidthInBytes = 1<<(LogTileWidthInMemWords+LogMemWordsInBytes);
2581 LogTileHeight = 4;
2582 TileHeight = 1<<LogTileHeight;
2583 PageSizeInBytes = 64*MemWordsInBytes;
2584 OV0LB_Rows = 96;
2585 h_inc = 1;
2586 switch(config->fourcc)
2588 /* 4:0:0*/
2589 case IMGFMT_Y800:
2590 /* 4:1:0*/
2591 case IMGFMT_YVU9:
2592 case IMGFMT_IF09:
2593 /* 4:2:0 */
2594 case IMGFMT_IYUV:
2595 case IMGFMT_YV12:
2596 case IMGFMT_I420: pitch = (src_w + mpitch) & ~mpitch;
2597 config->dest.pitch.y =
2598 config->dest.pitch.u =
2599 config->dest.pitch.v = best_pitch;
2600 break;
2601 /* RGB 4:4:4:4 */
2602 case IMGFMT_RGB32:
2603 case IMGFMT_BGR32: pitch = (src_w*4 + mpitch) & ~mpitch;
2604 config->dest.pitch.y =
2605 config->dest.pitch.u =
2606 config->dest.pitch.v = best_pitch;
2607 break;
2608 /* 4:2:2 */
2610 default: /* RGB15, RGB16, YVYU, UYVY, YUY2 */
2611 pitch = ((src_w*2) + mpitch) & ~mpitch;
2612 config->dest.pitch.y =
2613 config->dest.pitch.u =
2614 config->dest.pitch.v = best_pitch;
2615 break;
2617 besr.load_prg_start=0;
2618 besr.swap_uv=0;
2619 switch(config->fourcc)
2621 case IMGFMT_RGB15:
2622 besr.swap_uv=1;
2623 case IMGFMT_BGR15: besr.surf_id = SCALER_SOURCE_15BPP>>8;
2624 besr.load_prg_start = 1;
2625 break;
2626 case IMGFMT_RGB16:
2627 besr.swap_uv=1;
2628 case IMGFMT_BGR16: besr.surf_id = SCALER_SOURCE_16BPP>>8;
2629 besr.load_prg_start = 1;
2630 break;
2631 case IMGFMT_RGB32:
2632 besr.swap_uv=1;
2633 case IMGFMT_BGR32: besr.surf_id = SCALER_SOURCE_32BPP>>8;
2634 besr.load_prg_start = 1;
2635 break;
2636 /* 4:1:0*/
2637 case IMGFMT_IF09:
2638 case IMGFMT_YVU9: besr.surf_id = SCALER_SOURCE_YUV9>>8;
2639 break;
2640 /* 4:0:0*/
2641 case IMGFMT_Y800:
2642 /* 4:2:0 */
2643 case IMGFMT_IYUV:
2644 case IMGFMT_I420:
2645 case IMGFMT_YV12: besr.surf_id = SCALER_SOURCE_YUV12>>8;
2646 break;
2647 /* 4:2:2 */
2648 case IMGFMT_YVYU:
2649 case IMGFMT_UYVY: besr.surf_id = SCALER_SOURCE_YVYU422>>8;
2650 break;
2651 case IMGFMT_YUY2:
2652 default: besr.surf_id = SCALER_SOURCE_VYUY422>>8;
2653 break;
2655 switch (besr.surf_id)
2657 case 3:
2658 case 4:
2659 case 11:
2660 case 12: BytesPerPixel = 2;
2661 break;
2662 case 6: BytesPerPixel = 4;
2663 break;
2664 case 9:
2665 case 10:
2666 case 13:
2667 case 14: BytesPerPixel = 1;
2668 break;
2669 default: BytesPerPixel = 0;/*insert a debug statement here. */
2670 break;
2672 switch (besr.surf_id)
2674 case 3:
2675 case 4: BytesPerUVPixel = 0;
2676 break;/* In RGB modes, the BytesPerUVPixel is don't care */
2677 case 11:
2678 case 12: BytesPerUVPixel = 2;
2679 break;
2680 case 6: BytesPerUVPixel = 0;
2681 break; /* In RGB modes, the BytesPerUVPixel is don't care */
2682 case 9:
2683 case 10: BytesPerUVPixel = 1;
2684 break;
2685 case 13:
2686 case 14: BytesPerUVPixel = 2;
2687 break;
2688 default: BytesPerUVPixel = 0;/* insert a debug statement here. */
2689 break;
2692 switch (besr.surf_id)
2694 case 3:
2695 case 4:
2696 case 6: HorzUVSubSample = 1;
2697 break;
2698 case 9: HorzUVSubSample = 4;
2699 break;
2700 case 10:
2701 case 11:
2702 case 12:
2703 case 13:
2704 case 14: HorzUVSubSample = 2;
2705 break;
2706 default: HorzUVSubSample = 0;/* insert debug statement here. */
2707 break;
2709 switch (besr.surf_id)
2711 case 3:
2712 case 4:
2713 case 6:
2714 case 11:
2715 case 12: VertUVSubSample = 1;
2716 break;
2717 case 9: VertUVSubSample = 4;
2718 break;
2719 case 10:
2720 case 13:
2721 case 14: VertUVSubSample = 2;
2722 break;
2723 default: VertUVSubSample = 0;/* insert debug statment here. */
2724 break;
2726 DisallowFourTapVertFiltering = 0; /* Allow it by default */
2727 DisallowFourTapUVVertFiltering = 0; /* Allow it by default */
2728 LeftPixel = config->src.x;
2729 RightPixel = config->src.w-1;
2730 if(floor(config->src.x/HorzUVSubSample)<0) LeftUVPixel = 0;
2731 else LeftUVPixel = (int)floor(config->src.x/HorzUVSubSample);
2732 if(ceil((config->src.x+config->src.w)/HorzUVSubSample) > config->src.w/HorzUVSubSample)
2733 RightUVPixel = config->src.w/HorzUVSubSample - 1;
2734 else RightUVPixel = (int)ceil((config->src.x+config->src.w)/HorzUVSubSample) - 1;
2735 /* Top, Bottom and Right Crops can be out of range. The driver will program the hardware
2736 // to create a black border at the top and bottom. This is useful for DVD letterboxing. */
2737 SourceWidthInPixels = (int)(config->src.w + 1);
2738 SourceUVWidthInPixels = (int)(RightUVPixel - LeftUVPixel + 1);
2740 SourceWidthInMemWords = (int)(ceil(RightPixel*BytesPerPixel / MemWordsInBytes) -
2741 floor(LeftPixel*BytesPerPixel / MemWordsInBytes) + 1);
2742 /* SourceUVWidthInMemWords means Source_U_or_V_or_UV_WidthInMemWords depending on whether the UV is packed together of not. */
2743 SourceUVWidthInMemWords = (int)(ceil(RightUVPixel*BytesPerUVPixel /
2744 MemWordsInBytes) - floor(LeftUVPixel*BytesPerUVPixel /
2745 MemWordsInBytes) + 1);
2747 switch (besr.surf_id)
2749 case 9:
2750 case 10: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2752 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2754 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2756 DisallowFourTapVertFiltering = 1;
2759 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 1 > OV0LB_Rows-1)
2761 /*CYCACC_ASSERT(0, "Image U plane width spans more octwords than supported by hardware.") */
2763 else if ((SourceUVWidthInMemWords-1) * 4 + 1 > OV0LB_Rows-1)
2765 DisallowFourTapUVVertFiltering = 1;
2768 if ((ceil(SourceUVWidthInMemWords/2)-1) * 4 + 3 > OV0LB_Rows-1)
2770 /*CYCACC_ASSERT(0, "Image V plane width spans more octwords than supported by hardware.") */
2772 else if ((SourceUVWidthInMemWords-1) * 4 + 3 > OV0LB_Rows-1)
2774 DisallowFourTapUVVertFiltering = 1;
2776 break;
2777 case 13:
2778 case 14: if ((ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1)
2780 RADEON_ASSERT("ceil(SourceWidthInMemWords/2)-1) * 2 > OV0LB_Rows-1\n");
2782 else if ((SourceWidthInMemWords-1) * 2 > OV0LB_Rows-1)
2784 DisallowFourTapVertFiltering = 1;
2787 if ((ceil(SourceUVWidthInMemWords/2)-1) * 2 + 1 > OV0LB_Rows-1)
2789 /*CYCACC_ASSERT(0, "Image UV plane width spans more octwords than supported by hardware.") */
2791 else if ((SourceUVWidthInMemWords-1) * 2 + 1 > OV0LB_Rows-1)
2793 DisallowFourTapUVVertFiltering = 1;
2795 break;
2796 case 3:
2797 case 4:
2798 case 6:
2799 case 11:
2800 case 12: if ((ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1)
2802 RADEON_ASSERT("(ceil(SourceWidthInMemWords/2)-1) > OV0LB_Rows-1\n")
2804 else if ((SourceWidthInMemWords-1) > OV0LB_Rows-1)
2806 DisallowFourTapVertFiltering = 1;
2808 break;
2809 default: /* insert debug statement here. */
2810 break;
2812 dest_w = config->dest.w;
2813 dest_h = config->dest.h;
2814 if(radeon_is_dbl_scan()) dest_h *= 2;
2815 besr.dest_bpp = radeon_vid_get_dbpp();
2816 besr.fourcc = config->fourcc;
2817 if(radeon_is_interlace()) interlace_factor = 2;
2818 else interlace_factor = 1;
2819 /* TODO: must be checked in doublescan mode!!! */
2820 if((besr.chip_flags&R_INTEGRATED)==R_INTEGRATED)
2822 /* Force the overlay clock on for integrated chips */
2823 OUTPLL(VCLK_ECP_CNTL, (INPLL(VCLK_ECP_CNTL) | (1<<18)));
2825 horz_repl_factor = 1 << (uint32_t)((INPLL(VCLK_ECP_CNTL) & 0x300) >> 8);
2826 H_scale_ratio = (double)ceil(((double)dest_w+1)/horz_repl_factor)/src_w;
2827 V_scale_ratio = (double)(dest_h+1)/src_h;
2828 if(H_scale_ratio < 0.5 && V_scale_ratio < 0.5)
2830 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 3;
2831 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 2;
2833 else
2834 if(H_scale_ratio < 1 && V_scale_ratio < 1)
2836 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 2;
2837 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2839 else
2841 val_OV0_P1_MAX_LN_IN_PER_LN_OUT = 1;
2842 val_OV0_P23_MAX_LN_IN_PER_LN_OUT = 1;
2844 /* N.B.: Indeed it has 6.12 format but shifted on 8 to the left!!! */
2845 besr.v_inc = (uint16_t)((1./V_scale_ratio)*(1<<12)*interlace_factor+0.5);
2846 CRT_V_INC = besr.v_inc/interlace_factor;
2847 besr.v_inc <<= 8;
2849 int ThereIsTwoTapVerticalFiltering,DoNotUseMostRecentlyFetchedLine;
2850 int P1GroupSize = 0;
2851 int P23GroupSize;
2852 int P1StepSize = 0;
2853 int P23StepSize = 0;
2855 Calc_H_INC_STEP_BY(
2856 besr.surf_id,
2857 H_scale_ratio,
2858 DisallowFourTapVertFiltering,
2859 DisallowFourTapUVVertFiltering,
2860 &val_OV0_P1_H_INC,
2861 &val_OV0_P1_H_STEP_BY,
2862 &val_OV0_P23_H_INC,
2863 &val_OV0_P23_H_STEP_BY,
2864 &P1GroupSize,
2865 &P1StepSize,
2866 &P23StepSize);
2868 if(H_scale_ratio > MinHScaleHard)
2870 h_inc = (src_w << 12) / dest_w;
2871 besr.step_by = 0x0101;
2872 switch (besr.surf_id)
2874 case 3:
2875 case 4:
2876 case 6:
2877 besr.h_inc = (h_inc)|(h_inc<<16);
2878 break;
2879 case 9:
2880 besr.h_inc = h_inc | ((h_inc >> 2) << 16);
2881 break;
2882 default:
2883 besr.h_inc = h_inc | ((h_inc >> 1) << 16);
2884 break;
2888 P23GroupSize = 2; /* Current vaue for all modes */
2890 besr.horz_pick_nearest=0;
2891 DoNotUseMostRecentlyFetchedLine=0;
2892 ThereIsTwoTapVerticalFiltering = (val_OV0_P1_H_STEP_BY!=0) || (val_OV0_P23_H_STEP_BY!=0);
2893 if (ThereIsTwoTapVerticalFiltering && DoNotUseMostRecentlyFetchedLine)
2894 besr.vert_pick_nearest = 1;
2895 else
2896 besr.vert_pick_nearest = 0;
2898 ComputeXStartEnd(is_400,LeftPixel,LeftUVPixel,MemWordsInBytes,BytesPerPixel,
2899 SourceWidthInPixels,P1StepSize,BytesPerUVPixel,
2900 SourceUVWidthInPixels,P23StepSize,&val_OV0_P1_X_START,&val_OV0_P2_X_START);
2902 if(H_scale_ratio > MinHScaleHard)
2904 unsigned tmp;
2905 tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3);
2906 besr.p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
2907 ((tmp << 12) & 0xf0000000);
2909 tmp = (top & 0x0000ffff) + 0x00018000;
2910 besr.p1_v_accum_init = ((tmp << 4) & OV0_P1_V_ACCUM_INIT_MASK)
2911 |(OV0_P1_MAX_LN_IN_PER_LN_OUT & 1);
2912 tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2);
2913 besr.p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
2914 ((tmp << 12) & 0x70000000);
2916 tmp = ((top >> 1) & 0x0000ffff) + 0x00018000;
2917 besr.p23_v_accum_init = (is_420||is_410) ?
2918 ((tmp << 4) & OV0_P23_V_ACCUM_INIT_MASK)
2919 |(OV0_P23_MAX_LN_IN_PER_LN_OUT & 1) : 0;
2921 else
2922 ComputeAccumInit( val_OV0_P1_X_START,val_OV0_P2_X_START,
2923 val_OV0_P1_H_INC,val_OV0_P23_H_INC,
2924 val_OV0_P1_H_STEP_BY,val_OV0_P23_H_STEP_BY,
2925 CRT_V_INC,P1GroupSize,P23GroupSize,
2926 val_OV0_P1_MAX_LN_IN_PER_LN_OUT,
2927 val_OV0_P23_MAX_LN_IN_PER_LN_OUT);
2930 /* keep everything in 16.16 */
2931 besr.base_addr = INREG(DISPLAY_BASE_ADDR);
2932 config->offsets[0] = 0;
2933 for(i=1;i<besr.vid_nbufs;i++)
2934 config->offsets[i] = config->offsets[i-1]+config->frame_size;
2935 if(is_420 || is_410 || is_400)
2937 uint32_t d1line,d2line,d3line;
2938 d1line = top*pitch;
2939 if(is_420)
2941 d2line = src_h*pitch+(d1line>>2);
2942 d3line = d2line+((src_h*pitch)>>2);
2944 else
2945 if(is_410)
2947 d2line = src_h*pitch+(d1line>>4);
2948 d3line = d2line+((src_h*pitch)>>4);
2950 else
2952 d2line = 0;
2953 d3line = 0;
2955 d1line += (left >> 16) & ~15;
2956 if(is_420)
2958 d2line += (left >> 17) & ~15;
2959 d3line += (left >> 17) & ~15;
2961 else /* is_410 */
2963 d2line += (left >> 18) & ~15;
2964 d3line += (left >> 18) & ~15;
2966 config->offset.y = d1line & VIF_BUF0_BASE_ADRS_MASK;
2967 if(is_400)
2969 config->offset.v = 0;
2970 config->offset.u = 0;
2972 else
2974 config->offset.v = d2line & VIF_BUF1_BASE_ADRS_MASK;
2975 config->offset.u = d3line & VIF_BUF2_BASE_ADRS_MASK;
2977 for(i=0;i<besr.vid_nbufs;i++)
2979 besr.vid_buf_base_adrs_y[i]=((radeon_overlay_off+config->offsets[i]+config->offset.y)&VIF_BUF0_BASE_ADRS_MASK);
2980 if(is_400)
2982 besr.vid_buf_base_adrs_v[i]=0;
2983 besr.vid_buf_base_adrs_u[i]=0;
2985 else
2987 if (besr.fourcc == IMGFMT_I420 || besr.fourcc == IMGFMT_IYUV)
2989 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;
2990 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;
2992 else
2994 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;
2995 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;
2999 config->offset.y = ((besr.vid_buf_base_adrs_y[0])&VIF_BUF0_BASE_ADRS_MASK) - radeon_overlay_off;
3000 if(is_400)
3002 config->offset.v = 0;
3003 config->offset.u = 0;
3005 else
3007 config->offset.v = ((besr.vid_buf_base_adrs_v[0])&VIF_BUF1_BASE_ADRS_MASK) - radeon_overlay_off;
3008 config->offset.u = ((besr.vid_buf_base_adrs_u[0])&VIF_BUF2_BASE_ADRS_MASK) - radeon_overlay_off;
3011 else
3013 config->offset.y = config->offset.u = config->offset.v = ((left & ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK;
3014 for(i=0;i<besr.vid_nbufs;i++)
3016 besr.vid_buf_base_adrs_y[i] =
3017 besr.vid_buf_base_adrs_u[i] =
3018 besr.vid_buf_base_adrs_v[i] = radeon_overlay_off + config->offsets[i] + config->offset.y;
3021 leftUV = (left >> (is_410?18:17)) & 15;
3022 left = (left >> 16) & 15;
3023 besr.y_x_start = (config->dest.x+X_ADJUST) | (config->dest.y << 16);
3024 besr.y_x_end = (config->dest.x + dest_w+X_ADJUST) | ((config->dest.y + dest_h) << 16);
3025 ComputeBorders(config,VertUVSubSample);
3026 besr.vid_buf_pitch0_value = pitch;
3027 besr.vid_buf_pitch1_value = is_410 ? pitch>>2 : is_420 ? pitch>>1 : pitch;
3028 /* ********************************************************* */
3029 /* ** Calculate programmable coefficients as needed */
3030 /* ********************************************************* */
3032 /* ToDo_Active: When in pick nearest mode, we need to program the filter tap zero */
3033 /* coefficients to 0, 32, 0, 0. Or use hard coded coefficients. */
3034 if(H_scale_ratio > MinHScaleHard) besr.filter_cntl |= FILTER_HARDCODED_COEF;
3035 else
3037 FilterSetup (val_OV0_P1_H_INC);
3038 /* ToDo_Active: Must add the smarts into the driver to decide what type of filtering it */
3039 /* would like to do. For now, we let the test application decide. */
3040 besr.filter_cntl = FILTER_PROGRAMMABLE_COEF;
3041 if(DisallowFourTapVertFiltering)
3042 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_Y;
3043 if(DisallowFourTapUVVertFiltering)
3044 besr.filter_cntl |= FILTER_HARD_SCALE_VERT_UV;
3046 return 0;
3049 static void radeon_compute_framesize(vidix_playback_t *info)
3051 unsigned pitch,awidth,dbpp;
3052 pitch = radeon_query_pitch(info->fourcc,&info->src.pitch);
3053 dbpp = radeon_vid_get_dbpp();
3054 switch(info->fourcc)
3056 case IMGFMT_Y800:
3057 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3058 info->frame_size = awidth*info->src.h;
3059 break;
3060 case IMGFMT_YVU9:
3061 case IMGFMT_IF09:
3062 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3063 info->frame_size = awidth*(info->src.h+info->src.h/8);
3064 break;
3065 case IMGFMT_I420:
3066 case IMGFMT_YV12:
3067 case IMGFMT_IYUV:
3068 awidth = (info->src.w + (pitch-1)) & ~(pitch-1);
3069 info->frame_size = awidth*(info->src.h+info->src.h/2);
3070 break;
3071 case IMGFMT_RGB32:
3072 case IMGFMT_BGR32:
3073 awidth = (info->src.w*4 + (pitch-1)) & ~(pitch-1);
3074 info->frame_size = awidth*info->src.h;
3075 break;
3076 /* YUY2 YVYU, RGB15, RGB16 */
3077 default:
3078 awidth = (info->src.w*2 + (pitch-1)) & ~(pitch-1);
3079 info->frame_size = awidth*info->src.h;
3080 break;
3082 info->frame_size = (info->frame_size+4095)&~4095;
3085 static int radeon_config_playback(vidix_playback_t *info)
3087 unsigned rgb_size,nfr;
3088 uint32_t radeon_video_size;
3089 if(!is_supported_fourcc(info->fourcc)) return ENOSYS;
3090 if(info->num_frames>VID_PLAY_MAXFRAMES) info->num_frames=VID_PLAY_MAXFRAMES;
3091 if(info->num_frames==1) besr.double_buff=0;
3092 else besr.double_buff=1;
3093 radeon_compute_framesize(info);
3095 rgb_size = radeon_get_xres()*radeon_get_yres()*((radeon_vid_get_dbpp()+7)/8);
3096 nfr = info->num_frames;
3097 radeon_video_size = radeon_ram_size;
3098 for(;nfr>0; nfr--)
3100 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3101 #if !defined (RAGE128) && defined(CONFIG_X11)
3102 radeon_overlay_off -= firegl_shift;
3103 #endif
3104 radeon_overlay_off &= 0xffff0000;
3105 if(radeon_overlay_off >= (int)rgb_size ) break;
3107 if(nfr <= 3)
3109 nfr = info->num_frames;
3110 for(;nfr>0; nfr--)
3112 radeon_overlay_off = radeon_video_size - info->frame_size*nfr;
3113 #if !defined (RAGE128) && defined(CONFIG_X11)
3114 radeon_overlay_off -= firegl_shift;
3115 #endif
3116 radeon_overlay_off &= 0xffff0000;
3117 if(radeon_overlay_off > 0) break;
3120 if(nfr <= 0) return EINVAL;
3121 info->num_frames = nfr;
3122 besr.vid_nbufs = info->num_frames;
3123 info->dga_addr = (char *)radeon_mem_base + radeon_overlay_off;
3124 radeon_vid_init_video(info);
3125 return 0;
3128 static int radeon_playback_on(void)
3130 #ifdef RAGE128
3131 unsigned dw,dh;
3132 #endif
3133 radeon_vid_display_video();
3134 #ifdef RAGE128
3135 dh = (besr.y_x_end >> 16) - (besr.y_x_start >> 16);
3136 dw = (besr.y_x_end & 0xFFFF) - (besr.y_x_start & 0xFFFF);
3137 if(dw == radeon_get_xres() || dh == radeon_get_yres()) radeon_vid_exclusive();
3138 else radeon_vid_non_exclusive();
3139 #endif
3140 return 0;
3143 static int radeon_playback_off(void)
3145 radeon_vid_stop_video();
3146 return 0;
3149 static int radeon_frame_select(unsigned frame)
3151 uint32_t off[6];
3152 int prev_frame= (frame-1+besr.vid_nbufs) % besr.vid_nbufs;
3154 buf3-5 always should point onto second buffer for better
3155 deinterlacing and TV-in
3157 if(!besr.double_buff) return 0;
3158 if(frame > besr.vid_nbufs) frame = besr.vid_nbufs-1;
3159 if(prev_frame > (int)besr.vid_nbufs) prev_frame = besr.vid_nbufs-1;
3160 off[0] = besr.vid_buf_base_adrs_y[frame];
3161 off[1] = besr.vid_buf_base_adrs_v[frame];
3162 off[2] = besr.vid_buf_base_adrs_u[frame];
3163 off[3] = besr.vid_buf_base_adrs_y[prev_frame];
3164 off[4] = besr.vid_buf_base_adrs_v[prev_frame];
3165 off[5] = besr.vid_buf_base_adrs_u[prev_frame];
3166 radeon_fifo_wait(8);
3167 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3168 radeon_engine_idle();
3169 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3170 OUTREG(OV0_VID_BUF0_BASE_ADRS, off[0]);
3171 OUTREG(OV0_VID_BUF1_BASE_ADRS, off[1]);
3172 OUTREG(OV0_VID_BUF2_BASE_ADRS, off[2]);
3173 OUTREG(OV0_VID_BUF3_BASE_ADRS, off[3]);
3174 OUTREG(OV0_VID_BUF4_BASE_ADRS, off[4]);
3175 OUTREG(OV0_VID_BUF5_BASE_ADRS, off[5]);
3176 OUTREG(OV0_REG_LOAD_CNTL, 0);
3177 if(besr.vid_nbufs == 2) radeon_wait_vsync();
3178 if(verbosity > VERBOSE_LEVEL) radeon_vid_dump_regs();
3179 return 0;
3182 static vidix_video_eq_t equal =
3184 VEQ_CAP_BRIGHTNESS | VEQ_CAP_SATURATION
3185 #ifndef RAGE128
3186 | VEQ_CAP_CONTRAST | VEQ_CAP_HUE | VEQ_CAP_RGB_INTENSITY
3187 #endif
3189 0, 0, 0, 0, 0, 0, 0, 0 };
3191 static int radeon_get_eq(vidix_video_eq_t * eq)
3193 memcpy(eq,&equal,sizeof(vidix_video_eq_t));
3194 return 0;
3197 #ifndef RAGE128
3198 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
3199 #define RTFBrightness(a) (((a)*1.0)/2000.0)
3200 #define RTFIntensity(a) (((a)*1.0)/2000.0)
3201 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
3202 #define RTFHue(a) (((a)*3.1416)/1000.0)
3203 #define RTFCheckParam(a) {if((a)<-1000) (a)=-1000; if((a)>1000) (a)=1000;}
3204 #endif
3206 static int radeon_set_eq(const vidix_video_eq_t * eq)
3208 #ifdef RAGE128
3209 int br,sat;
3210 #else
3211 int itu_space;
3212 #endif
3213 if(eq->cap & VEQ_CAP_BRIGHTNESS) equal.brightness = eq->brightness;
3214 if(eq->cap & VEQ_CAP_CONTRAST) equal.contrast = eq->contrast;
3215 if(eq->cap & VEQ_CAP_SATURATION) equal.saturation = eq->saturation;
3216 if(eq->cap & VEQ_CAP_HUE) equal.hue = eq->hue;
3217 if(eq->cap & VEQ_CAP_RGB_INTENSITY)
3219 equal.red_intensity = eq->red_intensity;
3220 equal.green_intensity = eq->green_intensity;
3221 equal.blue_intensity = eq->blue_intensity;
3223 equal.flags = eq->flags;
3224 #ifdef RAGE128
3225 br = equal.brightness * 64 / 1000;
3226 if(br < -64) br = -64; if(br > 63) br = 63;
3227 sat = (equal.saturation*31 + 31000) / 2000;
3228 if(sat < 0) sat = 0; if(sat > 31) sat = 31;
3229 OUTREG(OV0_COLOUR_CNTL, (br & 0x7f) | (sat << 8) | (sat << 16));
3230 #else
3231 itu_space = equal.flags == VEQ_FLG_ITU_R_BT_709 ? 1 : 0;
3232 RTFCheckParam(equal.brightness);
3233 RTFCheckParam(equal.saturation);
3234 RTFCheckParam(equal.contrast);
3235 RTFCheckParam(equal.hue);
3236 RTFCheckParam(equal.red_intensity);
3237 RTFCheckParam(equal.green_intensity);
3238 RTFCheckParam(equal.blue_intensity);
3239 radeon_set_transform(RTFBrightness(equal.brightness),
3240 RTFContrast(equal.contrast),
3241 RTFSaturation(equal.saturation),
3242 RTFHue(equal.hue),
3243 RTFIntensity(equal.red_intensity),
3244 RTFIntensity(equal.green_intensity),
3245 RTFIntensity(equal.blue_intensity),
3246 itu_space);
3247 #endif
3248 return 0;
3251 static int radeon_playback_set_deint(const vidix_deinterlace_t * info)
3253 unsigned sflg;
3254 switch(info->flags)
3256 default:
3257 case CFG_NON_INTERLACED:
3258 besr.deinterlace_on = 0;
3259 break;
3260 case CFG_EVEN_ODD_INTERLACING:
3261 case CFG_INTERLACED:
3262 besr.deinterlace_on = 1;
3263 besr.deinterlace_pattern = 0x900AAAAA;
3264 break;
3265 case CFG_ODD_EVEN_INTERLACING:
3266 besr.deinterlace_on = 1;
3267 besr.deinterlace_pattern = 0x00055555;
3268 break;
3269 case CFG_UNIQUE_INTERLACING:
3270 besr.deinterlace_on = 1;
3271 besr.deinterlace_pattern = info->deinterlace_pattern;
3272 break;
3274 OUTREG(OV0_REG_LOAD_CNTL, REG_LD_CTL_LOCK);
3275 radeon_engine_idle();
3276 while(!(INREG(OV0_REG_LOAD_CNTL)&REG_LD_CTL_LOCK_READBACK));
3277 radeon_fifo_wait(15);
3278 sflg = INREG(OV0_SCALE_CNTL);
3279 if(besr.deinterlace_on)
3281 OUTREG(OV0_SCALE_CNTL,sflg | SCALER_ADAPTIVE_DEINT);
3282 OUTREG(OV0_DEINTERLACE_PATTERN,besr.deinterlace_pattern);
3284 else OUTREG(OV0_SCALE_CNTL,sflg & (~SCALER_ADAPTIVE_DEINT));
3285 OUTREG(OV0_REG_LOAD_CNTL, 0);
3286 return 0;
3289 static int radeon_playback_get_deint(vidix_deinterlace_t * info)
3291 if(!besr.deinterlace_on) info->flags = CFG_NON_INTERLACED;
3292 else
3294 info->flags = CFG_UNIQUE_INTERLACING;
3295 info->deinterlace_pattern = besr.deinterlace_pattern;
3297 return 0;
3301 /* Graphic keys */
3302 static vidix_grkey_t radeon_grkey;
3304 static int set_gr_key( void )
3306 int result = 0;
3308 besr.merge_cntl = 0xff000000 | /* overlay alpha */
3309 0x00ff0000; /* graphic alpha */
3310 if(radeon_grkey.ckey.op == CKEY_TRUE)
3312 int dbpp=radeon_vid_get_dbpp();
3313 besr.ckey_on=1;
3315 switch(dbpp)
3317 case 15:
3318 #ifndef RAGE128
3319 if((besr.chip_flags&R_100)!=R_100)
3320 besr.graphics_key_clr=
3321 ((radeon_grkey.ckey.blue &0xF8))
3322 | ((radeon_grkey.ckey.green&0xF8)<<8)
3323 | ((radeon_grkey.ckey.red &0xF8)<<16);
3324 else
3325 #endif
3326 besr.graphics_key_clr=
3327 ((radeon_grkey.ckey.blue &0xF8)>>3)
3328 | ((radeon_grkey.ckey.green&0xF8)<<2)
3329 | ((radeon_grkey.ckey.red &0xF8)<<7);
3330 break;
3331 case 16:
3332 #ifndef RAGE128
3333 /* This test may be too general/specific */
3334 if((besr.chip_flags&R_100)!=R_100)
3335 besr.graphics_key_clr=
3336 ((radeon_grkey.ckey.blue &0xF8))
3337 | ((radeon_grkey.ckey.green&0xFC)<<8)
3338 | ((radeon_grkey.ckey.red &0xF8)<<16);
3339 else
3340 #endif
3341 besr.graphics_key_clr=
3342 ((radeon_grkey.ckey.blue &0xF8)>>3)
3343 | ((radeon_grkey.ckey.green&0xFC)<<3)
3344 | ((radeon_grkey.ckey.red &0xF8)<<8);
3345 break;
3346 case 24:
3347 case 32:
3348 besr.graphics_key_clr=
3349 ((radeon_grkey.ckey.blue &0xFF))
3350 | ((radeon_grkey.ckey.green&0xFF)<<8)
3351 | ((radeon_grkey.ckey.red &0xFF)<<16);
3352 break;
3353 default:
3354 besr.ckey_on=0;
3355 besr.graphics_key_msk=0;
3356 besr.graphics_key_clr=0;
3358 #ifdef RAGE128
3359 besr.graphics_key_msk=(1<<dbpp)-1;
3360 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_NE|CMP_MIX_AND;
3361 #else
3362 besr.graphics_key_msk=besr.graphics_key_clr;
3363 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|CMP_MIX_AND|GRAPHIC_KEY_FN_EQ;
3364 #endif
3366 else if(radeon_grkey.ckey.op == CKEY_ALPHA)
3368 int dbpp=radeon_vid_get_dbpp();
3369 besr.ckey_on=1;
3371 switch(dbpp)
3373 case 32:
3374 besr.ckey_on=1;
3375 besr.graphics_key_msk=0;
3376 besr.graphics_key_clr=0;
3377 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3378 besr.merge_cntl |= 0x00000001; /* DISP_ALPHA_MODE_PER_PIXEL */
3379 break;
3380 default:
3381 besr.ckey_on=0;
3382 besr.graphics_key_msk=0;
3383 besr.graphics_key_clr=0;
3384 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3385 result = 1;
3388 else
3390 besr.ckey_on=0;
3391 besr.graphics_key_msk=0;
3392 besr.graphics_key_clr=0;
3393 besr.ckey_cntl = VIDEO_KEY_FN_TRUE|GRAPHIC_KEY_FN_TRUE|CMP_MIX_AND;
3394 besr.merge_cntl |= 0x00000100; /* DISP_RGB_OFFSET_EN */
3396 radeon_fifo_wait(3);
3397 OUTREG(OV0_GRAPHICS_KEY_MSK, besr.graphics_key_msk);
3398 OUTREG(OV0_GRAPHICS_KEY_CLR, besr.graphics_key_clr);
3399 OUTREG(OV0_KEY_CNTL,besr.ckey_cntl);
3400 OUTREG(DISP_MERGE_CNTL, besr.merge_cntl);
3401 return result;
3404 static int radeon_get_gkey(vidix_grkey_t *grkey)
3406 memcpy(grkey, &radeon_grkey, sizeof(vidix_grkey_t));
3407 return 0;
3410 static int radeon_set_gkey(const vidix_grkey_t *grkey)
3412 memcpy(&radeon_grkey, grkey, sizeof(vidix_grkey_t));
3413 return set_gr_key();
3416 #ifdef RAGE128
3417 VDXDriver rage128_drv = {
3418 "rage128",
3419 #else
3420 VDXDriver radeon_drv = {
3421 "radeon",
3422 #endif
3423 NULL,
3425 .probe = radeon_probe,
3426 .get_caps = radeon_get_caps,
3427 .query_fourcc = radeon_query_fourcc,
3428 .init = radeon_init,
3429 .destroy = radeon_destroy,
3430 .config_playback = radeon_config_playback,
3431 .playback_on = radeon_playback_on,
3432 .playback_off = radeon_playback_off,
3433 .frame_sel = radeon_frame_select,
3434 .get_eq = radeon_get_eq,
3435 .set_eq = radeon_set_eq,
3436 .get_deint = radeon_playback_get_deint,
3437 .set_deint = radeon_playback_set_deint,
3438 .get_gkey = radeon_get_gkey,
3439 .set_gkey = radeon_set_gkey,