2 * BES YUV video overlay driver for Radeon/Rage128Pro/Rage128 cards
4 * Copyright (C) 2001 Nick Kurshev
6 * This file is partly based on mga_vid and sis_vid from MPlayer.
7 * Code from CVS of GATOS project and X11 trees was also used.
9 * SPECIAL THANKS TO: Hans-Peter Raschke for active testing and hacking
10 * Rage128(pro) stuff of this driver.
12 * This file is part of MPlayer.
14 * MPlayer is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * MPlayer is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License along
25 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
26 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #define RADEON_VID_VERSION "1.2.1"
32 It's entirely possible this major conflicts with something else
33 mknod /dev/radeon_vid c 178 0
35 mknod /dev/rage128_vid c 178 0
36 for Rage128/Rage128Pro chips (although it doesn't matter)
37 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38 TESTED and WORKING formats: YUY2, UYVY, IYUV, I420, YV12
39 -----------------------------------------------------------
41 Highest priority: fbvid.h compatibility
42 High priority: Fixing BUGS
43 Middle priority: RGB/BGR 2-32, YVU9, IF09 support
44 Low priority: CLPL, IYU1, IYU2, UYNV, CYUV, YUNV, YVYU, Y41P, Y211, Y41T,
46 Y42T, V422, V655, CLJR, YUVP, UYVP, Mpeg PES (mpeg-1,2) support
47 ...........................................................
49 Color and video keys don't work
52 #include <linux/config.h>
53 #include <linux/version.h>
54 #include <linux/module.h>
55 #include <linux/types.h>
56 #include <linux/kernel.h>
57 #include <linux/sched.h>
59 #include <linux/string.h>
60 #include <linux/errno.h>
61 #include <linux/slab.h>
62 #include <linux/pci.h>
63 #include <linux/ioport.h>
64 #include <linux/init.h>
65 #include <linux/byteorder/swab.h>
67 #include "radeon_vid.h"
74 #include <asm/uaccess.h>
75 #include <asm/system.h>
81 #define RADEON_VID_MAJOR 178
84 MODULE_AUTHOR("Nick Kurshev <nickols_k@mail.ru>");
86 MODULE_DESCRIPTION("Accelerated YUV BES driver for Rage128. Version: "RADEON_VID_VERSION
);
88 MODULE_DESCRIPTION("Accelerated YUV BES driver for Radeons. Version: "RADEON_VID_VERSION
);
91 MODULE_LICENSE("GPL");
94 MODULE_PARM(mtrr
, "i");
95 MODULE_PARM_DESC(mtrr
, "Tune MTRR (touch=1(default))");
96 static int mtrr __initdata
= 1;
97 static struct { int vram
; int vram_valid
; } smtrr
;
99 MODULE_PARM(swap_fourcc
, "i");
100 MODULE_PARM_DESC(swap_fourcc
, "Swap fourcc (don't swap=0(default))");
101 static int swap_fourcc __initdata
= 0;
104 #define RVID_MSG "rage128_vid: "
107 #define RVID_MSG "radeon_vid: "
116 #define RTRACE printk
118 #define RTRACE(...) ((void)0)
122 #define min(a,b) (a < b ? a : b)
126 #if defined(__i386__)
127 /* Ugly but only way */
129 static inline double FastSin(double x
)
132 __asm__
volatile("fsin":"=t"(res
):"0"(x
));
136 #define sin(x) FastSin(x)
138 static inline double FastCos(double x
)
141 __asm__
volatile("fcos":"=t"(res
):"0"(x
));
145 #define cos(x) FastCos(x)
147 #include "generic_math.h"
151 #if !defined( RAGE128 ) && !defined( AVOID_FPU )
155 typedef struct bes_registers_s
157 /* base address of yuv framebuffer */
161 /* YUV BES registers */
162 uint32_t reg_load_cntl
;
168 uint32_t p1_blank_lines_at_top
;
169 uint32_t p23_blank_lines_at_top
;
170 uint32_t vid_buf_pitch0_value
;
171 uint32_t vid_buf_pitch1_value
;
172 uint32_t p1_x_start_end
;
173 uint32_t p2_x_start_end
;
174 uint32_t p3_x_start_end
;
176 uint32_t vid_buf0_base_adrs
;
177 /* These ones are for auto flip: maybe in the future */
178 uint32_t vid_buf1_base_adrs
;
179 uint32_t vid_buf2_base_adrs
;
180 uint32_t vid_buf3_base_adrs
;
181 uint32_t vid_buf4_base_adrs
;
182 uint32_t vid_buf5_base_adrs
;
184 uint32_t p1_v_accum_init
;
185 uint32_t p1_h_accum_init
;
186 uint32_t p23_v_accum_init
;
187 uint32_t p23_h_accum_init
;
189 uint32_t exclusive_horz
;
190 uint32_t auto_flip_cntl
;
191 uint32_t filter_cntl
;
194 /* Configurable stuff */
201 uint32_t graphics_key_clr
;
202 uint32_t graphics_key_msk
;
205 uint32_t deinterlace_pattern
;
209 typedef struct video_registers_s
218 static bes_registers_t besr
;
223 #define DECLARE_VREG(name) { #name, name, 0 }
225 #define DECLARE_VREG(name) { name, 0 }
228 static video_registers_t vregs
[] =
230 DECLARE_VREG(VIDEOMUX_CNTL
),
231 DECLARE_VREG(VIPPAD_MASK
),
232 DECLARE_VREG(VIPPAD1_A
),
233 DECLARE_VREG(VIPPAD1_EN
),
234 DECLARE_VREG(VIPPAD1_Y
),
235 DECLARE_VREG(OV0_Y_X_START
),
236 DECLARE_VREG(OV0_Y_X_END
),
237 DECLARE_VREG(OV0_PIPELINE_CNTL
),
238 DECLARE_VREG(OV0_EXCLUSIVE_HORZ
),
239 DECLARE_VREG(OV0_EXCLUSIVE_VERT
),
240 DECLARE_VREG(OV0_REG_LOAD_CNTL
),
241 DECLARE_VREG(OV0_SCALE_CNTL
),
242 DECLARE_VREG(OV0_V_INC
),
243 DECLARE_VREG(OV0_P1_V_ACCUM_INIT
),
244 DECLARE_VREG(OV0_P23_V_ACCUM_INIT
),
245 DECLARE_VREG(OV0_P1_BLANK_LINES_AT_TOP
),
246 DECLARE_VREG(OV0_P23_BLANK_LINES_AT_TOP
),
248 DECLARE_VREG(OV0_BASE_ADDR
),
250 DECLARE_VREG(OV0_VID_BUF0_BASE_ADRS
),
251 DECLARE_VREG(OV0_VID_BUF1_BASE_ADRS
),
252 DECLARE_VREG(OV0_VID_BUF2_BASE_ADRS
),
253 DECLARE_VREG(OV0_VID_BUF3_BASE_ADRS
),
254 DECLARE_VREG(OV0_VID_BUF4_BASE_ADRS
),
255 DECLARE_VREG(OV0_VID_BUF5_BASE_ADRS
),
256 DECLARE_VREG(OV0_VID_BUF_PITCH0_VALUE
),
257 DECLARE_VREG(OV0_VID_BUF_PITCH1_VALUE
),
258 DECLARE_VREG(OV0_AUTO_FLIP_CNTL
),
259 DECLARE_VREG(OV0_DEINTERLACE_PATTERN
),
260 DECLARE_VREG(OV0_SUBMIT_HISTORY
),
261 DECLARE_VREG(OV0_H_INC
),
262 DECLARE_VREG(OV0_STEP_BY
),
263 DECLARE_VREG(OV0_P1_H_ACCUM_INIT
),
264 DECLARE_VREG(OV0_P23_H_ACCUM_INIT
),
265 DECLARE_VREG(OV0_P1_X_START_END
),
266 DECLARE_VREG(OV0_P2_X_START_END
),
267 DECLARE_VREG(OV0_P3_X_START_END
),
268 DECLARE_VREG(OV0_FILTER_CNTL
),
269 DECLARE_VREG(OV0_FOUR_TAP_COEF_0
),
270 DECLARE_VREG(OV0_FOUR_TAP_COEF_1
),
271 DECLARE_VREG(OV0_FOUR_TAP_COEF_2
),
272 DECLARE_VREG(OV0_FOUR_TAP_COEF_3
),
273 DECLARE_VREG(OV0_FOUR_TAP_COEF_4
),
274 DECLARE_VREG(OV0_FLAG_CNTL
),
276 DECLARE_VREG(OV0_COLOUR_CNTL
),
278 DECLARE_VREG(OV0_SLICE_CNTL
),
280 DECLARE_VREG(OV0_VID_KEY_CLR
),
281 DECLARE_VREG(OV0_VID_KEY_MSK
),
282 DECLARE_VREG(OV0_GRAPHICS_KEY_CLR
),
283 DECLARE_VREG(OV0_GRAPHICS_KEY_MSK
),
284 DECLARE_VREG(OV0_KEY_CNTL
),
285 DECLARE_VREG(OV0_TEST
),
286 DECLARE_VREG(OV0_LIN_TRANS_A
),
287 DECLARE_VREG(OV0_LIN_TRANS_B
),
288 DECLARE_VREG(OV0_LIN_TRANS_C
),
289 DECLARE_VREG(OV0_LIN_TRANS_D
),
290 DECLARE_VREG(OV0_LIN_TRANS_E
),
291 DECLARE_VREG(OV0_LIN_TRANS_F
),
292 DECLARE_VREG(OV0_GAMMA_0_F
),
293 DECLARE_VREG(OV0_GAMMA_10_1F
),
294 DECLARE_VREG(OV0_GAMMA_20_3F
),
295 DECLARE_VREG(OV0_GAMMA_40_7F
),
296 DECLARE_VREG(OV0_GAMMA_380_3BF
),
297 DECLARE_VREG(OV0_GAMMA_3C0_3FF
),
298 DECLARE_VREG(SUBPIC_CNTL
),
299 DECLARE_VREG(SUBPIC_DEFCOLCON
),
300 DECLARE_VREG(SUBPIC_Y_X_START
),
301 DECLARE_VREG(SUBPIC_Y_X_END
),
302 DECLARE_VREG(SUBPIC_V_INC
),
303 DECLARE_VREG(SUBPIC_H_INC
),
304 DECLARE_VREG(SUBPIC_BUF0_OFFSET
),
305 DECLARE_VREG(SUBPIC_BUF1_OFFSET
),
306 DECLARE_VREG(SUBPIC_LC0_OFFSET
),
307 DECLARE_VREG(SUBPIC_LC1_OFFSET
),
308 DECLARE_VREG(SUBPIC_PITCH
),
309 DECLARE_VREG(SUBPIC_BTN_HLI_COLCON
),
310 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_START
),
311 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_END
),
312 DECLARE_VREG(SUBPIC_PALETTE_INDEX
),
313 DECLARE_VREG(SUBPIC_PALETTE_DATA
),
314 DECLARE_VREG(SUBPIC_H_ACCUM_INIT
),
315 DECLARE_VREG(SUBPIC_V_ACCUM_INIT
),
316 DECLARE_VREG(IDCT_RUNS
),
317 DECLARE_VREG(IDCT_LEVELS
),
318 DECLARE_VREG(IDCT_AUTH_CONTROL
),
319 DECLARE_VREG(IDCT_AUTH
),
320 DECLARE_VREG(IDCT_CONTROL
)
323 static uint32_t radeon_vid_in_use
= 0;
325 static uint8_t *radeon_mmio_base
= 0;
326 static uint32_t radeon_mem_base
= 0;
327 static int32_t radeon_overlay_off
= 0;
328 static uint32_t radeon_ram_size
= 0;
329 #define PARAM_BUFF_SIZE 4096
330 static uint8_t *radeon_param_buff
= NULL
;
331 static uint32_t radeon_param_buff_size
=0;
332 static uint32_t radeon_param_buff_len
=0; /* real length of buffer */
333 static mga_vid_config_t radeon_config
;
335 static char *fourcc_format_name(int format
)
339 case IMGFMT_RGB8
: return "RGB 8-bit";
340 case IMGFMT_RGB15
: return "RGB 15-bit";
341 case IMGFMT_RGB16
: return "RGB 16-bit";
342 case IMGFMT_RGB24
: return "RGB 24-bit";
343 case IMGFMT_RGB32
: return "RGB 32-bit";
344 case IMGFMT_BGR8
: return "BGR 8-bit";
345 case IMGFMT_BGR15
: return "BGR 15-bit";
346 case IMGFMT_BGR16
: return "BGR 16-bit";
347 case IMGFMT_BGR24
: return "BGR 24-bit";
348 case IMGFMT_BGR32
: return "BGR 32-bit";
349 case IMGFMT_YVU9
: return "Planar YVU9";
350 case IMGFMT_IF09
: return "Planar IF09";
351 case IMGFMT_YV12
: return "Planar YV12";
352 case IMGFMT_I420
: return "Planar I420";
353 case IMGFMT_IYUV
: return "Planar IYUV";
354 case IMGFMT_CLPL
: return "Planar CLPL";
355 case IMGFMT_Y800
: return "Planar Y800";
356 case IMGFMT_Y8
: return "Planar Y8";
357 case IMGFMT_IUYV
: return "Packed IUYV";
358 case IMGFMT_IY41
: return "Packed IY41";
359 case IMGFMT_IYU1
: return "Packed IYU1";
360 case IMGFMT_IYU2
: return "Packed IYU2";
361 case IMGFMT_UYNV
: return "Packed UYNV";
362 case IMGFMT_cyuv
: return "Packed CYUV";
363 case IMGFMT_Y422
: return "Packed Y422";
364 case IMGFMT_YUY2
: return "Packed YUY2";
365 case IMGFMT_YUNV
: return "Packed YUNV";
366 case IMGFMT_UYVY
: return "Packed UYVY";
367 // case IMGFMT_YVYU: return "Packed YVYU";
368 case IMGFMT_Y41P
: return "Packed Y41P";
369 case IMGFMT_Y211
: return "Packed Y211";
370 case IMGFMT_Y41T
: return "Packed Y41T";
371 case IMGFMT_Y42T
: return "Packed Y42T";
372 case IMGFMT_V422
: return "Packed V422";
373 case IMGFMT_V655
: return "Packed V655";
374 case IMGFMT_CLJR
: return "Packed CLJR";
375 case IMGFMT_YUVP
: return "Packed YUVP";
376 case IMGFMT_UYVP
: return "Packed UYVP";
377 case IMGFMT_MPEGPES
: return "Mpeg PES";
387 #define INREG8(addr) readb((radeon_mmio_base)+addr)
388 #define OUTREG8(addr,val) writeb(val, (radeon_mmio_base)+addr)
389 #define INREG(addr) readl((radeon_mmio_base)+addr)
390 #define OUTREG(addr,val) writel(val, (radeon_mmio_base)+addr)
391 #define OUTREGP(addr,val,mask) \
393 unsigned int tmp = INREG(addr); \
399 static uint32_t radeon_vid_get_dbpp( void )
401 uint32_t dbpp
,retval
;
402 dbpp
= (INREG(CRTC_GEN_CNTL
)>>8)& 0xF;
405 case DST_8BPP
: retval
= 8; break;
406 case DST_15BPP
: retval
= 15; break;
407 case DST_16BPP
: retval
= 16; break;
408 case DST_24BPP
: retval
= 24; break;
409 default: retval
=32; break;
414 static int radeon_is_dbl_scan( void )
416 return (INREG(CRTC_GEN_CNTL
))&CRTC_DBL_SCAN_EN
;
419 static int radeon_is_interlace( void )
421 return (INREG(CRTC_GEN_CNTL
))&CRTC_INTERLACE_EN
;
424 static __inline__
void radeon_engine_flush ( void )
429 OUTREGP(RB2D_DSTCACHE_CTLSTAT
, RB2D_DC_FLUSH_ALL
,
432 for (i
=0; i
< 2000000; i
++) {
433 if (!(INREG(RB2D_DSTCACHE_CTLSTAT
) & RB2D_DC_BUSY
))
439 static __inline__
void radeon_fifo_wait (int entries
)
443 for (i
=0; i
<2000000; i
++)
444 if ((INREG(RBBM_STATUS
) & 0x7f) >= entries
)
449 static __inline__
void radeon_engine_idle ( void )
453 /* ensure FIFO is empty before waiting for idle */
454 radeon_fifo_wait (64);
456 for (i
=0; i
<2000000; i
++) {
457 if (((INREG(RBBM_STATUS
) & GUI_ACTIVE
)) == 0) {
458 radeon_engine_flush ();
465 static void __init
radeon_vid_save_state( void )
468 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
469 vregs
[i
].value
= INREG(vregs
[i
].name
);
472 static void __exit
radeon_vid_restore_state( void )
476 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
477 radeon_engine_idle();
478 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
479 radeon_fifo_wait(15);
480 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
483 OUTREG(vregs
[i
].name
,vregs
[i
].value
);
485 OUTREG(OV0_REG_LOAD_CNTL
, 0);
489 static void radeon_vid_dump_regs( void )
492 printk(RVID_MSG
"*** Begin of OV0 registers dump ***\n");
493 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
494 printk(RVID_MSG
"%s = %08X\n",vregs
[i
].sname
,INREG(vregs
[i
].name
));
495 printk(RVID_MSG
"*** End of OV0 registers dump ***\n");
500 /* Reference color space transform data */
501 typedef struct tagREF_TRANSFORM
512 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
513 REF_TRANSFORM trans
[2] =
515 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
516 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
518 /****************************************************************************
520 * Function: Calculates and sets color space transform from supplied *
521 * reference transform, gamma, brightness, contrast, hue and *
523 * Inputs: bright - brightness *
527 * ref - index to the table of refernce transforms *
529 ****************************************************************************/
531 static void radeon_set_transform(float bright
, float cont
, float sat
,
532 float hue
, unsigned ref
)
534 float OvHueSin
, OvHueCos
;
535 float CAdjLuma
, CAdjOff
;
536 float CAdjRCb
, CAdjRCr
;
537 float CAdjGCb
, CAdjGCr
;
538 float CAdjBCb
, CAdjBCr
;
539 float OvLuma
, OvROff
, OvGOff
, OvBOff
;
546 u32 dwOvLuma
, dwOvROff
, dwOvGOff
, dwOvBOff
;
547 u32 dwOvRCb
, dwOvRCr
;
548 u32 dwOvGCb
, dwOvGCr
;
549 u32 dwOvBCb
, dwOvBCr
;
551 if (ref
>= 2) return;
553 OvHueSin
= sin((double)hue
);
554 OvHueCos
= cos((double)hue
);
556 CAdjLuma
= cont
* trans
[ref
].RefLuma
;
557 CAdjOff
= cont
* trans
[ref
].RefLuma
* bright
* 1023.0;
559 CAdjRCb
= sat
* -OvHueSin
* trans
[ref
].RefRCr
;
560 CAdjRCr
= sat
* OvHueCos
* trans
[ref
].RefRCr
;
561 CAdjGCb
= sat
* (OvHueCos
* trans
[ref
].RefGCb
- OvHueSin
* trans
[ref
].RefGCr
);
562 CAdjGCr
= sat
* (OvHueSin
* trans
[ref
].RefGCb
+ OvHueCos
* trans
[ref
].RefGCr
);
563 CAdjBCb
= sat
* OvHueCos
* trans
[ref
].RefBCb
;
564 CAdjBCr
= sat
* OvHueSin
* trans
[ref
].RefBCb
;
566 #if 0 /* default constants */
567 CAdjLuma
= 1.16455078125;
570 CAdjRCr
= 1.59619140625;
571 CAdjGCb
= -0.39111328125;
573 CAdjBCb
= 2.01708984375;
584 OvLuma
* Loff
- (OvRCb
+ OvRCr
) * Coff
;
586 OvLuma
* Loff
- (OvGCb
+ OvGCr
) * Coff
;
588 OvLuma
* Loff
- (OvBCb
+ OvBCr
) * Coff
;
589 #if 0 /* default constants */
595 dwOvROff
= ((int)(OvROff
* 2.0)) & 0x1fff;
596 dwOvGOff
= (int)(OvGOff
* 2.0) & 0x1fff;
597 dwOvBOff
= (int)(OvBOff
* 2.0) & 0x1fff;
600 dwOvLuma
=(((int)(OvLuma
* 2048.0))&0x7fff)<<17;
601 dwOvRCb
= (((int)(OvRCb
* 2048.0))&0x7fff)<<1;
602 dwOvRCr
= (((int)(OvRCr
* 2048.0))&0x7fff)<<17;
603 dwOvGCb
= (((int)(OvGCb
* 2048.0))&0x7fff)<<1;
604 dwOvGCr
= (((int)(OvGCr
* 2048.0))&0x7fff)<<17;
605 dwOvBCb
= (((int)(OvBCb
* 2048.0))&0x7fff)<<1;
606 dwOvBCr
= (((int)(OvBCr
* 2048.0))&0x7fff)<<17;
610 dwOvLuma
= (((int)(OvLuma
* 256.0))&0x7ff)<<20;
611 dwOvRCb
= (((int)(OvRCb
* 256.0))&0x7ff)<<4;
612 dwOvRCr
= (((int)(OvRCr
* 256.0))&0x7ff)<<20;
613 dwOvGCb
= (((int)(OvGCb
* 256.0))&0x7ff)<<4;
614 dwOvGCr
= (((int)(OvGCr
* 256.0))&0x7ff)<<20;
615 dwOvBCb
= (((int)(OvBCb
* 256.0))&0x7ff)<<4;
616 dwOvBCr
= (((int)(OvBCr
* 256.0))&0x7ff)<<20;
619 OUTREG(OV0_LIN_TRANS_A
, dwOvRCb
| dwOvLuma
);
620 OUTREG(OV0_LIN_TRANS_B
, dwOvROff
| dwOvRCr
);
621 OUTREG(OV0_LIN_TRANS_C
, dwOvGCb
| dwOvLuma
);
622 OUTREG(OV0_LIN_TRANS_D
, dwOvGOff
| dwOvGCr
);
623 OUTREG(OV0_LIN_TRANS_E
, dwOvBCb
| dwOvLuma
);
624 OUTREG(OV0_LIN_TRANS_F
, dwOvBOff
| dwOvBCr
);
629 /* Gamma curve definition */
632 unsigned int gammaReg
;
633 unsigned int gammaSlope
;
634 unsigned int gammaOffset
;
637 /* Recommended gamma curve parameters */
638 GAMMA_SETTINGS r200_def_gamma
[18] =
640 {OV0_GAMMA_0_F
, 0x100, 0x0000},
641 {OV0_GAMMA_10_1F
, 0x100, 0x0020},
642 {OV0_GAMMA_20_3F
, 0x100, 0x0040},
643 {OV0_GAMMA_40_7F
, 0x100, 0x0080},
644 {OV0_GAMMA_80_BF
, 0x100, 0x0100},
645 {OV0_GAMMA_C0_FF
, 0x100, 0x0100},
646 {OV0_GAMMA_100_13F
, 0x100, 0x0200},
647 {OV0_GAMMA_140_17F
, 0x100, 0x0200},
648 {OV0_GAMMA_180_1BF
, 0x100, 0x0300},
649 {OV0_GAMMA_1C0_1FF
, 0x100, 0x0300},
650 {OV0_GAMMA_200_23F
, 0x100, 0x0400},
651 {OV0_GAMMA_240_27F
, 0x100, 0x0400},
652 {OV0_GAMMA_280_2BF
, 0x100, 0x0500},
653 {OV0_GAMMA_2C0_2FF
, 0x100, 0x0500},
654 {OV0_GAMMA_300_33F
, 0x100, 0x0600},
655 {OV0_GAMMA_340_37F
, 0x100, 0x0600},
656 {OV0_GAMMA_380_3BF
, 0x100, 0x0700},
657 {OV0_GAMMA_3C0_3FF
, 0x100, 0x0700}
660 GAMMA_SETTINGS r100_def_gamma
[6] =
662 {OV0_GAMMA_0_F
, 0x100, 0x0000},
663 {OV0_GAMMA_10_1F
, 0x100, 0x0020},
664 {OV0_GAMMA_20_3F
, 0x100, 0x0040},
665 {OV0_GAMMA_40_7F
, 0x100, 0x0080},
666 {OV0_GAMMA_380_3BF
, 0x100, 0x0100},
667 {OV0_GAMMA_3C0_3FF
, 0x100, 0x0100}
670 static void make_default_gamma_correction( void )
674 OUTREG(OV0_LIN_TRANS_A
, 0x12A00000);
675 OUTREG(OV0_LIN_TRANS_B
, 0x199018FE);
676 OUTREG(OV0_LIN_TRANS_C
, 0x12A0F9B0);
677 OUTREG(OV0_LIN_TRANS_D
, 0xF2F0043B);
678 OUTREG(OV0_LIN_TRANS_E
, 0x12A02050);
679 OUTREG(OV0_LIN_TRANS_F
, 0x0000174E);
681 OUTREG(r100_def_gamma
[i
].gammaReg
,
682 (r100_def_gamma
[i
].gammaSlope
<<16) |
683 r100_def_gamma
[i
].gammaOffset
);
687 OUTREG(OV0_LIN_TRANS_A
, 0x12a00000);
688 OUTREG(OV0_LIN_TRANS_B
, 0x1990190e);
689 OUTREG(OV0_LIN_TRANS_C
, 0x12a0f9c0);
690 OUTREG(OV0_LIN_TRANS_D
, 0xf3000442);
691 OUTREG(OV0_LIN_TRANS_E
, 0x12a02040);
692 OUTREG(OV0_LIN_TRANS_F
, 0x175f);
695 Of 18 segments for gamma cure, all segments in R200 are programmable,
696 while only lower 4 and upper 2 segments are programmable in Radeon*/
698 OUTREG(r200_def_gamma
[i
].gammaReg
,
699 (r200_def_gamma
[i
].gammaSlope
<<16) |
700 r200_def_gamma
[i
].gammaOffset
);
706 static void radeon_vid_stop_video( void )
708 radeon_engine_idle();
709 OUTREG(OV0_SCALE_CNTL
, SCALER_SOFT_RESET
);
710 OUTREG(OV0_EXCLUSIVE_HORZ
, 0);
711 OUTREG(OV0_AUTO_FLIP_CNTL
, 0); /* maybe */
712 OUTREG(OV0_FILTER_CNTL
, FILTER_HARDCODED_COEF
);
713 OUTREG(OV0_KEY_CNTL
, GRAPHIC_KEY_FN_NE
);
717 static void radeon_vid_display_video( void )
721 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
722 radeon_engine_idle();
723 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
724 radeon_fifo_wait(15);
725 OUTREG(OV0_AUTO_FLIP_CNTL
,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD
);
726 OUTREG(OV0_AUTO_FLIP_CNTL
,(INREG(OV0_AUTO_FLIP_CNTL
)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE
));
727 OUTREG(OV0_AUTO_FLIP_CNTL
,(INREG(OV0_AUTO_FLIP_CNTL
)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE
));
729 OUTREG(OV0_DEINTERLACE_PATTERN
,besr
.deinterlace_pattern
);
731 OUTREG(OV0_COLOUR_CNTL
, (besr
.brightness
& 0x7f) |
732 (besr
.saturation
<< 8) |
733 (besr
.saturation
<< 16));
738 OUTREG(OV0_GRAPHICS_KEY_MSK
, besr
.graphics_key_msk
);
739 OUTREG(OV0_GRAPHICS_KEY_CLR
, besr
.graphics_key_clr
);
740 OUTREG(OV0_KEY_CNTL
,GRAPHIC_KEY_FN_EQ
|VIDEO_KEY_FN_FALSE
|CMP_MIX_OR
);
744 OUTREG(OV0_GRAPHICS_KEY_MSK
, 0ULL);
745 OUTREG(OV0_GRAPHICS_KEY_CLR
, 0ULL);
746 OUTREG(OV0_KEY_CNTL
,GRAPHIC_KEY_FN_NE
);
749 OUTREG(OV0_H_INC
, besr
.h_inc
);
750 OUTREG(OV0_STEP_BY
, besr
.step_by
);
751 OUTREG(OV0_Y_X_START
, besr
.y_x_start
);
752 OUTREG(OV0_Y_X_END
, besr
.y_x_end
);
753 OUTREG(OV0_V_INC
, besr
.v_inc
);
754 OUTREG(OV0_P1_BLANK_LINES_AT_TOP
, besr
.p1_blank_lines_at_top
);
755 OUTREG(OV0_P23_BLANK_LINES_AT_TOP
, besr
.p23_blank_lines_at_top
);
756 OUTREG(OV0_VID_BUF_PITCH0_VALUE
, besr
.vid_buf_pitch0_value
);
757 OUTREG(OV0_VID_BUF_PITCH1_VALUE
, besr
.vid_buf_pitch1_value
);
758 OUTREG(OV0_P1_X_START_END
, besr
.p1_x_start_end
);
759 OUTREG(OV0_P2_X_START_END
, besr
.p2_x_start_end
);
760 OUTREG(OV0_P3_X_START_END
, besr
.p3_x_start_end
);
762 OUTREG(OV0_BASE_ADDR
, besr
.base_addr
);
764 OUTREG(OV0_VID_BUF0_BASE_ADRS
, besr
.vid_buf0_base_adrs
);
765 OUTREG(OV0_VID_BUF1_BASE_ADRS
, besr
.vid_buf1_base_adrs
);
766 OUTREG(OV0_VID_BUF2_BASE_ADRS
, besr
.vid_buf2_base_adrs
);
768 OUTREG(OV0_VID_BUF3_BASE_ADRS
, besr
.vid_buf3_base_adrs
);
769 OUTREG(OV0_VID_BUF4_BASE_ADRS
, besr
.vid_buf4_base_adrs
);
770 OUTREG(OV0_VID_BUF5_BASE_ADRS
, besr
.vid_buf5_base_adrs
);
771 OUTREG(OV0_P1_V_ACCUM_INIT
, besr
.p1_v_accum_init
);
772 OUTREG(OV0_P1_H_ACCUM_INIT
, besr
.p1_h_accum_init
);
773 OUTREG(OV0_P23_H_ACCUM_INIT
, besr
.p23_h_accum_init
);
774 OUTREG(OV0_P23_V_ACCUM_INIT
, besr
.p23_v_accum_init
);
777 bes_flags
= SCALER_ENABLE
|
779 // SCALER_HORZ_PICK_NEAREST;
781 bes_flags
= SCALER_ENABLE
|
782 SCALER_SMART_SWITCH
|
786 if(besr
.double_buff
) bes_flags
|= SCALER_DOUBLE_BUFFER
;
787 if(besr
.deinterlace_on
) bes_flags
|= SCALER_ADAPTIVE_DEINT
;
789 bes_flags
|= SCALER_BURST_PER_PLANE
;
794 case IMGFMT_BGR15
: bes_flags
|= SCALER_SOURCE_15BPP
; break;
796 case IMGFMT_BGR16
: bes_flags
|= SCALER_SOURCE_16BPP
; break;
798 case IMGFMT_BGR24
: bes_flags
|= SCALER_SOURCE_24BPP
; break;
800 case IMGFMT_BGR32
: bes_flags
|= SCALER_SOURCE_32BPP
; break;
803 case IMGFMT_YVU9
: bes_flags
|= SCALER_SOURCE_YUV9
; break;
807 case IMGFMT_YV12
: bes_flags
|= SCALER_SOURCE_YUV12
;
810 case IMGFMT_UYVY
: bes_flags
|= SCALER_SOURCE_YVYU422
; break;
812 default: bes_flags
|= SCALER_SOURCE_VYUY422
; break;
814 OUTREG(OV0_SCALE_CNTL
, bes_flags
);
815 OUTREG(OV0_REG_LOAD_CNTL
, 0);
817 radeon_vid_dump_regs();
821 void radeon_vid_set_color_key(int ckey_on
, uint8_t R
, uint8_t G
, uint8_t B
)
823 besr
.ckey_on
= ckey_on
;
824 besr
.graphics_key_msk
=(1ULL<<radeon_vid_get_dbpp()) - 1;
825 besr
.graphics_key_clr
=(R
<<16)|(G
<<8)|(B
)|(0x00 << 24);
832 static int radeon_vid_init_video( mga_vid_config_t
*config
)
834 uint32_t tmp
,src_w
,src_h
,pitch
,h_inc
,step_by
,left
,leftUV
,top
;
836 RTRACE(RVID_MSG
"usr_config: version = %x format=%x card=%x ram=%u src(%ux%u) dest(%u:%ux%u:%u) frame_size=%u num_frames=%u\n"
837 ,(uint32_t)config
->version
838 ,(uint32_t)config
->format
839 ,(uint32_t)config
->card_type
840 ,(uint32_t)config
->ram_size
841 ,(uint32_t)config
->src_width
842 ,(uint32_t)config
->src_height
843 ,(uint32_t)config
->x_org
844 ,(uint32_t)config
->y_org
845 ,(uint32_t)config
->dest_width
846 ,(uint32_t)config
->dest_height
847 ,(uint32_t)config
->frame_size
848 ,(uint32_t)config
->num_frames
);
849 radeon_vid_stop_video();
850 left
= XXX_SRC_X
<< 16;
851 top
= XXX_SRC_Y
<< 16;
852 src_h
= config
->src_height
;
853 src_w
= config
->src_width
;
854 switch(config
->format
)
876 printk(RVID_MSG
"Unsupported pixel format: 0x%X\n",config
->format
);
880 if(config
->format
== IMGFMT_YV12
||
881 config
->format
== IMGFMT_I420
||
882 config
->format
== IMGFMT_IYUV
) is_420
= 1;
883 switch(config
->format
)
891 case IMGFMT_I420
: pitch
= (src_w
+ 31) & ~31; break;
899 case IMGFMT_BGR16
: pitch
= ((src_w
*2) + 15) & ~15; break;
901 case IMGFMT_BGR24
: pitch
= ((src_w
*3) + 15) & ~15; break;
903 case IMGFMT_BGR32
: pitch
= ((src_w
*4) + 15) & ~15; break;
905 if(radeon_is_dbl_scan()) config
->dest_height
*= 2;
907 if(radeon_is_interlace()) config
->dest_height
/= 2;
908 besr
.dest_bpp
= radeon_vid_get_dbpp();
909 besr
.fourcc
= config
->format
;
910 besr
.v_inc
= (src_h
<< 20) / config
->dest_height
;
911 h_inc
= (src_w
<< 12) / config
->dest_width
;
914 while(h_inc
>= (2 << 12)) {
919 /* keep everything in 16.16 */
920 besr
.base_addr
= radeon_mem_base
;
923 uint32_t d1line
,d2line
,d3line
;
925 d2line
= src_h
*pitch
+(d1line
>>1);
926 d3line
= d2line
+((src_h
*pitch
)>>2);
927 d1line
+= (left
>> 16) & ~15;
928 d2line
+= (left
>> 17) & ~15;
929 d3line
+= (left
>> 17) & ~15;
930 besr
.vid_buf0_base_adrs
=((radeon_overlay_off
+d1line
)&VIF_BUF0_BASE_ADRS_MASK
);
931 besr
.vid_buf1_base_adrs
=((radeon_overlay_off
+d2line
)&VIF_BUF1_BASE_ADRS_MASK
)|VIF_BUF1_PITCH_SEL
;
932 besr
.vid_buf2_base_adrs
=((radeon_overlay_off
+d3line
)&VIF_BUF2_BASE_ADRS_MASK
)|VIF_BUF2_PITCH_SEL
;
933 if(besr
.fourcc
== IMGFMT_I420
|| besr
.fourcc
== IMGFMT_IYUV
)
936 tmp
= besr
.vid_buf1_base_adrs
;
937 besr
.vid_buf1_base_adrs
= besr
.vid_buf2_base_adrs
;
938 besr
.vid_buf2_base_adrs
= tmp
;
943 besr
.vid_buf0_base_adrs
= radeon_overlay_off
;
944 besr
.vid_buf0_base_adrs
+= ((left
& ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK
;
945 besr
.vid_buf1_base_adrs
= besr
.vid_buf0_base_adrs
;
946 besr
.vid_buf2_base_adrs
= besr
.vid_buf0_base_adrs
;
948 besr
.vid_buf3_base_adrs
= besr
.vid_buf0_base_adrs
+config
->frame_size
;
949 besr
.vid_buf4_base_adrs
= besr
.vid_buf1_base_adrs
+config
->frame_size
;
950 besr
.vid_buf5_base_adrs
= besr
.vid_buf2_base_adrs
+config
->frame_size
;
952 tmp
= (left
& 0x0003ffff) + 0x00028000 + (h_inc
<< 3);
953 besr
.p1_h_accum_init
= ((tmp
<< 4) & 0x000f8000) |
954 ((tmp
<< 12) & 0xf0000000);
956 tmp
= ((left
>> 1) & 0x0001ffff) + 0x00028000 + (h_inc
<< 2);
957 besr
.p23_h_accum_init
= ((tmp
<< 4) & 0x000f8000) |
958 ((tmp
<< 12) & 0x70000000);
959 tmp
= (top
& 0x0000ffff) + 0x00018000;
960 besr
.p1_v_accum_init
= ((tmp
<< 4) & OV0_P1_V_ACCUM_INIT_MASK
)
961 |(OV0_P1_MAX_LN_IN_PER_LN_OUT
& 1);
963 tmp
= ((top
>> 1) & 0x0000ffff) + 0x00018000;
964 besr
.p23_v_accum_init
= is_420
? ((tmp
<< 4) & OV0_P23_V_ACCUM_INIT_MASK
)
965 |(OV0_P23_MAX_LN_IN_PER_LN_OUT
& 1) : 0;
967 leftUV
= (left
>> 17) & 15;
968 left
= (left
>> 16) & 15;
969 besr
.h_inc
= h_inc
| ((h_inc
>> 1) << 16);
970 besr
.step_by
= step_by
| (step_by
<< 8);
971 besr
.y_x_start
= (config
->x_org
+X_ADJUST
) | (config
->y_org
<< 16);
972 besr
.y_x_end
= (config
->x_org
+ config
->dest_width
+X_ADJUST
) | ((config
->y_org
+ config
->dest_height
) << 16);
973 besr
.p1_blank_lines_at_top
= P1_BLNK_LN_AT_TOP_M1_MASK
|((src_h
-1)<<16);
976 src_h
= (src_h
+ 1) >> 1;
977 besr
.p23_blank_lines_at_top
= P23_BLNK_LN_AT_TOP_M1_MASK
|((src_h
-1)<<16);
979 else besr
.p23_blank_lines_at_top
= 0;
980 besr
.vid_buf_pitch0_value
= pitch
;
981 besr
.vid_buf_pitch1_value
= is_420
? pitch
>>1 : pitch
;
982 besr
.p1_x_start_end
= (src_w
+left
-1)|(left
<<16);
984 besr
.p2_x_start_end
= (src_w
+left
-1)|(leftUV
<<16);
985 besr
.p3_x_start_end
= besr
.p2_x_start_end
;
989 static void radeon_vid_frame_sel(int frame
)
991 uint32_t off0
,off1
,off2
;
992 if(!besr
.double_buff
) return;
995 off0
= besr
.vid_buf3_base_adrs
;
996 off1
= besr
.vid_buf4_base_adrs
;
997 off2
= besr
.vid_buf5_base_adrs
;
1001 off0
= besr
.vid_buf0_base_adrs
;
1002 off1
= besr
.vid_buf1_base_adrs
;
1003 off2
= besr
.vid_buf2_base_adrs
;
1005 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
1006 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
1007 OUTREG(OV0_VID_BUF0_BASE_ADRS
, off0
);
1008 OUTREG(OV0_VID_BUF1_BASE_ADRS
, off1
);
1009 OUTREG(OV0_VID_BUF2_BASE_ADRS
, off2
);
1010 OUTREG(OV0_REG_LOAD_CNTL
, 0);
1013 static void radeon_vid_make_default(void)
1016 OUTREG(OV0_COLOUR_CNTL
,0x00101000UL
); /* Default brihgtness and saturation for Rage128 */
1018 make_default_gamma_correction();
1020 besr
.deinterlace_pattern
= 0x900AAAAA;
1021 OUTREG(OV0_DEINTERLACE_PATTERN
,besr
.deinterlace_pattern
);
1022 besr
.deinterlace_on
=1;
1027 static void radeon_vid_preset(void)
1031 tmp
= INREG(OV0_COLOUR_CNTL
);
1032 besr
.saturation
= (tmp
>>8)&0x1f;
1033 besr
.brightness
= tmp
& 0x7f;
1035 besr
.graphics_key_clr
= INREG(OV0_GRAPHICS_KEY_CLR
);
1036 besr
.deinterlace_pattern
= INREG(OV0_DEINTERLACE_PATTERN
);
1039 static int video_on
= 0;
1041 static int radeon_vid_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
1047 case MGA_VID_CONFIG
:
1048 RTRACE(RVID_MSG
"radeon_mmio_base = %p\n",radeon_mmio_base
);
1049 RTRACE(RVID_MSG
"radeon_mem_base = %08x\n",radeon_mem_base
);
1050 RTRACE(RVID_MSG
"Received configuration\n");
1052 if(copy_from_user(&radeon_config
,(mga_vid_config_t
*) arg
,sizeof(mga_vid_config_t
)))
1054 printk(RVID_MSG
"failed copy from userspace\n");
1057 if(radeon_config
.version
!= MGA_VID_VERSION
){
1058 printk(RVID_MSG
"incompatible version! driver: %X requested: %X\n",MGA_VID_VERSION
,radeon_config
.version
);
1062 if(radeon_config
.frame_size
==0 || radeon_config
.frame_size
>1024*768*2){
1063 printk(RVID_MSG
"illegal frame_size: %d\n",radeon_config
.frame_size
);
1067 if(radeon_config
.num_frames
<1){
1068 printk(RVID_MSG
"illegal num_frames: %d\n",radeon_config
.num_frames
);
1071 if(radeon_config
.num_frames
==1) besr
.double_buff
=0;
1072 if(!besr
.double_buff
) radeon_config
.num_frames
=1;
1073 else radeon_config
.num_frames
=2;
1074 radeon_config
.card_type
= 0;
1075 radeon_config
.ram_size
= radeon_ram_size
;
1076 radeon_overlay_off
= radeon_ram_size
*0x100000 - radeon_config
.frame_size
*radeon_config
.num_frames
;
1077 radeon_overlay_off
&= 0xffff0000;
1078 if(radeon_overlay_off
< 0){
1079 printk(RVID_MSG
"not enough video memory. Need: %u has: %u\n",radeon_config
.frame_size
*radeon_config
.num_frames
,radeon_ram_size
*0x100000);
1082 RTRACE(RVID_MSG
"using video overlay at offset %08X\n",radeon_overlay_off
);
1083 if (copy_to_user((mga_vid_config_t
*) arg
, &radeon_config
, sizeof(mga_vid_config_t
)))
1085 printk(RVID_MSG
"failed copy to userspace\n");
1088 radeon_vid_set_color_key(radeon_config
.colkey_on
,
1089 radeon_config
.colkey_red
,
1090 radeon_config
.colkey_green
,
1091 radeon_config
.colkey_blue
);
1092 if(swap_fourcc
) radeon_config
.format
= swab32(radeon_config
.format
);
1093 printk(RVID_MSG
"configuring for '%s' fourcc\n",fourcc_format_name(radeon_config
.format
));
1094 return radeon_vid_init_video(&radeon_config
);
1098 RTRACE(RVID_MSG
"Video ON (ioctl)\n");
1099 radeon_vid_display_video();
1104 RTRACE(RVID_MSG
"Video OFF (ioctl)\n");
1105 if(video_on
) radeon_vid_stop_video();
1110 if(copy_from_user(&frame
,(int *) arg
,sizeof(int)))
1112 printk(RVID_MSG
"FSEL failed copy from userspace\n");
1115 radeon_vid_frame_sel(frame
);
1119 printk(RVID_MSG
"Invalid ioctl\n");
1126 struct ati_card_id_s
1129 const char name
[17];
1132 const struct ati_card_id_s ati_card_ids
[]=
1136 This driver should be compatible with Rage128 (pro) chips.
1137 (include adaptive deinterlacing!!!).
1138 Moreover: the same logic can be used with Mach64 chips.
1139 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
1140 but they are incompatible by i/o ports. So if enthusiasts will want
1141 then they can redefine OUTREG and INREG macros and redefine OV0_*
1142 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
1143 fourccs (422 and 420 formats only).
1145 /* Rage128 Pro GL */
1146 { PCI_DEVICE_ID_ATI_Rage128_PA
, "R128Pro PA" },
1147 { PCI_DEVICE_ID_ATI_Rage128_PB
, "R128Pro PB" },
1148 { PCI_DEVICE_ID_ATI_Rage128_PC
, "R128Pro PC" },
1149 { PCI_DEVICE_ID_ATI_Rage128_PD
, "R128Pro PD" },
1150 { PCI_DEVICE_ID_ATI_Rage128_PE
, "R128Pro PE" },
1151 { PCI_DEVICE_ID_ATI_RAGE128_PF
, "R128Pro PF" },
1152 /* Rage128 Pro VR */
1153 { PCI_DEVICE_ID_ATI_RAGE128_PG
, "R128Pro PG" },
1154 { PCI_DEVICE_ID_ATI_RAGE128_PH
, "R128Pro PH" },
1155 { PCI_DEVICE_ID_ATI_RAGE128_PI
, "R128Pro PI" },
1156 { PCI_DEVICE_ID_ATI_RAGE128_PJ
, "R128Pro PJ" },
1157 { PCI_DEVICE_ID_ATI_RAGE128_PK
, "R128Pro PK" },
1158 { PCI_DEVICE_ID_ATI_RAGE128_PL
, "R128Pro PL" },
1159 { PCI_DEVICE_ID_ATI_RAGE128_PM
, "R128Pro PM" },
1160 { PCI_DEVICE_ID_ATI_RAGE128_PN
, "R128Pro PN" },
1161 { PCI_DEVICE_ID_ATI_RAGE128_PO
, "R128Pro PO" },
1162 { PCI_DEVICE_ID_ATI_RAGE128_PP
, "R128Pro PP" },
1163 { PCI_DEVICE_ID_ATI_RAGE128_PQ
, "R128Pro PQ" },
1164 { PCI_DEVICE_ID_ATI_RAGE128_PR
, "R128Pro PR" },
1165 { PCI_DEVICE_ID_ATI_RAGE128_TR
, "R128Pro TR" },
1166 { PCI_DEVICE_ID_ATI_RAGE128_PS
, "R128Pro PS" },
1167 { PCI_DEVICE_ID_ATI_RAGE128_PT
, "R128Pro PT" },
1168 { PCI_DEVICE_ID_ATI_RAGE128_PU
, "R128Pro PU" },
1169 { PCI_DEVICE_ID_ATI_RAGE128_PV
, "R128Pro PV" },
1170 { PCI_DEVICE_ID_ATI_RAGE128_PW
, "R128Pro PW" },
1171 { PCI_DEVICE_ID_ATI_RAGE128_PX
, "R128Pro PX" },
1173 { PCI_DEVICE_ID_ATI_RAGE128_RE
, "R128 RE" },
1174 { PCI_DEVICE_ID_ATI_RAGE128_RF
, "R128 RF" },
1175 { PCI_DEVICE_ID_ATI_RAGE128_RG
, "R128 RG" },
1176 { PCI_DEVICE_ID_ATI_RAGE128_RH
, "R128 RH" },
1177 { PCI_DEVICE_ID_ATI_RAGE128_RI
, "R128 RI" },
1179 { PCI_DEVICE_ID_ATI_RAGE128_RK
, "R128 RK" },
1180 { PCI_DEVICE_ID_ATI_RAGE128_RL
, "R128 RL" },
1181 { PCI_DEVICE_ID_ATI_RAGE128_RM
, "R128 RM" },
1182 { PCI_DEVICE_ID_ATI_RAGE128_RN
, "R128 RN" },
1183 { PCI_DEVICE_ID_ATI_RAGE128_RO
, "R128 RO" },
1185 { PCI_DEVICE_ID_ATI_RAGE128_LE
, "R128 M3 LE" },
1186 { PCI_DEVICE_ID_ATI_RAGE128_LF
, "R128 M3 LF" },
1187 /* Rage128 Pro Ultra */
1188 { PCI_DEVICE_ID_ATI_RAGE128_U1
, "R128Pro U1" },
1189 { PCI_DEVICE_ID_ATI_RAGE128_U2
, "R128Pro U2" },
1190 { PCI_DEVICE_ID_ATI_RAGE128_U3
, "R128Pro U3" }
1192 /* Radeons (indeed: Rage 256 Pro ;) */
1193 { PCI_DEVICE_ID_RADEON_QD
, "Radeon QD " },
1194 { PCI_DEVICE_ID_RADEON_QE
, "Radeon QE " },
1195 { PCI_DEVICE_ID_RADEON_QF
, "Radeon QF " },
1196 { PCI_DEVICE_ID_RADEON_QG
, "Radeon QG " },
1197 { PCI_DEVICE_ID_RADEON_QY
, "Radeon VE QY " },
1198 { PCI_DEVICE_ID_RADEON_QZ
, "Radeon VE QZ " },
1199 { PCI_DEVICE_ID_RADEON_LY
, "Radeon M6 LY " },
1200 { PCI_DEVICE_ID_RADEON_LZ
, "Radeon M6 LZ " },
1201 { PCI_DEVICE_ID_RADEON_LW
, "Radeon M7 LW " },
1202 { PCI_DEVICE_ID_R200_QL
, "Radeon2 8500 QL " },
1203 { PCI_DEVICE_ID_R200_BB
, "Radeon2 8500 AIW" },
1204 { PCI_DEVICE_ID_RV200_QW
, "Radeon2 7500 QW " }
1208 static int detected_chip
;
1210 static int __init
radeon_vid_config_card(void)
1212 struct pci_dev
*dev
= NULL
;
1215 for(i
=0;i
<sizeof(ati_card_ids
)/sizeof(struct ati_card_id_s
);i
++)
1216 if((dev
=pci_find_device(PCI_VENDOR_ID_ATI
, ati_card_ids
[i
].id
, NULL
)))
1220 printk(RVID_MSG
"No supported cards found\n");
1224 radeon_mmio_base
= ioremap_nocache(pci_resource_start (dev
, 2),RADEON_REGSIZE
);
1225 radeon_mem_base
= dev
->resource
[0].start
;
1227 RTRACE(RVID_MSG
"MMIO at 0x%p\n", radeon_mmio_base
);
1228 RTRACE(RVID_MSG
"Frame Buffer at 0x%08x\n", radeon_mem_base
);
1230 /* video memory size */
1231 radeon_ram_size
= INREG(CONFIG_MEMSIZE
);
1233 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1234 radeon_ram_size
&= CONFIG_MEMSIZE_MASK
;
1235 radeon_ram_size
/= 0x100000;
1237 printk(RVID_MSG
"Found %s (%uMb memory)\n",ati_card_ids
[i
].name
,radeon_ram_size
);
1239 if(ati_card_ids
[i
].id
== PCI_DEVICE_ID_R200_QL
||
1240 ati_card_ids
[i
].id
== PCI_DEVICE_ID_R200_BB
||
1241 ati_card_ids
[i
].id
== PCI_DEVICE_ID_RV200_QW
) IsR200
= 1;
1246 #define PARAM_BRIGHTNESS "brightness="
1247 #define PARAM_SATURATION "saturation="
1248 #define PARAM_CONTRAST "contrast="
1249 #define PARAM_HUE "hue="
1250 #define PARAM_DOUBLE_BUFF "double_buff="
1251 #define PARAM_DEINTERLACE "deinterlace="
1252 #define PARAM_DEINTERLACE_PATTERN "deinterlace_pattern="
1254 static int ovBrightness
=0, ovSaturation
=0, ovContrast
=0, ovHue
=0, ov_trans_idx
=0;
1257 static void radeon_param_buff_fill( void )
1259 unsigned len
,saturation
;
1261 brightness
= besr
.brightness
& 0x7f;
1262 /* FIXME: It's probably x86 specific convertion. But it doesn't matter
1263 for general logic - only for printing value */
1264 if(brightness
> 63) brightness
= (((~besr
.brightness
) & 0x3f)+1) * (-1);
1265 saturation
= besr
.saturation
;
1267 len
+= sprintf(&radeon_param_buff
[len
],"Interface version: %04X\nDriver version: %s\n",MGA_VID_VERSION
,RADEON_VID_VERSION
);
1268 len
+= sprintf(&radeon_param_buff
[len
],"Chip: %s\n",ati_card_ids
[detected_chip
].name
);
1269 len
+= sprintf(&radeon_param_buff
[len
],"Memory: %x:%x\n",radeon_mem_base
,radeon_ram_size
*0x100000);
1270 len
+= sprintf(&radeon_param_buff
[len
],"MMIO: %p\n",radeon_mmio_base
);
1271 len
+= sprintf(&radeon_param_buff
[len
],"Overlay offset: %x\n",radeon_overlay_off
);
1273 len
+= sprintf(&radeon_param_buff
[len
],"Tune MTRR: %s\n",mtrr
?"on":"off");
1275 if(besr
.ckey_on
) len
+= sprintf(&radeon_param_buff
[len
],"Last used color_key=%X (mask=%X)\n",besr
.graphics_key_clr
,besr
.graphics_key_msk
);
1276 len
+= sprintf(&radeon_param_buff
[len
],"Swapped fourcc: %s\n",swap_fourcc
?"on":"off");
1277 len
+= sprintf(&radeon_param_buff
[len
],"Last BPP: %u\n",besr
.dest_bpp
);
1278 len
+= sprintf(&radeon_param_buff
[len
],"Last fourcc: %s\n\n",fourcc_format_name(besr
.fourcc
));
1279 len
+= sprintf(&radeon_param_buff
[len
],"Configurable stuff:\n");
1280 len
+= sprintf(&radeon_param_buff
[len
],"~~~~~~~~~~~~~~~~~~~\n");
1281 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DOUBLE_BUFF
"%s\n",besr
.double_buff
?"on":"off");
1283 len
+= sprintf(&radeon_param_buff
[len
],PARAM_BRIGHTNESS
"%i\n",(int)brightness
);
1284 len
+= sprintf(&radeon_param_buff
[len
],PARAM_SATURATION
"%u\n",saturation
);
1287 len
+= sprintf(&radeon_param_buff
[len
],PARAM_BRIGHTNESS
"%i\n",ovBrightness
);
1288 len
+= sprintf(&radeon_param_buff
[len
],PARAM_SATURATION
"%i\n",ovSaturation
);
1289 len
+= sprintf(&radeon_param_buff
[len
],PARAM_CONTRAST
"%i\n",ovContrast
);
1290 len
+= sprintf(&radeon_param_buff
[len
],PARAM_HUE
"%i\n",ovHue
);
1293 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DEINTERLACE
"%s\n",besr
.deinterlace_on
?"on":"off");
1294 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DEINTERLACE_PATTERN
"%X\n",besr
.deinterlace_pattern
);
1295 radeon_param_buff_len
= len
;
1298 static ssize_t
radeon_vid_read(struct file
*file
, char *buf
, size_t count
, loff_t
*ppos
)
1301 if(!radeon_param_buff
) return -ESPIPE
;
1302 if(!(*ppos
)) radeon_param_buff_fill();
1303 if(*ppos
>= radeon_param_buff_len
) return 0;
1304 size
= min(count
,radeon_param_buff_len
-(uint32_t)(*ppos
));
1305 memcpy(buf
,radeon_param_buff
,size
);
1310 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
1311 #define RTFBrightness(a) (((a)*1.0)/2000.0)
1312 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
1313 #define RTFHue(a) (((a)*3.1416)/1000.0)
1314 #define RadeonSetParm(a,b,c,d) if((b)>=(c)&&(b)<=(d)) { (a)=(b);\
1315 radeon_set_transform(RTFBrightness(ovBrightness),RTFContrast(ovContrast)\
1316 ,RTFSaturation(ovSaturation),RTFHue(ovHue),ov_trans_idx); }
1319 static ssize_t
radeon_vid_write(struct file
*file
, const char *buf
, size_t count
, loff_t
*ppos
)
1322 if(memcmp(buf
,PARAM_BRIGHTNESS
,min(count
,strlen(PARAM_BRIGHTNESS
))) == 0)
1325 brightness
=simple_strtol(&buf
[strlen(PARAM_BRIGHTNESS
)],NULL
,10);
1326 if(brightness
>= -64 && brightness
<= 63)
1328 besr
.brightness
= brightness
;
1329 OUTREG(OV0_COLOUR_CNTL
, (brightness
& 0x7f) |
1330 (besr
.saturation
<< 8) |
1331 (besr
.saturation
<< 16));
1335 if(memcmp(buf
,PARAM_SATURATION
,min(count
,strlen(PARAM_SATURATION
))) == 0)
1338 saturation
=simple_strtol(&buf
[strlen(PARAM_SATURATION
)],NULL
,10);
1339 if(saturation
>= 0 && saturation
<= 31)
1340 OUTREG(OV0_COLOUR_CNTL
, (besr
.brightness
& 0x7f) |
1342 (saturation
<< 16));
1347 if(memcmp(buf
,PARAM_BRIGHTNESS
,min(count
,strlen(PARAM_BRIGHTNESS
))) == 0)
1350 tmp
=simple_strtol(&buf
[strlen(PARAM_BRIGHTNESS
)],NULL
,10);
1351 RadeonSetParm(ovBrightness
,tmp
,-1000,1000);
1354 if(memcmp(buf
,PARAM_SATURATION
,min(count
,strlen(PARAM_SATURATION
))) == 0)
1357 tmp
=simple_strtol(&buf
[strlen(PARAM_SATURATION
)],NULL
,10);
1358 RadeonSetParm(ovSaturation
,tmp
,-1000,1000);
1361 if(memcmp(buf
,PARAM_CONTRAST
,min(count
,strlen(PARAM_CONTRAST
))) == 0)
1364 tmp
=simple_strtol(&buf
[strlen(PARAM_CONTRAST
)],NULL
,10);
1365 RadeonSetParm(ovContrast
,tmp
,-1000,1000);
1368 if(memcmp(buf
,PARAM_HUE
,min(count
,strlen(PARAM_HUE
))) == 0)
1371 tmp
=simple_strtol(&buf
[strlen(PARAM_HUE
)],NULL
,10);
1372 RadeonSetParm(ovHue
,tmp
,-1000,1000);
1377 if(memcmp(buf
,PARAM_DOUBLE_BUFF
,min(count
,strlen(PARAM_DOUBLE_BUFF
))) == 0)
1379 if(memcmp(&buf
[strlen(PARAM_DOUBLE_BUFF
)],"on",2) == 0) besr
.double_buff
= 1;
1380 else besr
.double_buff
= 0;
1383 if(memcmp(buf
,PARAM_DEINTERLACE
,min(count
,strlen(PARAM_DEINTERLACE
))) == 0)
1385 if(memcmp(&buf
[strlen(PARAM_DEINTERLACE
)],"on",2) == 0) besr
.deinterlace_on
= 1;
1386 else besr
.deinterlace_on
= 0;
1389 if(memcmp(buf
,PARAM_DEINTERLACE_PATTERN
,min(count
,strlen(PARAM_DEINTERLACE_PATTERN
))) == 0)
1392 dpat
=simple_strtol(&buf
[strlen(PARAM_DEINTERLACE_PATTERN
)],NULL
,16);
1393 OUTREG(OV0_DEINTERLACE_PATTERN
, dpat
);
1396 radeon_vid_preset();
1400 static int radeon_vid_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1403 RTRACE(RVID_MSG
"mapping video memory into userspace\n");
1404 if(remap_page_range(vma
->vm_start
, radeon_mem_base
+ radeon_overlay_off
,
1405 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
1407 printk(RVID_MSG
"error mapping video memory\n");
1414 static int radeon_vid_release(struct inode
*inode
, struct file
*file
)
1416 radeon_vid_in_use
= 0;
1417 radeon_vid_stop_video();
1423 static long long radeon_vid_lseek(struct file
*file
, long long offset
, int origin
)
1428 static int radeon_vid_open(struct inode
*inode
, struct file
*file
)
1430 int minor
= MINOR(inode
->i_rdev
);
1435 if(radeon_vid_in_use
== 1)
1438 radeon_vid_in_use
= 1;
1443 #if LINUX_VERSION_CODE >= 0x020400
1444 static struct file_operations radeon_vid_fops
=
1446 llseek
: radeon_vid_lseek
,
1447 read
: radeon_vid_read
,
1448 write
: radeon_vid_write
,
1453 ioctl
: radeon_vid_ioctl
,
1454 mmap
: radeon_vid_mmap
,
1455 open
: radeon_vid_open
,
1459 release
: radeon_vid_release
1471 static struct file_operations radeon_vid_fops
=
1487 * Main Initialization Function
1490 static int __init
radeon_vid_initialize(void)
1492 radeon_vid_in_use
= 0;
1494 printk(RVID_MSG
"Rage128/Rage128Pro video overlay driver v"RADEON_VID_VERSION
" (C) Nick Kurshev\n");
1496 printk(RVID_MSG
"Radeon video overlay driver v"RADEON_VID_VERSION
" (C) Nick Kurshev\n");
1498 if(register_chrdev(RADEON_VID_MAJOR
, "radeon_vid", &radeon_vid_fops
))
1500 printk(RVID_MSG
"unable to get major: %d\n", RADEON_VID_MAJOR
);
1504 if (!radeon_vid_config_card())
1506 printk(RVID_MSG
"can't configure this card\n");
1507 unregister_chrdev(RADEON_VID_MAJOR
, "radeon_vid");
1510 radeon_param_buff
= kmalloc(PARAM_BUFF_SIZE
,GFP_KERNEL
);
1511 if(radeon_param_buff
) radeon_param_buff_size
= PARAM_BUFF_SIZE
;
1513 radeon_vid_save_state();
1515 radeon_vid_make_default();
1516 radeon_vid_preset();
1519 smtrr
.vram
= mtrr_add(radeon_mem_base
,
1520 radeon_ram_size
*0x100000, MTRR_TYPE_WRCOMB
, 1);
1521 smtrr
.vram_valid
= 1;
1522 /* let there be speed */
1523 printk(RVID_MSG
"MTRR set to ON\n");
1525 #endif /* CONFIG_MTRR */
1529 int __init
init_module(void)
1531 return radeon_vid_initialize();
1534 void __exit
cleanup_module(void)
1537 radeon_vid_restore_state();
1539 if(radeon_mmio_base
)
1540 iounmap(radeon_mmio_base
);
1541 kfree(radeon_param_buff
);
1542 RTRACE(RVID_MSG
"Cleaning up module\n");
1543 unregister_chrdev(RADEON_VID_MAJOR
, "radeon_vid");
1545 if (smtrr
.vram_valid
)
1546 mtrr_del(smtrr
.vram
, radeon_mem_base
,
1547 radeon_ram_size
*0x100000);
1548 #endif /* CONFIG_MTRR */