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