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)&REG_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)&REG_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)&REG_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