5 * Copyright (C) 2001 Nick Kurshev
7 * BES YUV video overlay driver for Radeon/Rage128Pro/Rage128 cards
9 * This software has been released under the terms of the GNU Public
10 * license. See http://www.gnu.org/copyleft/gpl.html for details.
12 * This file is partly based on mga_vid and sis_vid stuff from
14 * Also here was used code from CVS of GATOS project and X11 trees.
16 * SPECIAL THANKS TO: Hans-Peter Raschke for active testing and hacking
17 * Rage128(pro) stuff of this driver.
20 #define RADEON_VID_VERSION "1.2.1"
23 It's entirely possible this major conflicts with something else
24 mknod /dev/radeon_vid c 178 0
26 mknod /dev/rage128_vid c 178 0
27 for Rage128/Rage128Pro chips (although it doesn't matter)
28 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
29 TESTED and WORKING formats: YUY2, UYVY, IYUV, I420, YV12
30 -----------------------------------------------------------
32 Highest priority: fbvid.h compatibility
33 High priority: Fixing BUGS
34 Middle priority: RGB/BGR 2-32, YVU9, IF09 support
35 Low priority: CLPL, IYU1, IYU2, UYNV, CYUV, YUNV, YVYU, Y41P, Y211, Y41T,
37 Y42T, V422, V655, CLJR, YUVP, UYVP, Mpeg PES (mpeg-1,2) support
38 ...........................................................
40 Color and video keys don't work
43 #include <linux/config.h>
44 #include <linux/version.h>
45 #include <linux/module.h>
46 #include <linux/types.h>
47 #include <linux/kernel.h>
48 #include <linux/sched.h>
50 #include <linux/string.h>
51 #include <linux/errno.h>
52 #include <linux/slab.h>
53 #include <linux/pci.h>
54 #include <linux/ioport.h>
55 #include <linux/init.h>
56 #include <linux/byteorder/swab.h>
58 #include "radeon_vid.h"
65 #include <asm/uaccess.h>
66 #include <asm/system.h>
72 #define RADEON_VID_MAJOR 178
75 MODULE_AUTHOR("Nick Kurshev <nickols_k@mail.ru>");
77 MODULE_DESCRIPTION("Accelerated YUV BES driver for Rage128. Version: "RADEON_VID_VERSION
);
79 MODULE_DESCRIPTION("Accelerated YUV BES driver for Radeons. Version: "RADEON_VID_VERSION
);
82 MODULE_LICENSE("GPL");
85 MODULE_PARM(mtrr
, "i");
86 MODULE_PARM_DESC(mtrr
, "Tune MTRR (touch=1(default))");
87 static int mtrr __initdata
= 1;
88 static struct { int vram
; int vram_valid
; } smtrr
;
90 MODULE_PARM(swap_fourcc
, "i");
91 MODULE_PARM_DESC(swap_fourcc
, "Swap fourcc (don't swap=0(default))");
92 static int swap_fourcc __initdata
= 0;
95 #define RVID_MSG "rage128_vid: "
98 #define RVID_MSG "radeon_vid: "
107 #define RTRACE printk
109 #define RTRACE(...) ((void)0)
113 #define min(a,b) (a < b ? a : b)
117 #if defined(__i386__)
118 /* Ugly but only way */
120 static double inline __FastSin(double x
)
123 __asm
__volatile("fsin":"=t"(res
):"0"(x
));
127 #define sin(x) __FastSin(x)
129 static double inline __FastCos(double x
)
132 __asm
__volatile("fcos":"=t"(res
):"0"(x
));
136 #define cos(x) __FastCos(x)
138 #include "generic_math.h"
142 #if !defined( RAGE128 ) && !defined( AVOID_FPU )
146 typedef struct bes_registers_s
148 /* base address of yuv framebuffer */
152 /* YUV BES registers */
153 uint32_t reg_load_cntl
;
159 uint32_t p1_blank_lines_at_top
;
160 uint32_t p23_blank_lines_at_top
;
161 uint32_t vid_buf_pitch0_value
;
162 uint32_t vid_buf_pitch1_value
;
163 uint32_t p1_x_start_end
;
164 uint32_t p2_x_start_end
;
165 uint32_t p3_x_start_end
;
167 uint32_t vid_buf0_base_adrs
;
168 /* These ones are for auto flip: maybe in the future */
169 uint32_t vid_buf1_base_adrs
;
170 uint32_t vid_buf2_base_adrs
;
171 uint32_t vid_buf3_base_adrs
;
172 uint32_t vid_buf4_base_adrs
;
173 uint32_t vid_buf5_base_adrs
;
175 uint32_t p1_v_accum_init
;
176 uint32_t p1_h_accum_init
;
177 uint32_t p23_v_accum_init
;
178 uint32_t p23_h_accum_init
;
180 uint32_t exclusive_horz
;
181 uint32_t auto_flip_cntl
;
182 uint32_t filter_cntl
;
185 /* Configurable stuff */
192 uint32_t graphics_key_clr
;
193 uint32_t graphics_key_msk
;
196 uint32_t deinterlace_pattern
;
200 typedef struct video_registers_s
209 static bes_registers_t besr
;
214 #define DECLARE_VREG(name) { #name, name, 0 }
216 #define DECLARE_VREG(name) { name, 0 }
219 static video_registers_t vregs
[] =
221 DECLARE_VREG(VIDEOMUX_CNTL
),
222 DECLARE_VREG(VIPPAD_MASK
),
223 DECLARE_VREG(VIPPAD1_A
),
224 DECLARE_VREG(VIPPAD1_EN
),
225 DECLARE_VREG(VIPPAD1_Y
),
226 DECLARE_VREG(OV0_Y_X_START
),
227 DECLARE_VREG(OV0_Y_X_END
),
228 DECLARE_VREG(OV0_PIPELINE_CNTL
),
229 DECLARE_VREG(OV0_EXCLUSIVE_HORZ
),
230 DECLARE_VREG(OV0_EXCLUSIVE_VERT
),
231 DECLARE_VREG(OV0_REG_LOAD_CNTL
),
232 DECLARE_VREG(OV0_SCALE_CNTL
),
233 DECLARE_VREG(OV0_V_INC
),
234 DECLARE_VREG(OV0_P1_V_ACCUM_INIT
),
235 DECLARE_VREG(OV0_P23_V_ACCUM_INIT
),
236 DECLARE_VREG(OV0_P1_BLANK_LINES_AT_TOP
),
237 DECLARE_VREG(OV0_P23_BLANK_LINES_AT_TOP
),
239 DECLARE_VREG(OV0_BASE_ADDR
),
241 DECLARE_VREG(OV0_VID_BUF0_BASE_ADRS
),
242 DECLARE_VREG(OV0_VID_BUF1_BASE_ADRS
),
243 DECLARE_VREG(OV0_VID_BUF2_BASE_ADRS
),
244 DECLARE_VREG(OV0_VID_BUF3_BASE_ADRS
),
245 DECLARE_VREG(OV0_VID_BUF4_BASE_ADRS
),
246 DECLARE_VREG(OV0_VID_BUF5_BASE_ADRS
),
247 DECLARE_VREG(OV0_VID_BUF_PITCH0_VALUE
),
248 DECLARE_VREG(OV0_VID_BUF_PITCH1_VALUE
),
249 DECLARE_VREG(OV0_AUTO_FLIP_CNTL
),
250 DECLARE_VREG(OV0_DEINTERLACE_PATTERN
),
251 DECLARE_VREG(OV0_SUBMIT_HISTORY
),
252 DECLARE_VREG(OV0_H_INC
),
253 DECLARE_VREG(OV0_STEP_BY
),
254 DECLARE_VREG(OV0_P1_H_ACCUM_INIT
),
255 DECLARE_VREG(OV0_P23_H_ACCUM_INIT
),
256 DECLARE_VREG(OV0_P1_X_START_END
),
257 DECLARE_VREG(OV0_P2_X_START_END
),
258 DECLARE_VREG(OV0_P3_X_START_END
),
259 DECLARE_VREG(OV0_FILTER_CNTL
),
260 DECLARE_VREG(OV0_FOUR_TAP_COEF_0
),
261 DECLARE_VREG(OV0_FOUR_TAP_COEF_1
),
262 DECLARE_VREG(OV0_FOUR_TAP_COEF_2
),
263 DECLARE_VREG(OV0_FOUR_TAP_COEF_3
),
264 DECLARE_VREG(OV0_FOUR_TAP_COEF_4
),
265 DECLARE_VREG(OV0_FLAG_CNTL
),
267 DECLARE_VREG(OV0_COLOUR_CNTL
),
269 DECLARE_VREG(OV0_SLICE_CNTL
),
271 DECLARE_VREG(OV0_VID_KEY_CLR
),
272 DECLARE_VREG(OV0_VID_KEY_MSK
),
273 DECLARE_VREG(OV0_GRAPHICS_KEY_CLR
),
274 DECLARE_VREG(OV0_GRAPHICS_KEY_MSK
),
275 DECLARE_VREG(OV0_KEY_CNTL
),
276 DECLARE_VREG(OV0_TEST
),
277 DECLARE_VREG(OV0_LIN_TRANS_A
),
278 DECLARE_VREG(OV0_LIN_TRANS_B
),
279 DECLARE_VREG(OV0_LIN_TRANS_C
),
280 DECLARE_VREG(OV0_LIN_TRANS_D
),
281 DECLARE_VREG(OV0_LIN_TRANS_E
),
282 DECLARE_VREG(OV0_LIN_TRANS_F
),
283 DECLARE_VREG(OV0_GAMMA_0_F
),
284 DECLARE_VREG(OV0_GAMMA_10_1F
),
285 DECLARE_VREG(OV0_GAMMA_20_3F
),
286 DECLARE_VREG(OV0_GAMMA_40_7F
),
287 DECLARE_VREG(OV0_GAMMA_380_3BF
),
288 DECLARE_VREG(OV0_GAMMA_3C0_3FF
),
289 DECLARE_VREG(SUBPIC_CNTL
),
290 DECLARE_VREG(SUBPIC_DEFCOLCON
),
291 DECLARE_VREG(SUBPIC_Y_X_START
),
292 DECLARE_VREG(SUBPIC_Y_X_END
),
293 DECLARE_VREG(SUBPIC_V_INC
),
294 DECLARE_VREG(SUBPIC_H_INC
),
295 DECLARE_VREG(SUBPIC_BUF0_OFFSET
),
296 DECLARE_VREG(SUBPIC_BUF1_OFFSET
),
297 DECLARE_VREG(SUBPIC_LC0_OFFSET
),
298 DECLARE_VREG(SUBPIC_LC1_OFFSET
),
299 DECLARE_VREG(SUBPIC_PITCH
),
300 DECLARE_VREG(SUBPIC_BTN_HLI_COLCON
),
301 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_START
),
302 DECLARE_VREG(SUBPIC_BTN_HLI_Y_X_END
),
303 DECLARE_VREG(SUBPIC_PALETTE_INDEX
),
304 DECLARE_VREG(SUBPIC_PALETTE_DATA
),
305 DECLARE_VREG(SUBPIC_H_ACCUM_INIT
),
306 DECLARE_VREG(SUBPIC_V_ACCUM_INIT
),
307 DECLARE_VREG(IDCT_RUNS
),
308 DECLARE_VREG(IDCT_LEVELS
),
309 DECLARE_VREG(IDCT_AUTH_CONTROL
),
310 DECLARE_VREG(IDCT_AUTH
),
311 DECLARE_VREG(IDCT_CONTROL
)
314 static uint32_t radeon_vid_in_use
= 0;
316 static uint8_t *radeon_mmio_base
= 0;
317 static uint32_t radeon_mem_base
= 0;
318 static int32_t radeon_overlay_off
= 0;
319 static uint32_t radeon_ram_size
= 0;
320 #define PARAM_BUFF_SIZE 4096
321 static uint8_t *radeon_param_buff
= NULL
;
322 static uint32_t radeon_param_buff_size
=0;
323 static uint32_t radeon_param_buff_len
=0; /* real length of buffer */
324 static mga_vid_config_t radeon_config
;
326 static char *fourcc_format_name(int format
)
330 case IMGFMT_RGB8
: return("RGB 8-bit");
331 case IMGFMT_RGB15
: return("RGB 15-bit");
332 case IMGFMT_RGB16
: return("RGB 16-bit");
333 case IMGFMT_RGB24
: return("RGB 24-bit");
334 case IMGFMT_RGB32
: return("RGB 32-bit");
335 case IMGFMT_BGR8
: return("BGR 8-bit");
336 case IMGFMT_BGR15
: return("BGR 15-bit");
337 case IMGFMT_BGR16
: return("BGR 16-bit");
338 case IMGFMT_BGR24
: return("BGR 24-bit");
339 case IMGFMT_BGR32
: return("BGR 32-bit");
340 case IMGFMT_YVU9
: return("Planar YVU9");
341 case IMGFMT_IF09
: return("Planar IF09");
342 case IMGFMT_YV12
: return("Planar YV12");
343 case IMGFMT_I420
: return("Planar I420");
344 case IMGFMT_IYUV
: return("Planar IYUV");
345 case IMGFMT_CLPL
: return("Planar CLPL");
346 case IMGFMT_Y800
: return("Planar Y800");
347 case IMGFMT_Y8
: return("Planar Y8");
348 case IMGFMT_IUYV
: return("Packed IUYV");
349 case IMGFMT_IY41
: return("Packed IY41");
350 case IMGFMT_IYU1
: return("Packed IYU1");
351 case IMGFMT_IYU2
: return("Packed IYU2");
352 case IMGFMT_UYNV
: return("Packed UYNV");
353 case IMGFMT_cyuv
: return("Packed CYUV");
354 case IMGFMT_Y422
: return("Packed Y422");
355 case IMGFMT_YUY2
: return("Packed YUY2");
356 case IMGFMT_YUNV
: return("Packed YUNV");
357 case IMGFMT_UYVY
: return("Packed UYVY");
358 // case IMGFMT_YVYU: return("Packed YVYU");
359 case IMGFMT_Y41P
: return("Packed Y41P");
360 case IMGFMT_Y211
: return("Packed Y211");
361 case IMGFMT_Y41T
: return("Packed Y41T");
362 case IMGFMT_Y42T
: return("Packed Y42T");
363 case IMGFMT_V422
: return("Packed V422");
364 case IMGFMT_V655
: return("Packed V655");
365 case IMGFMT_CLJR
: return("Packed CLJR");
366 case IMGFMT_YUVP
: return("Packed YUVP");
367 case IMGFMT_UYVP
: return("Packed UYVP");
368 case IMGFMT_MPEGPES
: return("Mpeg PES");
378 #define INREG8(addr) readb((radeon_mmio_base)+addr)
379 #define OUTREG8(addr,val) writeb(val, (radeon_mmio_base)+addr)
380 #define INREG(addr) readl((radeon_mmio_base)+addr)
381 #define OUTREG(addr,val) writel(val, (radeon_mmio_base)+addr)
382 #define OUTREGP(addr,val,mask) \
384 unsigned int _tmp = INREG(addr); \
387 OUTREG(addr, _tmp); \
390 static uint32_t radeon_vid_get_dbpp( void )
392 uint32_t dbpp
,retval
;
393 dbpp
= (INREG(CRTC_GEN_CNTL
)>>8)& 0xF;
396 case DST_8BPP
: retval
= 8; break;
397 case DST_15BPP
: retval
= 15; break;
398 case DST_16BPP
: retval
= 16; break;
399 case DST_24BPP
: retval
= 24; break;
400 default: retval
=32; break;
405 static int radeon_is_dbl_scan( void )
407 return (INREG(CRTC_GEN_CNTL
))&CRTC_DBL_SCAN_EN
;
410 static int radeon_is_interlace( void )
412 return (INREG(CRTC_GEN_CNTL
))&CRTC_INTERLACE_EN
;
415 static __inline__
void radeon_engine_flush ( void )
420 OUTREGP(RB2D_DSTCACHE_CTLSTAT
, RB2D_DC_FLUSH_ALL
,
423 for (i
=0; i
< 2000000; i
++) {
424 if (!(INREG(RB2D_DSTCACHE_CTLSTAT
) & RB2D_DC_BUSY
))
430 static __inline__
void _radeon_fifo_wait (int entries
)
434 for (i
=0; i
<2000000; i
++)
435 if ((INREG(RBBM_STATUS
) & 0x7f) >= entries
)
440 static __inline__
void _radeon_engine_idle ( void )
444 /* ensure FIFO is empty before waiting for idle */
445 _radeon_fifo_wait (64);
447 for (i
=0; i
<2000000; i
++) {
448 if (((INREG(RBBM_STATUS
) & GUI_ACTIVE
)) == 0) {
449 radeon_engine_flush ();
455 #define radeon_engine_idle() _radeon_engine_idle()
456 #define radeon_fifo_wait(entries) _radeon_fifo_wait(entries)
459 static void __init
radeon_vid_save_state( void )
462 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
463 vregs
[i
].value
= INREG(vregs
[i
].name
);
466 static void __exit
radeon_vid_restore_state( void )
470 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
471 radeon_engine_idle();
472 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
473 radeon_fifo_wait(15);
474 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
477 OUTREG(vregs
[i
].name
,vregs
[i
].value
);
479 OUTREG(OV0_REG_LOAD_CNTL
, 0);
483 static void radeon_vid_dump_regs( void )
486 printk(RVID_MSG
"*** Begin of OV0 registers dump ***\n");
487 for(i
=0;i
<sizeof(vregs
)/sizeof(video_registers_t
);i
++)
488 printk(RVID_MSG
"%s = %08X\n",vregs
[i
].sname
,INREG(vregs
[i
].name
));
489 printk(RVID_MSG
"*** End of OV0 registers dump ***\n");
494 /* Reference color space transform data */
495 typedef struct tagREF_TRANSFORM
506 /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces */
507 REF_TRANSFORM trans
[2] =
509 {1.1678, 0.0, 1.6007, -0.3929, -0.8154, 2.0232, 0.0}, /* BT.601 */
510 {1.1678, 0.0, 1.7980, -0.2139, -0.5345, 2.1186, 0.0} /* BT.709 */
512 /****************************************************************************
514 * Function: Calculates and sets color space transform from supplied *
515 * reference transform, gamma, brightness, contrast, hue and *
517 * Inputs: bright - brightness *
521 * ref - index to the table of refernce transforms *
523 ****************************************************************************/
525 static void radeon_set_transform(float bright
, float cont
, float sat
,
526 float hue
, unsigned ref
)
528 float OvHueSin
, OvHueCos
;
529 float CAdjLuma
, CAdjOff
;
530 float CAdjRCb
, CAdjRCr
;
531 float CAdjGCb
, CAdjGCr
;
532 float CAdjBCb
, CAdjBCr
;
533 float OvLuma
, OvROff
, OvGOff
, OvBOff
;
540 u32 dwOvLuma
, dwOvROff
, dwOvGOff
, dwOvBOff
;
541 u32 dwOvRCb
, dwOvRCr
;
542 u32 dwOvGCb
, dwOvGCr
;
543 u32 dwOvBCb
, dwOvBCr
;
545 if (ref
>= 2) return;
547 OvHueSin
= sin((double)hue
);
548 OvHueCos
= cos((double)hue
);
550 CAdjLuma
= cont
* trans
[ref
].RefLuma
;
551 CAdjOff
= cont
* trans
[ref
].RefLuma
* bright
* 1023.0;
553 CAdjRCb
= sat
* -OvHueSin
* trans
[ref
].RefRCr
;
554 CAdjRCr
= sat
* OvHueCos
* trans
[ref
].RefRCr
;
555 CAdjGCb
= sat
* (OvHueCos
* trans
[ref
].RefGCb
- OvHueSin
* trans
[ref
].RefGCr
);
556 CAdjGCr
= sat
* (OvHueSin
* trans
[ref
].RefGCb
+ OvHueCos
* trans
[ref
].RefGCr
);
557 CAdjBCb
= sat
* OvHueCos
* trans
[ref
].RefBCb
;
558 CAdjBCr
= sat
* OvHueSin
* trans
[ref
].RefBCb
;
560 #if 0 /* default constants */
561 CAdjLuma
= 1.16455078125;
564 CAdjRCr
= 1.59619140625;
565 CAdjGCb
= -0.39111328125;
567 CAdjBCb
= 2.01708984375;
578 OvLuma
* Loff
- (OvRCb
+ OvRCr
) * Coff
;
580 OvLuma
* Loff
- (OvGCb
+ OvGCr
) * Coff
;
582 OvLuma
* Loff
- (OvBCb
+ OvBCr
) * Coff
;
583 #if 0 /* default constants */
589 dwOvROff
= ((int)(OvROff
* 2.0)) & 0x1fff;
590 dwOvGOff
= (int)(OvGOff
* 2.0) & 0x1fff;
591 dwOvBOff
= (int)(OvBOff
* 2.0) & 0x1fff;
594 dwOvLuma
=(((int)(OvLuma
* 2048.0))&0x7fff)<<17;
595 dwOvRCb
= (((int)(OvRCb
* 2048.0))&0x7fff)<<1;
596 dwOvRCr
= (((int)(OvRCr
* 2048.0))&0x7fff)<<17;
597 dwOvGCb
= (((int)(OvGCb
* 2048.0))&0x7fff)<<1;
598 dwOvGCr
= (((int)(OvGCr
* 2048.0))&0x7fff)<<17;
599 dwOvBCb
= (((int)(OvBCb
* 2048.0))&0x7fff)<<1;
600 dwOvBCr
= (((int)(OvBCr
* 2048.0))&0x7fff)<<17;
604 dwOvLuma
= (((int)(OvLuma
* 256.0))&0x7ff)<<20;
605 dwOvRCb
= (((int)(OvRCb
* 256.0))&0x7ff)<<4;
606 dwOvRCr
= (((int)(OvRCr
* 256.0))&0x7ff)<<20;
607 dwOvGCb
= (((int)(OvGCb
* 256.0))&0x7ff)<<4;
608 dwOvGCr
= (((int)(OvGCr
* 256.0))&0x7ff)<<20;
609 dwOvBCb
= (((int)(OvBCb
* 256.0))&0x7ff)<<4;
610 dwOvBCr
= (((int)(OvBCr
* 256.0))&0x7ff)<<20;
613 OUTREG(OV0_LIN_TRANS_A
, dwOvRCb
| dwOvLuma
);
614 OUTREG(OV0_LIN_TRANS_B
, dwOvROff
| dwOvRCr
);
615 OUTREG(OV0_LIN_TRANS_C
, dwOvGCb
| dwOvLuma
);
616 OUTREG(OV0_LIN_TRANS_D
, dwOvGOff
| dwOvGCr
);
617 OUTREG(OV0_LIN_TRANS_E
, dwOvBCb
| dwOvLuma
);
618 OUTREG(OV0_LIN_TRANS_F
, dwOvBOff
| dwOvBCr
);
623 /* Gamma curve definition */
626 unsigned int gammaReg
;
627 unsigned int gammaSlope
;
628 unsigned int gammaOffset
;
631 /* Recommended gamma curve parameters */
632 GAMMA_SETTINGS r200_def_gamma
[18] =
634 {OV0_GAMMA_0_F
, 0x100, 0x0000},
635 {OV0_GAMMA_10_1F
, 0x100, 0x0020},
636 {OV0_GAMMA_20_3F
, 0x100, 0x0040},
637 {OV0_GAMMA_40_7F
, 0x100, 0x0080},
638 {OV0_GAMMA_80_BF
, 0x100, 0x0100},
639 {OV0_GAMMA_C0_FF
, 0x100, 0x0100},
640 {OV0_GAMMA_100_13F
, 0x100, 0x0200},
641 {OV0_GAMMA_140_17F
, 0x100, 0x0200},
642 {OV0_GAMMA_180_1BF
, 0x100, 0x0300},
643 {OV0_GAMMA_1C0_1FF
, 0x100, 0x0300},
644 {OV0_GAMMA_200_23F
, 0x100, 0x0400},
645 {OV0_GAMMA_240_27F
, 0x100, 0x0400},
646 {OV0_GAMMA_280_2BF
, 0x100, 0x0500},
647 {OV0_GAMMA_2C0_2FF
, 0x100, 0x0500},
648 {OV0_GAMMA_300_33F
, 0x100, 0x0600},
649 {OV0_GAMMA_340_37F
, 0x100, 0x0600},
650 {OV0_GAMMA_380_3BF
, 0x100, 0x0700},
651 {OV0_GAMMA_3C0_3FF
, 0x100, 0x0700}
654 GAMMA_SETTINGS r100_def_gamma
[6] =
656 {OV0_GAMMA_0_F
, 0x100, 0x0000},
657 {OV0_GAMMA_10_1F
, 0x100, 0x0020},
658 {OV0_GAMMA_20_3F
, 0x100, 0x0040},
659 {OV0_GAMMA_40_7F
, 0x100, 0x0080},
660 {OV0_GAMMA_380_3BF
, 0x100, 0x0100},
661 {OV0_GAMMA_3C0_3FF
, 0x100, 0x0100}
664 static void make_default_gamma_correction( void )
668 OUTREG(OV0_LIN_TRANS_A
, 0x12A00000);
669 OUTREG(OV0_LIN_TRANS_B
, 0x199018FE);
670 OUTREG(OV0_LIN_TRANS_C
, 0x12A0F9B0);
671 OUTREG(OV0_LIN_TRANS_D
, 0xF2F0043B);
672 OUTREG(OV0_LIN_TRANS_E
, 0x12A02050);
673 OUTREG(OV0_LIN_TRANS_F
, 0x0000174E);
675 OUTREG(r100_def_gamma
[i
].gammaReg
,
676 (r100_def_gamma
[i
].gammaSlope
<<16) |
677 r100_def_gamma
[i
].gammaOffset
);
681 OUTREG(OV0_LIN_TRANS_A
, 0x12a00000);
682 OUTREG(OV0_LIN_TRANS_B
, 0x1990190e);
683 OUTREG(OV0_LIN_TRANS_C
, 0x12a0f9c0);
684 OUTREG(OV0_LIN_TRANS_D
, 0xf3000442);
685 OUTREG(OV0_LIN_TRANS_E
, 0x12a02040);
686 OUTREG(OV0_LIN_TRANS_F
, 0x175f);
689 Of 18 segments for gamma cure, all segments in R200 are programmable,
690 while only lower 4 and upper 2 segments are programmable in Radeon*/
692 OUTREG(r200_def_gamma
[i
].gammaReg
,
693 (r200_def_gamma
[i
].gammaSlope
<<16) |
694 r200_def_gamma
[i
].gammaOffset
);
700 static void radeon_vid_stop_video( void )
702 radeon_engine_idle();
703 OUTREG(OV0_SCALE_CNTL
, SCALER_SOFT_RESET
);
704 OUTREG(OV0_EXCLUSIVE_HORZ
, 0);
705 OUTREG(OV0_AUTO_FLIP_CNTL
, 0); /* maybe */
706 OUTREG(OV0_FILTER_CNTL
, FILTER_HARDCODED_COEF
);
707 OUTREG(OV0_KEY_CNTL
, GRAPHIC_KEY_FN_NE
);
711 static void radeon_vid_display_video( void )
715 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
716 radeon_engine_idle();
717 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
718 radeon_fifo_wait(15);
719 OUTREG(OV0_AUTO_FLIP_CNTL
,OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD
);
720 OUTREG(OV0_AUTO_FLIP_CNTL
,(INREG(OV0_AUTO_FLIP_CNTL
)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE
));
721 OUTREG(OV0_AUTO_FLIP_CNTL
,(INREG(OV0_AUTO_FLIP_CNTL
)^OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE
));
723 OUTREG(OV0_DEINTERLACE_PATTERN
,besr
.deinterlace_pattern
);
725 OUTREG(OV0_COLOUR_CNTL
, (besr
.brightness
& 0x7f) |
726 (besr
.saturation
<< 8) |
727 (besr
.saturation
<< 16));
732 OUTREG(OV0_GRAPHICS_KEY_MSK
, besr
.graphics_key_msk
);
733 OUTREG(OV0_GRAPHICS_KEY_CLR
, besr
.graphics_key_clr
);
734 OUTREG(OV0_KEY_CNTL
,GRAPHIC_KEY_FN_EQ
|VIDEO_KEY_FN_FALSE
|CMP_MIX_OR
);
738 OUTREG(OV0_GRAPHICS_KEY_MSK
, 0ULL);
739 OUTREG(OV0_GRAPHICS_KEY_CLR
, 0ULL);
740 OUTREG(OV0_KEY_CNTL
,GRAPHIC_KEY_FN_NE
);
743 OUTREG(OV0_H_INC
, besr
.h_inc
);
744 OUTREG(OV0_STEP_BY
, besr
.step_by
);
745 OUTREG(OV0_Y_X_START
, besr
.y_x_start
);
746 OUTREG(OV0_Y_X_END
, besr
.y_x_end
);
747 OUTREG(OV0_V_INC
, besr
.v_inc
);
748 OUTREG(OV0_P1_BLANK_LINES_AT_TOP
, besr
.p1_blank_lines_at_top
);
749 OUTREG(OV0_P23_BLANK_LINES_AT_TOP
, besr
.p23_blank_lines_at_top
);
750 OUTREG(OV0_VID_BUF_PITCH0_VALUE
, besr
.vid_buf_pitch0_value
);
751 OUTREG(OV0_VID_BUF_PITCH1_VALUE
, besr
.vid_buf_pitch1_value
);
752 OUTREG(OV0_P1_X_START_END
, besr
.p1_x_start_end
);
753 OUTREG(OV0_P2_X_START_END
, besr
.p2_x_start_end
);
754 OUTREG(OV0_P3_X_START_END
, besr
.p3_x_start_end
);
756 OUTREG(OV0_BASE_ADDR
, besr
.base_addr
);
758 OUTREG(OV0_VID_BUF0_BASE_ADRS
, besr
.vid_buf0_base_adrs
);
759 OUTREG(OV0_VID_BUF1_BASE_ADRS
, besr
.vid_buf1_base_adrs
);
760 OUTREG(OV0_VID_BUF2_BASE_ADRS
, besr
.vid_buf2_base_adrs
);
762 OUTREG(OV0_VID_BUF3_BASE_ADRS
, besr
.vid_buf3_base_adrs
);
763 OUTREG(OV0_VID_BUF4_BASE_ADRS
, besr
.vid_buf4_base_adrs
);
764 OUTREG(OV0_VID_BUF5_BASE_ADRS
, besr
.vid_buf5_base_adrs
);
765 OUTREG(OV0_P1_V_ACCUM_INIT
, besr
.p1_v_accum_init
);
766 OUTREG(OV0_P1_H_ACCUM_INIT
, besr
.p1_h_accum_init
);
767 OUTREG(OV0_P23_H_ACCUM_INIT
, besr
.p23_h_accum_init
);
768 OUTREG(OV0_P23_V_ACCUM_INIT
, besr
.p23_v_accum_init
);
771 bes_flags
= SCALER_ENABLE
|
773 // SCALER_HORZ_PICK_NEAREST;
775 bes_flags
= SCALER_ENABLE
|
776 SCALER_SMART_SWITCH
|
780 if(besr
.double_buff
) bes_flags
|= SCALER_DOUBLE_BUFFER
;
781 if(besr
.deinterlace_on
) bes_flags
|= SCALER_ADAPTIVE_DEINT
;
783 bes_flags
|= SCALER_BURST_PER_PLANE
;
788 case IMGFMT_BGR15
: bes_flags
|= SCALER_SOURCE_15BPP
; break;
790 case IMGFMT_BGR16
: bes_flags
|= SCALER_SOURCE_16BPP
; break;
792 case IMGFMT_BGR24
: bes_flags
|= SCALER_SOURCE_24BPP
; break;
794 case IMGFMT_BGR32
: bes_flags
|= SCALER_SOURCE_32BPP
; break;
797 case IMGFMT_YVU9
: bes_flags
|= SCALER_SOURCE_YUV9
; break;
801 case IMGFMT_YV12
: bes_flags
|= SCALER_SOURCE_YUV12
;
804 case IMGFMT_UYVY
: bes_flags
|= SCALER_SOURCE_YVYU422
; break;
806 default: bes_flags
|= SCALER_SOURCE_VYUY422
; break;
808 OUTREG(OV0_SCALE_CNTL
, bes_flags
);
809 OUTREG(OV0_REG_LOAD_CNTL
, 0);
811 radeon_vid_dump_regs();
815 void radeon_vid_set_color_key(int ckey_on
, uint8_t R
, uint8_t G
, uint8_t B
)
817 besr
.ckey_on
= ckey_on
;
818 besr
.graphics_key_msk
=(1ULL<<radeon_vid_get_dbpp()) - 1;
819 besr
.graphics_key_clr
=(R
<<16)|(G
<<8)|(B
)|(0x00 << 24);
826 static int radeon_vid_init_video( mga_vid_config_t
*config
)
828 uint32_t tmp
,src_w
,src_h
,pitch
,h_inc
,step_by
,left
,leftUV
,top
;
830 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"
831 ,(uint32_t)config
->version
832 ,(uint32_t)config
->format
833 ,(uint32_t)config
->card_type
834 ,(uint32_t)config
->ram_size
835 ,(uint32_t)config
->src_width
836 ,(uint32_t)config
->src_height
837 ,(uint32_t)config
->x_org
838 ,(uint32_t)config
->y_org
839 ,(uint32_t)config
->dest_width
840 ,(uint32_t)config
->dest_height
841 ,(uint32_t)config
->frame_size
842 ,(uint32_t)config
->num_frames
);
843 radeon_vid_stop_video();
844 left
= XXX_SRC_X
<< 16;
845 top
= XXX_SRC_Y
<< 16;
846 src_h
= config
->src_height
;
847 src_w
= config
->src_width
;
848 switch(config
->format
)
870 printk(RVID_MSG
"Unsupported pixel format: 0x%X\n",config
->format
);
874 if(config
->format
== IMGFMT_YV12
||
875 config
->format
== IMGFMT_I420
||
876 config
->format
== IMGFMT_IYUV
) is_420
= 1;
877 switch(config
->format
)
885 case IMGFMT_I420
: pitch
= (src_w
+ 31) & ~31; break;
893 case IMGFMT_BGR16
: pitch
= ((src_w
*2) + 15) & ~15; break;
895 case IMGFMT_BGR24
: pitch
= ((src_w
*3) + 15) & ~15; break;
897 case IMGFMT_BGR32
: pitch
= ((src_w
*4) + 15) & ~15; break;
899 if(radeon_is_dbl_scan()) config
->dest_height
*= 2;
901 if(radeon_is_interlace()) config
->dest_height
/= 2;
902 besr
.dest_bpp
= radeon_vid_get_dbpp();
903 besr
.fourcc
= config
->format
;
904 besr
.v_inc
= (src_h
<< 20) / config
->dest_height
;
905 h_inc
= (src_w
<< 12) / config
->dest_width
;
908 while(h_inc
>= (2 << 12)) {
913 /* keep everything in 16.16 */
914 besr
.base_addr
= radeon_mem_base
;
917 uint32_t d1line
,d2line
,d3line
;
919 d2line
= src_h
*pitch
+(d1line
>>1);
920 d3line
= d2line
+((src_h
*pitch
)>>2);
921 d1line
+= (left
>> 16) & ~15;
922 d2line
+= (left
>> 17) & ~15;
923 d3line
+= (left
>> 17) & ~15;
924 besr
.vid_buf0_base_adrs
=((radeon_overlay_off
+d1line
)&VIF_BUF0_BASE_ADRS_MASK
);
925 besr
.vid_buf1_base_adrs
=((radeon_overlay_off
+d2line
)&VIF_BUF1_BASE_ADRS_MASK
)|VIF_BUF1_PITCH_SEL
;
926 besr
.vid_buf2_base_adrs
=((radeon_overlay_off
+d3line
)&VIF_BUF2_BASE_ADRS_MASK
)|VIF_BUF2_PITCH_SEL
;
927 if(besr
.fourcc
== IMGFMT_I420
|| besr
.fourcc
== IMGFMT_IYUV
)
930 tmp
= besr
.vid_buf1_base_adrs
;
931 besr
.vid_buf1_base_adrs
= besr
.vid_buf2_base_adrs
;
932 besr
.vid_buf2_base_adrs
= tmp
;
937 besr
.vid_buf0_base_adrs
= radeon_overlay_off
;
938 besr
.vid_buf0_base_adrs
+= ((left
& ~7) << 1)&VIF_BUF0_BASE_ADRS_MASK
;
939 besr
.vid_buf1_base_adrs
= besr
.vid_buf0_base_adrs
;
940 besr
.vid_buf2_base_adrs
= besr
.vid_buf0_base_adrs
;
942 besr
.vid_buf3_base_adrs
= besr
.vid_buf0_base_adrs
+config
->frame_size
;
943 besr
.vid_buf4_base_adrs
= besr
.vid_buf1_base_adrs
+config
->frame_size
;
944 besr
.vid_buf5_base_adrs
= besr
.vid_buf2_base_adrs
+config
->frame_size
;
946 tmp
= (left
& 0x0003ffff) + 0x00028000 + (h_inc
<< 3);
947 besr
.p1_h_accum_init
= ((tmp
<< 4) & 0x000f8000) |
948 ((tmp
<< 12) & 0xf0000000);
950 tmp
= ((left
>> 1) & 0x0001ffff) + 0x00028000 + (h_inc
<< 2);
951 besr
.p23_h_accum_init
= ((tmp
<< 4) & 0x000f8000) |
952 ((tmp
<< 12) & 0x70000000);
953 tmp
= (top
& 0x0000ffff) + 0x00018000;
954 besr
.p1_v_accum_init
= ((tmp
<< 4) & OV0_P1_V_ACCUM_INIT_MASK
)
955 |(OV0_P1_MAX_LN_IN_PER_LN_OUT
& 1);
957 tmp
= ((top
>> 1) & 0x0000ffff) + 0x00018000;
958 besr
.p23_v_accum_init
= is_420
? ((tmp
<< 4) & OV0_P23_V_ACCUM_INIT_MASK
)
959 |(OV0_P23_MAX_LN_IN_PER_LN_OUT
& 1) : 0;
961 leftUV
= (left
>> 17) & 15;
962 left
= (left
>> 16) & 15;
963 besr
.h_inc
= h_inc
| ((h_inc
>> 1) << 16);
964 besr
.step_by
= step_by
| (step_by
<< 8);
965 besr
.y_x_start
= (config
->x_org
+X_ADJUST
) | (config
->y_org
<< 16);
966 besr
.y_x_end
= (config
->x_org
+ config
->dest_width
+X_ADJUST
) | ((config
->y_org
+ config
->dest_height
) << 16);
967 besr
.p1_blank_lines_at_top
= P1_BLNK_LN_AT_TOP_M1_MASK
|((src_h
-1)<<16);
970 src_h
= (src_h
+ 1) >> 1;
971 besr
.p23_blank_lines_at_top
= P23_BLNK_LN_AT_TOP_M1_MASK
|((src_h
-1)<<16);
973 else besr
.p23_blank_lines_at_top
= 0;
974 besr
.vid_buf_pitch0_value
= pitch
;
975 besr
.vid_buf_pitch1_value
= is_420
? pitch
>>1 : pitch
;
976 besr
.p1_x_start_end
= (src_w
+left
-1)|(left
<<16);
978 besr
.p2_x_start_end
= (src_w
+left
-1)|(leftUV
<<16);
979 besr
.p3_x_start_end
= besr
.p2_x_start_end
;
983 static void radeon_vid_frame_sel(int frame
)
985 uint32_t off0
,off1
,off2
;
986 if(!besr
.double_buff
) return;
989 off0
= besr
.vid_buf3_base_adrs
;
990 off1
= besr
.vid_buf4_base_adrs
;
991 off2
= besr
.vid_buf5_base_adrs
;
995 off0
= besr
.vid_buf0_base_adrs
;
996 off1
= besr
.vid_buf1_base_adrs
;
997 off2
= besr
.vid_buf2_base_adrs
;
999 OUTREG(OV0_REG_LOAD_CNTL
, REG_LD_CTL_LOCK
);
1000 while(!(INREG(OV0_REG_LOAD_CNTL
)®_LD_CTL_LOCK_READBACK
));
1001 OUTREG(OV0_VID_BUF0_BASE_ADRS
, off0
);
1002 OUTREG(OV0_VID_BUF1_BASE_ADRS
, off1
);
1003 OUTREG(OV0_VID_BUF2_BASE_ADRS
, off2
);
1004 OUTREG(OV0_REG_LOAD_CNTL
, 0);
1007 static void radeon_vid_make_default(void)
1010 OUTREG(OV0_COLOUR_CNTL
,0x00101000UL
); /* Default brihgtness and saturation for Rage128 */
1012 make_default_gamma_correction();
1014 besr
.deinterlace_pattern
= 0x900AAAAA;
1015 OUTREG(OV0_DEINTERLACE_PATTERN
,besr
.deinterlace_pattern
);
1016 besr
.deinterlace_on
=1;
1021 static void radeon_vid_preset(void)
1025 tmp
= INREG(OV0_COLOUR_CNTL
);
1026 besr
.saturation
= (tmp
>>8)&0x1f;
1027 besr
.brightness
= tmp
& 0x7f;
1029 besr
.graphics_key_clr
= INREG(OV0_GRAPHICS_KEY_CLR
);
1030 besr
.deinterlace_pattern
= INREG(OV0_DEINTERLACE_PATTERN
);
1033 static int video_on
= 0;
1035 static int radeon_vid_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
1041 case MGA_VID_CONFIG
:
1042 RTRACE(RVID_MSG
"radeon_mmio_base = %p\n",radeon_mmio_base
);
1043 RTRACE(RVID_MSG
"radeon_mem_base = %08x\n",radeon_mem_base
);
1044 RTRACE(RVID_MSG
"Received configuration\n");
1046 if(copy_from_user(&radeon_config
,(mga_vid_config_t
*) arg
,sizeof(mga_vid_config_t
)))
1048 printk(RVID_MSG
"failed copy from userspace\n");
1051 if(radeon_config
.version
!= MGA_VID_VERSION
){
1052 printk(RVID_MSG
"incompatible version! driver: %X requested: %X\n",MGA_VID_VERSION
,radeon_config
.version
);
1056 if(radeon_config
.frame_size
==0 || radeon_config
.frame_size
>1024*768*2){
1057 printk(RVID_MSG
"illegal frame_size: %d\n",radeon_config
.frame_size
);
1061 if(radeon_config
.num_frames
<1){
1062 printk(RVID_MSG
"illegal num_frames: %d\n",radeon_config
.num_frames
);
1065 if(radeon_config
.num_frames
==1) besr
.double_buff
=0;
1066 if(!besr
.double_buff
) radeon_config
.num_frames
=1;
1067 else radeon_config
.num_frames
=2;
1068 radeon_config
.card_type
= 0;
1069 radeon_config
.ram_size
= radeon_ram_size
;
1070 radeon_overlay_off
= radeon_ram_size
*0x100000 - radeon_config
.frame_size
*radeon_config
.num_frames
;
1071 radeon_overlay_off
&= 0xffff0000;
1072 if(radeon_overlay_off
< 0){
1073 printk(RVID_MSG
"not enough video memory. Need: %u has: %u\n",radeon_config
.frame_size
*radeon_config
.num_frames
,radeon_ram_size
*0x100000);
1076 RTRACE(RVID_MSG
"using video overlay at offset %08X\n",radeon_overlay_off
);
1077 if (copy_to_user((mga_vid_config_t
*) arg
, &radeon_config
, sizeof(mga_vid_config_t
)))
1079 printk(RVID_MSG
"failed copy to userspace\n");
1082 radeon_vid_set_color_key(radeon_config
.colkey_on
,
1083 radeon_config
.colkey_red
,
1084 radeon_config
.colkey_green
,
1085 radeon_config
.colkey_blue
);
1086 if(swap_fourcc
) radeon_config
.format
= swab32(radeon_config
.format
);
1087 printk(RVID_MSG
"configuring for '%s' fourcc\n",fourcc_format_name(radeon_config
.format
));
1088 return radeon_vid_init_video(&radeon_config
);
1092 RTRACE(RVID_MSG
"Video ON (ioctl)\n");
1093 radeon_vid_display_video();
1098 RTRACE(RVID_MSG
"Video OFF (ioctl)\n");
1099 if(video_on
) radeon_vid_stop_video();
1104 if(copy_from_user(&frame
,(int *) arg
,sizeof(int)))
1106 printk(RVID_MSG
"FSEL failed copy from userspace\n");
1109 radeon_vid_frame_sel(frame
);
1113 printk(RVID_MSG
"Invalid ioctl\n");
1120 struct ati_card_id_s
1123 const char name
[17];
1126 const struct ati_card_id_s ati_card_ids
[]=
1130 This driver should be compatible with Rage128 (pro) chips.
1131 (include adaptive deinterlacing!!!).
1132 Moreover: the same logic can be used with Mach64 chips.
1133 (I mean: mach64xx, 3d rage, 3d rage IIc, 3D rage pro, 3d rage mobility).
1134 but they are incompatible by i/o ports. So if enthusiasts will want
1135 then they can redefine OUTREG and INREG macros and redefine OV0_*
1136 constants. Also it seems that mach64 chips supports only: YUY2, YV12, UYVY
1137 fourccs (422 and 420 formats only).
1139 /* Rage128 Pro GL */
1140 { PCI_DEVICE_ID_ATI_Rage128_PA
, "R128Pro PA" },
1141 { PCI_DEVICE_ID_ATI_Rage128_PB
, "R128Pro PB" },
1142 { PCI_DEVICE_ID_ATI_Rage128_PC
, "R128Pro PC" },
1143 { PCI_DEVICE_ID_ATI_Rage128_PD
, "R128Pro PD" },
1144 { PCI_DEVICE_ID_ATI_Rage128_PE
, "R128Pro PE" },
1145 { PCI_DEVICE_ID_ATI_RAGE128_PF
, "R128Pro PF" },
1146 /* Rage128 Pro VR */
1147 { PCI_DEVICE_ID_ATI_RAGE128_PG
, "R128Pro PG" },
1148 { PCI_DEVICE_ID_ATI_RAGE128_PH
, "R128Pro PH" },
1149 { PCI_DEVICE_ID_ATI_RAGE128_PI
, "R128Pro PI" },
1150 { PCI_DEVICE_ID_ATI_RAGE128_PJ
, "R128Pro PJ" },
1151 { PCI_DEVICE_ID_ATI_RAGE128_PK
, "R128Pro PK" },
1152 { PCI_DEVICE_ID_ATI_RAGE128_PL
, "R128Pro PL" },
1153 { PCI_DEVICE_ID_ATI_RAGE128_PM
, "R128Pro PM" },
1154 { PCI_DEVICE_ID_ATI_RAGE128_PN
, "R128Pro PN" },
1155 { PCI_DEVICE_ID_ATI_RAGE128_PO
, "R128Pro PO" },
1156 { PCI_DEVICE_ID_ATI_RAGE128_PP
, "R128Pro PP" },
1157 { PCI_DEVICE_ID_ATI_RAGE128_PQ
, "R128Pro PQ" },
1158 { PCI_DEVICE_ID_ATI_RAGE128_PR
, "R128Pro PR" },
1159 { PCI_DEVICE_ID_ATI_RAGE128_TR
, "R128Pro TR" },
1160 { PCI_DEVICE_ID_ATI_RAGE128_PS
, "R128Pro PS" },
1161 { PCI_DEVICE_ID_ATI_RAGE128_PT
, "R128Pro PT" },
1162 { PCI_DEVICE_ID_ATI_RAGE128_PU
, "R128Pro PU" },
1163 { PCI_DEVICE_ID_ATI_RAGE128_PV
, "R128Pro PV" },
1164 { PCI_DEVICE_ID_ATI_RAGE128_PW
, "R128Pro PW" },
1165 { PCI_DEVICE_ID_ATI_RAGE128_PX
, "R128Pro PX" },
1167 { PCI_DEVICE_ID_ATI_RAGE128_RE
, "R128 RE" },
1168 { PCI_DEVICE_ID_ATI_RAGE128_RF
, "R128 RF" },
1169 { PCI_DEVICE_ID_ATI_RAGE128_RG
, "R128 RG" },
1170 { PCI_DEVICE_ID_ATI_RAGE128_RH
, "R128 RH" },
1171 { PCI_DEVICE_ID_ATI_RAGE128_RI
, "R128 RI" },
1173 { PCI_DEVICE_ID_ATI_RAGE128_RK
, "R128 RK" },
1174 { PCI_DEVICE_ID_ATI_RAGE128_RL
, "R128 RL" },
1175 { PCI_DEVICE_ID_ATI_RAGE128_RM
, "R128 RM" },
1176 { PCI_DEVICE_ID_ATI_RAGE128_RN
, "R128 RN" },
1177 { PCI_DEVICE_ID_ATI_RAGE128_RO
, "R128 RO" },
1179 { PCI_DEVICE_ID_ATI_RAGE128_LE
, "R128 M3 LE" },
1180 { PCI_DEVICE_ID_ATI_RAGE128_LF
, "R128 M3 LF" },
1181 /* Rage128 Pro Ultra */
1182 { PCI_DEVICE_ID_ATI_RAGE128_U1
, "R128Pro U1" },
1183 { PCI_DEVICE_ID_ATI_RAGE128_U2
, "R128Pro U2" },
1184 { PCI_DEVICE_ID_ATI_RAGE128_U3
, "R128Pro U3" }
1186 /* Radeons (indeed: Rage 256 Pro ;) */
1187 { PCI_DEVICE_ID_RADEON_QD
, "Radeon QD " },
1188 { PCI_DEVICE_ID_RADEON_QE
, "Radeon QE " },
1189 { PCI_DEVICE_ID_RADEON_QF
, "Radeon QF " },
1190 { PCI_DEVICE_ID_RADEON_QG
, "Radeon QG " },
1191 { PCI_DEVICE_ID_RADEON_QY
, "Radeon VE QY " },
1192 { PCI_DEVICE_ID_RADEON_QZ
, "Radeon VE QZ " },
1193 { PCI_DEVICE_ID_RADEON_LY
, "Radeon M6 LY " },
1194 { PCI_DEVICE_ID_RADEON_LZ
, "Radeon M6 LZ " },
1195 { PCI_DEVICE_ID_RADEON_LW
, "Radeon M7 LW " },
1196 { PCI_DEVICE_ID_R200_QL
, "Radeon2 8500 QL " },
1197 { PCI_DEVICE_ID_R200_BB
, "Radeon2 8500 AIW" },
1198 { PCI_DEVICE_ID_RV200_QW
, "Radeon2 7500 QW " }
1202 static int detected_chip
;
1204 static int __init
radeon_vid_config_card(void)
1206 struct pci_dev
*dev
= NULL
;
1209 for(i
=0;i
<sizeof(ati_card_ids
)/sizeof(struct ati_card_id_s
);i
++)
1210 if((dev
=pci_find_device(PCI_VENDOR_ID_ATI
, ati_card_ids
[i
].id
, NULL
)))
1214 printk(RVID_MSG
"No supported cards found\n");
1218 radeon_mmio_base
= ioremap_nocache(pci_resource_start (dev
, 2),RADEON_REGSIZE
);
1219 radeon_mem_base
= dev
->resource
[0].start
;
1221 RTRACE(RVID_MSG
"MMIO at 0x%p\n", radeon_mmio_base
);
1222 RTRACE(RVID_MSG
"Frame Buffer at 0x%08x\n", radeon_mem_base
);
1224 /* video memory size */
1225 radeon_ram_size
= INREG(CONFIG_MEMSIZE
);
1227 /* mem size is bits [28:0], mask off the rest. Range: from 1Mb up to 512 Mb */
1228 radeon_ram_size
&= CONFIG_MEMSIZE_MASK
;
1229 radeon_ram_size
/= 0x100000;
1231 printk(RVID_MSG
"Found %s (%uMb memory)\n",ati_card_ids
[i
].name
,radeon_ram_size
);
1233 if(ati_card_ids
[i
].id
== PCI_DEVICE_ID_R200_QL
||
1234 ati_card_ids
[i
].id
== PCI_DEVICE_ID_R200_BB
||
1235 ati_card_ids
[i
].id
== PCI_DEVICE_ID_RV200_QW
) IsR200
= 1;
1240 #define PARAM_BRIGHTNESS "brightness="
1241 #define PARAM_SATURATION "saturation="
1242 #define PARAM_CONTRAST "contrast="
1243 #define PARAM_HUE "hue="
1244 #define PARAM_DOUBLE_BUFF "double_buff="
1245 #define PARAM_DEINTERLACE "deinterlace="
1246 #define PARAM_DEINTERLACE_PATTERN "deinterlace_pattern="
1248 static int ovBrightness
=0, ovSaturation
=0, ovContrast
=0, ovHue
=0, ov_trans_idx
=0;
1251 static void radeon_param_buff_fill( void )
1253 unsigned len
,saturation
;
1255 brightness
= besr
.brightness
& 0x7f;
1256 /* FIXME: It's probably x86 specific convertion. But it doesn't matter
1257 for general logic - only for printing value */
1258 if(brightness
> 63) brightness
= (((~besr
.brightness
) & 0x3f)+1) * (-1);
1259 saturation
= besr
.saturation
;
1261 len
+= sprintf(&radeon_param_buff
[len
],"Interface version: %04X\nDriver version: %s\n",MGA_VID_VERSION
,RADEON_VID_VERSION
);
1262 len
+= sprintf(&radeon_param_buff
[len
],"Chip: %s\n",ati_card_ids
[detected_chip
].name
);
1263 len
+= sprintf(&radeon_param_buff
[len
],"Memory: %x:%x\n",radeon_mem_base
,radeon_ram_size
*0x100000);
1264 len
+= sprintf(&radeon_param_buff
[len
],"MMIO: %p\n",radeon_mmio_base
);
1265 len
+= sprintf(&radeon_param_buff
[len
],"Overlay offset: %x\n",radeon_overlay_off
);
1267 len
+= sprintf(&radeon_param_buff
[len
],"Tune MTRR: %s\n",mtrr
?"on":"off");
1269 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
);
1270 len
+= sprintf(&radeon_param_buff
[len
],"Swapped fourcc: %s\n",swap_fourcc
?"on":"off");
1271 len
+= sprintf(&radeon_param_buff
[len
],"Last BPP: %u\n",besr
.dest_bpp
);
1272 len
+= sprintf(&radeon_param_buff
[len
],"Last fourcc: %s\n\n",fourcc_format_name(besr
.fourcc
));
1273 len
+= sprintf(&radeon_param_buff
[len
],"Configurable stuff:\n");
1274 len
+= sprintf(&radeon_param_buff
[len
],"~~~~~~~~~~~~~~~~~~~\n");
1275 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DOUBLE_BUFF
"%s\n",besr
.double_buff
?"on":"off");
1277 len
+= sprintf(&radeon_param_buff
[len
],PARAM_BRIGHTNESS
"%i\n",(int)brightness
);
1278 len
+= sprintf(&radeon_param_buff
[len
],PARAM_SATURATION
"%u\n",saturation
);
1281 len
+= sprintf(&radeon_param_buff
[len
],PARAM_BRIGHTNESS
"%i\n",ovBrightness
);
1282 len
+= sprintf(&radeon_param_buff
[len
],PARAM_SATURATION
"%i\n",ovSaturation
);
1283 len
+= sprintf(&radeon_param_buff
[len
],PARAM_CONTRAST
"%i\n",ovContrast
);
1284 len
+= sprintf(&radeon_param_buff
[len
],PARAM_HUE
"%i\n",ovHue
);
1287 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DEINTERLACE
"%s\n",besr
.deinterlace_on
?"on":"off");
1288 len
+= sprintf(&radeon_param_buff
[len
],PARAM_DEINTERLACE_PATTERN
"%X\n",besr
.deinterlace_pattern
);
1289 radeon_param_buff_len
= len
;
1292 static ssize_t
radeon_vid_read(struct file
*file
, char *buf
, size_t count
, loff_t
*ppos
)
1295 if(!radeon_param_buff
) return -ESPIPE
;
1296 if(!(*ppos
)) radeon_param_buff_fill();
1297 if(*ppos
>= radeon_param_buff_len
) return 0;
1298 size
= min(count
,radeon_param_buff_len
-(uint32_t)(*ppos
));
1299 memcpy(buf
,radeon_param_buff
,size
);
1304 #define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
1305 #define RTFBrightness(a) (((a)*1.0)/2000.0)
1306 #define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
1307 #define RTFHue(a) (((a)*3.1416)/1000.0)
1308 #define RadeonSetParm(a,b,c,d) if((b)>=(c)&&(b)<=(d)) { (a)=(b);\
1309 radeon_set_transform(RTFBrightness(ovBrightness),RTFContrast(ovContrast)\
1310 ,RTFSaturation(ovSaturation),RTFHue(ovHue),ov_trans_idx); }
1313 static ssize_t
radeon_vid_write(struct file
*file
, const char *buf
, size_t count
, loff_t
*ppos
)
1316 if(memcmp(buf
,PARAM_BRIGHTNESS
,min(count
,strlen(PARAM_BRIGHTNESS
))) == 0)
1319 brightness
=simple_strtol(&buf
[strlen(PARAM_BRIGHTNESS
)],NULL
,10);
1320 if(brightness
>= -64 && brightness
<= 63)
1322 besr
.brightness
= brightness
;
1323 OUTREG(OV0_COLOUR_CNTL
, (brightness
& 0x7f) |
1324 (besr
.saturation
<< 8) |
1325 (besr
.saturation
<< 16));
1329 if(memcmp(buf
,PARAM_SATURATION
,min(count
,strlen(PARAM_SATURATION
))) == 0)
1332 saturation
=simple_strtol(&buf
[strlen(PARAM_SATURATION
)],NULL
,10);
1333 if(saturation
>= 0 && saturation
<= 31)
1334 OUTREG(OV0_COLOUR_CNTL
, (besr
.brightness
& 0x7f) |
1336 (saturation
<< 16));
1341 if(memcmp(buf
,PARAM_BRIGHTNESS
,min(count
,strlen(PARAM_BRIGHTNESS
))) == 0)
1344 tmp
=simple_strtol(&buf
[strlen(PARAM_BRIGHTNESS
)],NULL
,10);
1345 RadeonSetParm(ovBrightness
,tmp
,-1000,1000);
1348 if(memcmp(buf
,PARAM_SATURATION
,min(count
,strlen(PARAM_SATURATION
))) == 0)
1351 tmp
=simple_strtol(&buf
[strlen(PARAM_SATURATION
)],NULL
,10);
1352 RadeonSetParm(ovSaturation
,tmp
,-1000,1000);
1355 if(memcmp(buf
,PARAM_CONTRAST
,min(count
,strlen(PARAM_CONTRAST
))) == 0)
1358 tmp
=simple_strtol(&buf
[strlen(PARAM_CONTRAST
)],NULL
,10);
1359 RadeonSetParm(ovContrast
,tmp
,-1000,1000);
1362 if(memcmp(buf
,PARAM_HUE
,min(count
,strlen(PARAM_HUE
))) == 0)
1365 tmp
=simple_strtol(&buf
[strlen(PARAM_HUE
)],NULL
,10);
1366 RadeonSetParm(ovHue
,tmp
,-1000,1000);
1371 if(memcmp(buf
,PARAM_DOUBLE_BUFF
,min(count
,strlen(PARAM_DOUBLE_BUFF
))) == 0)
1373 if(memcmp(&buf
[strlen(PARAM_DOUBLE_BUFF
)],"on",2) == 0) besr
.double_buff
= 1;
1374 else besr
.double_buff
= 0;
1377 if(memcmp(buf
,PARAM_DEINTERLACE
,min(count
,strlen(PARAM_DEINTERLACE
))) == 0)
1379 if(memcmp(&buf
[strlen(PARAM_DEINTERLACE
)],"on",2) == 0) besr
.deinterlace_on
= 1;
1380 else besr
.deinterlace_on
= 0;
1383 if(memcmp(buf
,PARAM_DEINTERLACE_PATTERN
,min(count
,strlen(PARAM_DEINTERLACE_PATTERN
))) == 0)
1386 dpat
=simple_strtol(&buf
[strlen(PARAM_DEINTERLACE_PATTERN
)],NULL
,16);
1387 OUTREG(OV0_DEINTERLACE_PATTERN
, dpat
);
1390 radeon_vid_preset();
1394 static int radeon_vid_mmap(struct file
*file
, struct vm_area_struct
*vma
)
1397 RTRACE(RVID_MSG
"mapping video memory into userspace\n");
1398 if(remap_page_range(vma
->vm_start
, radeon_mem_base
+ radeon_overlay_off
,
1399 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
))
1401 printk(RVID_MSG
"error mapping video memory\n");
1408 static int radeon_vid_release(struct inode
*inode
, struct file
*file
)
1410 radeon_vid_in_use
= 0;
1411 radeon_vid_stop_video();
1417 static long long radeon_vid_lseek(struct file
*file
, long long offset
, int origin
)
1422 static int radeon_vid_open(struct inode
*inode
, struct file
*file
)
1424 int minor
= MINOR(inode
->i_rdev
);
1429 if(radeon_vid_in_use
== 1)
1432 radeon_vid_in_use
= 1;
1437 #if LINUX_VERSION_CODE >= 0x020400
1438 static struct file_operations radeon_vid_fops
=
1440 llseek
: radeon_vid_lseek
,
1441 read
: radeon_vid_read
,
1442 write
: radeon_vid_write
,
1447 ioctl
: radeon_vid_ioctl
,
1448 mmap
: radeon_vid_mmap
,
1449 open
: radeon_vid_open
,
1453 release
: radeon_vid_release
1465 static struct file_operations radeon_vid_fops
=
1481 * Main Initialization Function
1484 static int __init
radeon_vid_initialize(void)
1486 radeon_vid_in_use
= 0;
1488 printk(RVID_MSG
"Rage128/Rage128Pro video overlay driver v"RADEON_VID_VERSION
" (C) Nick Kurshev\n");
1490 printk(RVID_MSG
"Radeon video overlay driver v"RADEON_VID_VERSION
" (C) Nick Kurshev\n");
1492 if(register_chrdev(RADEON_VID_MAJOR
, "radeon_vid", &radeon_vid_fops
))
1494 printk(RVID_MSG
"unable to get major: %d\n", RADEON_VID_MAJOR
);
1498 if (!radeon_vid_config_card())
1500 printk(RVID_MSG
"can't configure this card\n");
1501 unregister_chrdev(RADEON_VID_MAJOR
, "radeon_vid");
1504 radeon_param_buff
= kmalloc(PARAM_BUFF_SIZE
,GFP_KERNEL
);
1505 if(radeon_param_buff
) radeon_param_buff_size
= PARAM_BUFF_SIZE
;
1507 radeon_vid_save_state();
1509 radeon_vid_make_default();
1510 radeon_vid_preset();
1513 smtrr
.vram
= mtrr_add(radeon_mem_base
,
1514 radeon_ram_size
*0x100000, MTRR_TYPE_WRCOMB
, 1);
1515 smtrr
.vram_valid
= 1;
1516 /* let there be speed */
1517 printk(RVID_MSG
"MTRR set to ON\n");
1519 #endif /* CONFIG_MTRR */
1523 int __init
init_module(void)
1525 return radeon_vid_initialize();
1528 void __exit
cleanup_module(void)
1531 radeon_vid_restore_state();
1533 if(radeon_mmio_base
)
1534 iounmap(radeon_mmio_base
);
1535 kfree(radeon_param_buff
);
1536 RTRACE(RVID_MSG
"Cleaning up module\n");
1537 unregister_chrdev(RADEON_VID_MAJOR
, "radeon_vid");
1539 if (smtrr
.vram_valid
)
1540 mtrr_del(smtrr
.vram
, radeon_mem_base
,
1541 radeon_ram_size
*0x100000);
1542 #endif /* CONFIG_MTRR */