2 * VIDIX driver for SiS chipsets.
3 * Based on SiS Xv driver
5 * Copyright (C) 2003 Jake Page, Sugar Media
6 * Copyright 2002-2003 by Thomas Winischhofer, Vienna, Austria
7 * 2003/10/08 integrated into mplayer/vidix architecture -- Alex Beregszaszi
9 * This file is part of MPlayer.
11 * MPlayer is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * MPlayer is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 #include "pci_names.h"
44 /** Random defines **/
46 #define WATCHDOG_DELAY 500000 /* Watchdog counter for retrace waiting */
47 #define IMAGE_MIN_WIDTH 32 /* Min and max source image sizes */
48 #define IMAGE_MIN_HEIGHT 24
49 #define IMAGE_MAX_WIDTH 720
50 #define IMAGE_MAX_HEIGHT 576
51 #define IMAGE_MAX_WIDTH_M650 1920
52 #define IMAGE_MAX_HEIGHT_M650 1080
54 #define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */
55 #define OVERLAY_MIN_HEIGHT 24
57 #define DISPMODE_SINGLE1 0x1 /* TW: CRT1 only */
58 #define DISPMODE_SINGLE2 0x2 /* TW: CRT2 only */
59 #define DISPMODE_MIRROR 0x4 /* TW: CRT1 + CRT2 MIRROR */
61 #define VMODE_INTERLACED 0x1
62 #define VMODE_DOUBLESCAN 0x2
91 uint8_t contrastFactor
;
95 uint8_t(*VBlankActiveFunc
) ();
97 uint16_t SCREENheight
;
99 } SISOverlayRec
, *SISOverlayPtr
;
102 /** static variable definitions **/
103 static int sis_probed
= 0;
104 static pciinfo_t pci_info
;
105 unsigned int sis_verbose
= 0;
107 static void *sis_mem_base
;
108 /* static void *sis_reg_base; */
109 unsigned short sis_iobase
;
111 unsigned int sis_vga_engine
= UNKNOWN_VGA
;
112 static unsigned int sis_displaymode
= DISPMODE_SINGLE1
;
113 static unsigned int sis_has_two_overlays
= 0;
114 static unsigned int sis_bridge_is_slave
= 0;
115 static unsigned int sis_shift_value
= 1;
116 static unsigned int sis_vmode
= 0;
117 unsigned int sis_vbflags
= DISPTYPE_DISP1
;
118 unsigned int sis_overlay_on_crt1
= 1;
119 int sis_crt1_off
= -1;
120 unsigned int sis_detected_crt2_devices
;
121 unsigned int sis_force_crt2_type
= CRT2_DEFAULT
;
122 int sis_device_id
= -1;
124 static int sis_format
;
125 static int sis_Yoff
= 0;
126 static int sis_Voff
= 0;
127 static int sis_Uoff
= 0;
128 static int sis_screen_width
= 640;
129 static int sis_screen_height
= 480;
131 static int sis_frames
[VID_PLAY_MAXFRAMES
];
133 static vidix_grkey_t sis_grkey
;
135 static vidix_capability_t sis_cap
= {
136 "SiS 300/310/325 Video Driver",
145 FLAG_UPSCALER
| FLAG_DOWNSCALER
| FLAG_EQUALIZER
,
151 static vidix_video_eq_t sis_equal
= {
152 VEQ_CAP_BRIGHTNESS
| VEQ_CAP_CONTRAST
,
153 200, 0, 0, 0, 0, 0, 0, 0
156 static unsigned short sis_card_ids
[] = {
168 /** function declarations **/
170 void sis_init_video_bridge(void);
173 static void set_overlay(SISOverlayPtr pOverlay
, int index
);
174 static void close_overlay(void);
175 static void calc_scale_factor(SISOverlayPtr pOverlay
,
176 int index
, int iscrt2
);
177 static void set_line_buf_size(SISOverlayPtr pOverlay
);
178 static void merge_line_buf(int enable
);
179 static void set_format(SISOverlayPtr pOverlay
);
180 static void set_colorkey(void);
182 static void set_brightness(uint8_t brightness
);
183 static void set_contrast(uint8_t contrast
);
184 static void set_saturation(char saturation
);
185 static void set_hue(uint8_t hue
);
187 /* IO Port access functions */
188 static uint8_t getvideoreg(uint8_t reg
)
191 inSISIDXREG(SISVID
, reg
, ret
);
195 static void setvideoreg(uint8_t reg
, uint8_t data
)
197 outSISIDXREG(SISVID
, reg
, data
);
200 static void setvideoregmask(uint8_t reg
, uint8_t data
, uint8_t mask
)
204 inSISIDXREG(SISVID
, reg
, old
);
205 data
= (data
& mask
) | (old
& (~mask
));
206 outSISIDXREG(SISVID
, reg
, data
);
209 static void setsrregmask(uint8_t reg
, uint8_t data
, uint8_t mask
)
213 inSISIDXREG(SISSR
, reg
, old
);
214 data
= (data
& mask
) | (old
& (~mask
));
215 outSISIDXREG(SISSR
, reg
, data
);
219 static uint8_t vblank_active_CRT1(void)
221 /* this may be too simplistic? */
222 return inSISREG(SISINPSTAT
) & 0x08;
225 static uint8_t vblank_active_CRT2(void)
228 if (sis_vga_engine
== SIS_315_VGA
) {
229 inSISIDXREG(SISPART1
, Index_310_CRT2_FC_VR
, ret
);
231 inSISIDXREG(SISPART1
, Index_CRT2_FC_VR
, ret
);
233 return (ret
& 0x02) ^ 0x02;
236 static int find_chip(unsigned chip_id
)
239 for (i
= 0; i
< sizeof(sis_card_ids
) / sizeof(unsigned short); i
++) {
240 if (chip_id
== sis_card_ids
[i
])
246 static int sis_probe(int verbose
, int force
)
248 pciinfo_t lst
[MAX_PCI_DEVICES
];
252 sis_verbose
= verbose
;
254 err
= pci_scan(lst
, &num_pci
);
256 printf("[SiS] Error occurred during pci scan: %s\n", strerror(err
));
260 for (i
= 0; i
< num_pci
; i
++) {
261 if (lst
[i
].vendor
== VENDOR_SIS
) {
264 idx
= find_chip(lst
[i
].device
);
267 dname
= pci_device_name(VENDOR_SIS
, lst
[i
].device
);
268 dname
= dname
? dname
: "Unknown chip";
270 printf("[SiS] Found chip: %s (0x%X)\n",
271 dname
, lst
[i
].device
);
272 sis_device_id
= sis_cap
.device_id
= lst
[i
].device
;
274 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
276 sis_has_two_overlays
= 0;
277 switch (sis_cap
.device_id
) {
279 case DEVICE_SIS_630_VGA
:
280 sis_has_two_overlays
= 1;
281 case DEVICE_SIS_540_VGA
:
282 sis_vga_engine
= SIS_300_VGA
;
285 case DEVICE_SIS_550_VGA
:
286 sis_has_two_overlays
= 1;
287 case DEVICE_SIS_315H
:
289 case DEVICE_SIS_315PRO
:
290 case DEVICE_SIS_650_VGA
:
291 /* M650 & 651 have 2 overlays */
292 /* JCP: I think this works, but not really tested yet */
293 if (enable_app_io() == 0 )
296 unsigned char tempreg1
, tempreg2
;
298 inSISIDXREG(SISCR
, 0x5F, CR5F
);
300 andSISIDXREG(SISCR
, 0x5c, 0x07);
301 inSISIDXREG(SISCR
, 0x5c, tempreg1
);
303 setSISIDXREG(SISCR
, 0x5c, 0x07, 0xf8);
304 inSISIDXREG(SISCR
, 0x5c, tempreg2
);
306 if ((!tempreg1
) || (tempreg2
)) {
308 sis_has_two_overlays
= 1;
311 sis_has_two_overlays
= 1; /* ? */
313 if (sis_has_two_overlays
) {
316 ("[SiS] detected M650/651 with 2 overlays\n");
320 sis_vga_engine
= SIS_315_VGA
;
323 /* should never get here */
324 sis_vga_engine
= UNKNOWN_VGA
;
330 if (err
&& sis_verbose
) {
331 printf("[SiS] Can't find chip\n");
339 static int sis_init(void)
341 uint8_t sr_data
, cr_data
, cr_data2
;
342 char *env_overlay_crt
;
345 printf("[SiS] driver was not probed but is being initialized\n");
349 if (enable_app_io() != 0)
351 printf("[SiS] can't enable register I/O\n");
355 /* JCP: this is WRONG. Need to coordinate w/ sisfb to use correct mem */
356 /* map 16MB scary hack for now. */
357 sis_mem_base
= map_phys_mem(pci_info
.base0
, 0x1000000);
358 /* sis_reg_base = map_phys_mem(pci_info.base1, 0x20000); */
359 sis_iobase
= pci_info
.base2
& 0xFFFC;
361 /* would like to use fb ioctl - or some other method - here to get
362 current resolution. */
363 inSISIDXREG(SISCR
, 0x12, cr_data
);
364 inSISIDXREG(SISCR
, 0x07, cr_data2
);
366 ((cr_data
& 0xff) | ((uint16_t) (cr_data2
& 0x02) << 7) |
367 ((uint16_t) (cr_data2
& 0x40) << 3) | ((uint16_t) (cr_data
& 0x02)
370 inSISIDXREG(SISSR
, 0x0b, sr_data
);
371 inSISIDXREG(SISCR
, 0x01, cr_data
);
372 sis_screen_width
= (((cr_data
& 0xff) |
373 ((uint16_t) (sr_data
& 0x0C) << 6)) + 1) * 8;
375 inSISIDXREG(SISSR
, Index_SR_Graphic_Mode
, sr_data
);
376 if (sr_data
& 0x20) /* interlaced mode */
377 sis_vmode
|= VMODE_INTERLACED
;
379 /* JCP: eventually I'd like to replace this with a call to sisfb
380 SISFB_GET_INFO ioctl to get video bridge info. Not for now,
381 since it requires a very new and not widely distributed version. */
382 sis_init_video_bridge();
384 env_overlay_crt
= getenv("VIDIX_CRT");
385 if (env_overlay_crt
) {
386 int crt
= atoi(env_overlay_crt
);
387 if (crt
== 1 || crt
== 2) {
388 sis_overlay_on_crt1
= (crt
== 1);
389 if (sis_verbose
> 0) {
391 ("[SiS] override: using overlay on CRT%d from VIDIX_CRT\n",
400 static void sis_destroy(void)
402 /* unmap_phys_mem(sis_reg_base, 0x20000); */
403 /* JCP: see above, hence also a hack. */
404 unmap_phys_mem(sis_mem_base
, 0x1000000);
408 static int sis_get_caps(vidix_capability_t
* to
)
410 memcpy(to
, &sis_cap
, sizeof(vidix_capability_t
));
414 static int is_supported_fourcc(uint32_t fourcc
)
429 static int sis_query_fourcc(vidix_fourcc_t
* to
)
431 if (is_supported_fourcc(to
->fourcc
)) {
432 to
->depth
= VID_DEPTH_8BPP
| VID_DEPTH_16BPP
| VID_DEPTH_32BPP
;
433 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
436 to
->depth
= to
->flags
= 0;
440 static int bridge_in_slave_mode(void)
442 unsigned char usScratchP1_00
;
444 if (!(sis_vbflags
& VB_VIDEOBRIDGE
))
447 inSISIDXREG(SISPART1
, 0x00, usScratchP1_00
);
448 if (((sis_vga_engine
== SIS_300_VGA
)
449 && (usScratchP1_00
& 0xa0) == 0x20)
450 || ((sis_vga_engine
== SIS_315_VGA
)
451 && (usScratchP1_00
& 0x50) == 0x10)) {
458 /* This does not handle X dual head mode, since 1) vidix doesn't support it
459 and 2) it doesn't make sense for other gfx drivers */
460 static void set_dispmode(void)
462 sis_bridge_is_slave
= 0;
464 if (bridge_in_slave_mode())
465 sis_bridge_is_slave
= 1;
467 if ((sis_vbflags
& VB_DISPMODE_MIRROR
) ||
468 (sis_bridge_is_slave
&& (sis_vbflags
& DISPTYPE_DISP2
))) {
469 if (sis_has_two_overlays
)
470 sis_displaymode
= DISPMODE_MIRROR
; /* TW: CRT1+CRT2 (2 overlays) */
471 else if (!sis_overlay_on_crt1
)
472 sis_displaymode
= DISPMODE_SINGLE2
;
474 sis_displaymode
= DISPMODE_SINGLE1
;
476 if (sis_vbflags
& DISPTYPE_DISP1
) {
477 sis_displaymode
= DISPMODE_SINGLE1
; /* TW: CRT1 only */
479 sis_displaymode
= DISPMODE_SINGLE2
; /* TW: CRT2 only */
484 static void set_disptype_regs(void)
486 switch (sis_displaymode
) {
487 case DISPMODE_SINGLE1
: /* TW: CRT1 only */
488 if (sis_verbose
> 2) {
489 printf("[SiS] Setting up overlay on CRT1\n");
491 if (sis_has_two_overlays
) {
492 setsrregmask(0x06, 0x00, 0xc0);
493 setsrregmask(0x32, 0x00, 0xc0);
495 setsrregmask(0x06, 0x00, 0xc0);
496 setsrregmask(0x32, 0x00, 0xc0);
499 case DISPMODE_SINGLE2
: /* TW: CRT2 only */
500 if (sis_verbose
> 2) {
501 printf("[SiS] Setting up overlay on CRT2\n");
503 if (sis_has_two_overlays
) {
504 setsrregmask(0x06, 0x80, 0xc0);
505 setsrregmask(0x32, 0x80, 0xc0);
507 setsrregmask(0x06, 0x40, 0xc0);
508 setsrregmask(0x32, 0x40, 0xc0);
511 case DISPMODE_MIRROR
: /* TW: CRT1 + CRT2 */
513 if (sis_verbose
> 2) {
514 printf("[SiS] Setting up overlay on CRT1 AND CRT2!\n");
516 setsrregmask(0x06, 0x80, 0xc0);
517 setsrregmask(0x32, 0x80, 0xc0);
522 static void init_overlay(void)
524 /* Initialize first overlay (CRT1) */
526 /* Write-enable video registers */
527 setvideoregmask(Index_VI_Control_Misc2
, 0x80, 0x81);
529 /* Disable overlay */
530 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
532 /* Disable bobEnable */
533 setvideoregmask(Index_VI_Control_Misc1
, 0x02, 0x02);
535 /* Reset scale control and contrast */
536 setvideoregmask(Index_VI_Scale_Control
, 0x60, 0x60);
537 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x1F);
539 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low
, 0x00);
540 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle
, 0x00);
541 setvideoreg(Index_VI_UV_Buf_Preset_Low
, 0x00);
542 setvideoreg(Index_VI_UV_Buf_Preset_Middle
, 0x00);
543 setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High
, 0x00);
544 setvideoreg(Index_VI_Play_Threshold_Low
, 0x00);
545 setvideoreg(Index_VI_Play_Threshold_High
, 0x00);
547 /* may not want to init these here, could already be set to other
549 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
550 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x07);
551 setvideoreg(Index_VI_Brightness
, 0x20);
552 if (sis_vga_engine
== SIS_315_VGA
) {
553 setvideoreg(Index_VI_Hue
, 0x00);
554 setvideoreg(Index_VI_Saturation
, 0x00);
557 /* Initialize second overlay (CRT2) */
558 if (sis_has_two_overlays
) {
559 /* Write-enable video registers */
560 setvideoregmask(Index_VI_Control_Misc2
, 0x81, 0x81);
562 /* Disable overlay */
563 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
565 /* Disable bobEnable */
566 setvideoregmask(Index_VI_Control_Misc1
, 0x02, 0x02);
568 /* Reset scale control and contrast */
569 setvideoregmask(Index_VI_Scale_Control
, 0x60, 0x60);
570 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x1F);
572 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low
, 0x00);
573 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle
, 0x00);
574 setvideoreg(Index_VI_UV_Buf_Preset_Low
, 0x00);
575 setvideoreg(Index_VI_UV_Buf_Preset_Middle
, 0x00);
576 setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High
, 0x00);
577 setvideoreg(Index_VI_Play_Threshold_Low
, 0x00);
578 setvideoreg(Index_VI_Play_Threshold_High
, 0x00);
580 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x01);
581 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x07);
582 setvideoreg(Index_VI_Brightness
, 0x20);
583 if (sis_vga_engine
== SIS_315_VGA
) {
584 setvideoreg(Index_VI_Hue
, 0x00);
585 setvideoreg(Index_VI_Saturation
, 0x00);
590 static int sis_set_eq(const vidix_video_eq_t
* eq
);
592 static int sis_config_playback(vidix_playback_t
* info
)
594 SISOverlayRec overlay
;
595 int srcOffsetX
= 0, srcOffsetY
= 0;
597 int index
= 0, iscrt2
= 0;
608 if (!is_supported_fourcc(info
->fourcc
))
611 /* set chipset/engine.dependent config info */
612 /* which CRT to use, etc.? */
613 switch (sis_vga_engine
) {
616 sis_equal
.cap
|= VEQ_CAP_SATURATION
| VEQ_CAP_HUE
;
624 sis_displaymode
= DISPMODE_SINGLE1
; /* xV driver code in set_dispmode() */
631 /* get basic dimension info */
637 drw_x
= info
->dest
.x
;
638 drw_y
= info
->dest
.y
;
639 drw_w
= info
->dest
.w
;
640 drw_h
= info
->dest
.h
;
642 switch (info
->fourcc
) {
645 pitch
= (src_w
+ 7) & ~7;
646 total_size
= (pitch
* src_h
* 3) >> 1;
652 pitch
= ((src_w
<< 1) + 3) & ~3;
653 total_size
= pitch
* src_h
;
659 /* "allocate" memory for overlay! */
660 /* start at 8MB = sisfb's "dri reserved space" -
661 really shouldn't hardcode though */
662 /* XXX: JCP - this can use the sisfb FBIO_ALLOC ioctl to safely
663 allocate "video heap" memory... */
664 dga_offset
= 0x800000;
666 /* use 7MB for now. need to calc/get real info from sisfb? */
667 /* this can result in a LOT of frames - probably not necessary */
668 info
->num_frames
= 0x700000 / (total_size
* 2);
669 if (info
->num_frames
> VID_PLAY_MAXFRAMES
)
670 info
->num_frames
= VID_PLAY_MAXFRAMES
;
672 info
->dga_addr
= sis_mem_base
+ dga_offset
;
673 info
->dest
.pitch
.y
= 16;
674 info
->dest
.pitch
.u
= 16;
675 info
->dest
.pitch
.v
= 16;
679 info
->frame_size
= (total_size
* 2); /* why times 2 ? */
680 for (i
= 0; i
< info
->num_frames
; i
++) {
681 info
->offsets
[i
] = info
->frame_size
* i
;
682 /* save ptrs to mem buffers */
683 sis_frames
[i
] = (dga_offset
+ info
->offsets
[i
]);
686 memset(&overlay
, 0, sizeof(overlay
));
687 overlay
.pixelFormat
= sis_format
= info
->fourcc
;
688 overlay
.pitch
= overlay
.origPitch
= pitch
;
691 overlay
.keyOP
= (sis_grkey
.ckey
.op
== CKEY_TRUE
?
692 VI_ROP_DestKey
: VI_ROP_Always
);
694 overlay
.bobEnable
= 0x00;
696 overlay
.SCREENheight
= sis_screen_height
;
698 /* probably will not support X virtual screen > phys very well? */
699 overlay
.dstBox
.x1
= drw_x
; /* - pScrn->frameX0; */
700 overlay
.dstBox
.x2
= drw_x
+ drw_w
; /* - pScrn->frameX0; ??? */
701 overlay
.dstBox
.y1
= drw_y
; /* - pScrn->frameY0; */
702 overlay
.dstBox
.y2
= drw_y
+ drw_h
; /* - pScrn->frameY0; ??? */
704 if ((overlay
.dstBox
.x1
> overlay
.dstBox
.x2
) ||
705 (overlay
.dstBox
.y1
> overlay
.dstBox
.y2
))
708 if ((overlay
.dstBox
.x2
< 0) || (overlay
.dstBox
.y2
< 0))
711 if (overlay
.dstBox
.x1
< 0) {
712 srcOffsetX
= src_w
* (-overlay
.dstBox
.x1
) / drw_w
;
713 overlay
.dstBox
.x1
= 0;
715 if (overlay
.dstBox
.y1
< 0) {
716 srcOffsetY
= src_h
* (-overlay
.dstBox
.y1
) / drw_h
;
717 overlay
.dstBox
.y1
= 0;
720 switch (info
->fourcc
) {
722 info
->dest
.pitch
.y
= 16;
723 sx
= (src_x
+ srcOffsetX
) & ~7;
724 sy
= (src_y
+ srcOffsetY
) & ~1;
725 info
->offset
.y
= sis_Yoff
= sx
+ sy
* pitch
;
726 /* JCP: NOTE reversed u & v here! Not sure why this is needed.
727 maybe mplayer & sis define U & V differently?? */
728 info
->offset
.u
= sis_Voff
=
729 src_h
* pitch
+ ((sx
+ sy
* pitch
/ 2) >> 1);
730 info
->offset
.v
= sis_Uoff
=
731 src_h
* pitch
* 5 / 4 + ((sx
+ sy
* pitch
/ 2) >> 1);
733 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
734 overlay
.PSV
= (sis_frames
[0] + sis_Voff
) >> sis_shift_value
;
735 overlay
.PSU
= (sis_frames
[0] + sis_Uoff
) >> sis_shift_value
;
738 sx
= (src_x
+ srcOffsetX
) & ~7;
739 sy
= (src_y
+ srcOffsetY
) & ~1;
740 info
->offset
.y
= sis_Yoff
= sx
+ sy
* pitch
;
741 /* JCP: see above... */
742 info
->offset
.u
= sis_Voff
=
743 src_h
* pitch
* 5 / 4 + ((sx
+ sy
* pitch
/ 2) >> 1);
744 info
->offset
.v
= sis_Uoff
=
745 src_h
* pitch
+ ((sx
+ sy
* pitch
/ 2) >> 1);
747 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
748 overlay
.PSV
= (sis_frames
[0] + sis_Voff
) >> sis_shift_value
;
749 overlay
.PSU
= (sis_frames
[0] + sis_Uoff
) >> sis_shift_value
;
756 sx
= (src_x
+ srcOffsetX
) & ~1;
757 sy
= (src_y
+ srcOffsetY
);
758 info
->offset
.y
= sis_Yoff
= sx
* 2 + sy
* pitch
;
760 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
764 /* FIXME: is it possible that srcW < 0? */
765 overlay
.srcW
= src_w
- (sx
- src_x
);
766 overlay
.srcH
= src_h
- (sy
- src_y
);
768 /* set merge line buffer */
769 merge_line_buf(overlay
.srcW
> 384);
771 /* calculate line buffer length */
772 set_line_buf_size(&overlay
);
774 if (sis_displaymode
== DISPMODE_SINGLE2
) {
775 if (sis_has_two_overlays
) {
776 /* TW: On chips with two overlays we use
777 * overlay 2 for CRT2 */
781 /* TW: On chips with only one overlay we
782 * use that only overlay for CRT2 */
786 overlay
.VBlankActiveFunc
= vblank_active_CRT2
;
787 /* overlay.GetScanLineFunc = get_scanline_CRT2; */
791 overlay
.VBlankActiveFunc
= vblank_active_CRT1
;
792 /* overlay.GetScanLineFunc = get_scanline_CRT1; */
795 /* calc scale factor (to use below) */
796 calc_scale_factor(&overlay
, index
, iscrt2
);
798 /* Select video1 (used for CRT1) or video2 (used for CRT2) */
799 setvideoregmask(Index_VI_Control_Misc2
, index
, 0x01);
801 set_format(&overlay
);
805 sis_set_eq(&sis_equal
);
807 /* set up video overlay registers */
808 set_overlay(&overlay
, index
);
810 /* prevent badness if bits are not at default setting */
811 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x01);
812 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x04);
814 /* JCP: Xv driver implementation loops back over above code to
820 static int sis_playback_on(void)
822 setvideoregmask(Index_VI_Control_Misc0
, 0x02, 0x02);
826 static int sis_playback_off(void)
828 unsigned char sridx
, cridx
;
829 sridx
= inSISREG(SISSR
);
830 cridx
= inSISREG(SISCR
);
832 outSISREG(SISSR
, sridx
);
833 outSISREG(SISCR
, cridx
);
838 static int sis_frame_select(unsigned int frame
)
844 if (sis_displaymode
== DISPMODE_SINGLE2
&& sis_has_two_overlays
) {
848 PSY
= (sis_frames
[frame
] + sis_Yoff
) >> sis_shift_value
;
850 /* Unlock address registers */
851 data
= getvideoreg(Index_VI_Control_Misc1
);
852 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
853 /* TEST: Is this required? */
854 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
856 /* TEST: Is this required? */
857 if (sis_vga_engine
== SIS_315_VGA
)
858 setvideoreg(Index_VI_Control_Misc3
, 0x00);
861 /* set Y start address */
862 setvideoreg(Index_VI_Disp_Y_Buf_Start_Low
, (uint8_t) (PSY
));
863 setvideoreg(Index_VI_Disp_Y_Buf_Start_Middle
, (uint8_t) ((PSY
) >> 8));
864 setvideoreg(Index_VI_Disp_Y_Buf_Start_High
, (uint8_t) ((PSY
) >> 16));
865 /* set 310/325 series overflow bits for Y plane */
866 if (sis_vga_engine
== SIS_315_VGA
) {
867 setvideoreg(Index_VI_Y_Buf_Start_Over
,
868 ((uint8_t) ((PSY
) >> 24) & 0x01));
871 /* Set U/V data if using plane formats */
872 if ((sis_format
== IMGFMT_YV12
) || (sis_format
== IMGFMT_I420
)) {
876 PSU
= (sis_frames
[frame
] + sis_Uoff
) >> sis_shift_value
;
877 PSV
= (sis_frames
[frame
] + sis_Voff
) >> sis_shift_value
;
879 /* set U/V start address */
880 setvideoreg(Index_VI_U_Buf_Start_Low
, (uint8_t) PSU
);
881 setvideoreg(Index_VI_U_Buf_Start_Middle
, (uint8_t) (PSU
>> 8));
882 setvideoreg(Index_VI_U_Buf_Start_High
, (uint8_t) (PSU
>> 16));
884 setvideoreg(Index_VI_V_Buf_Start_Low
, (uint8_t) PSV
);
885 setvideoreg(Index_VI_V_Buf_Start_Middle
, (uint8_t) (PSV
>> 8));
886 setvideoreg(Index_VI_V_Buf_Start_High
, (uint8_t) (PSV
>> 16));
888 /* 310/325 series overflow bits */
889 if (sis_vga_engine
== SIS_315_VGA
) {
890 setvideoreg(Index_VI_U_Buf_Start_Over
,
891 ((uint8_t) (PSU
>> 24) & 0x01));
892 setvideoreg(Index_VI_V_Buf_Start_Over
,
893 ((uint8_t) (PSV
>> 24) & 0x01));
897 if (sis_vga_engine
== SIS_315_VGA
) {
898 /* Trigger register copy for 310 series */
899 setvideoreg(Index_VI_Control_Misc3
, 1 << index
);
902 /* Lock the address registers */
903 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x20);
908 static int sis_get_gkeys(vidix_grkey_t
* grkey
)
910 memcpy(grkey
, &sis_grkey
, sizeof(vidix_grkey_t
));
914 static int sis_set_gkeys(const vidix_grkey_t
* grkey
)
916 memcpy(&sis_grkey
, grkey
, sizeof(vidix_grkey_t
));
921 static int sis_get_eq(vidix_video_eq_t
* eq
)
923 memcpy(eq
, &sis_equal
, sizeof(vidix_video_eq_t
));
927 static int sis_set_eq(const vidix_video_eq_t
* eq
)
929 int br
, sat
, cr
, hue
;
930 if (eq
->cap
& VEQ_CAP_BRIGHTNESS
)
931 sis_equal
.brightness
= eq
->brightness
;
932 if (eq
->cap
& VEQ_CAP_CONTRAST
)
933 sis_equal
.contrast
= eq
->contrast
;
934 if (eq
->cap
& VEQ_CAP_SATURATION
)
935 sis_equal
.saturation
= eq
->saturation
;
936 if (eq
->cap
& VEQ_CAP_HUE
)
937 sis_equal
.hue
= eq
->hue
;
938 if (eq
->cap
& VEQ_CAP_RGB_INTENSITY
) {
939 sis_equal
.red_intensity
= eq
->red_intensity
;
940 sis_equal
.green_intensity
= eq
->green_intensity
;
941 sis_equal
.blue_intensity
= eq
->blue_intensity
;
943 sis_equal
.flags
= eq
->flags
;
945 cr
= (sis_equal
.contrast
+ 1000) * 7 / 2000;
951 br
= sis_equal
.brightness
* 127 / 1000;
957 sat
= (sis_equal
.saturation
* 7) / 1000;
963 hue
= sis_equal
.hue
* 7 / 1000;
971 if (sis_vga_engine
== SIS_315_VGA
) {
979 static void set_overlay(SISOverlayPtr pOverlay
, int index
)
982 uint8_t h_over
= 0, v_over
= 0;
983 uint16_t top
, bottom
, left
, right
;
984 uint16_t screenX
= sis_screen_width
;
985 uint16_t screenY
= sis_screen_height
;
989 top
= pOverlay
->dstBox
.y1
;
990 bottom
= pOverlay
->dstBox
.y2
;
991 if (bottom
> screenY
) {
995 left
= pOverlay
->dstBox
.x1
;
996 right
= pOverlay
->dstBox
.x2
;
997 if (right
> screenX
) {
1001 /* JCP: these aren't really tested... */
1002 /* TW: DoubleScan modes require Y coordinates * 2 */
1003 if (sis_vmode
& VMODE_DOUBLESCAN
) {
1007 /* TW: Interlace modes require Y coordinates / 2 */
1008 if (sis_vmode
& VMODE_INTERLACED
) {
1013 h_over
= (((left
>> 8) & 0x0f) | ((right
>> 4) & 0xf0));
1014 v_over
= (((top
>> 8) & 0x0f) | ((bottom
>> 4) & 0xf0));
1016 pitch
= pOverlay
->pitch
>> sis_shift_value
;
1018 /* set line buffer size */
1019 setvideoreg(Index_VI_Line_Buffer_Size
, pOverlay
->lineBufSize
);
1021 /* set color key mode */
1022 setvideoregmask(Index_VI_Key_Overlay_OP
, pOverlay
->keyOP
, 0x0F);
1024 /* TW: We don't have to wait for vertical retrace in all cases */
1025 /* JCP: be safe for now. */
1026 if (1 /*pPriv->mustwait */ ) {
1027 watchdog
= WATCHDOG_DELAY
;
1028 while (pOverlay
->VBlankActiveFunc() && --watchdog
);
1029 watchdog
= WATCHDOG_DELAY
;
1030 while ((!pOverlay
->VBlankActiveFunc()) && --watchdog
);
1031 if (!watchdog
&& sis_verbose
> 0) {
1032 printf("[SiS]: timed out waiting for vertical retrace\n");
1036 /* Unlock address registers */
1037 data
= getvideoreg(Index_VI_Control_Misc1
);
1038 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
1039 /* TEST: Is this required? */
1040 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
1043 /* TEST: Is this required? */
1044 if (sis_vga_engine
== SIS_315_VGA
)
1045 setvideoreg(Index_VI_Control_Misc3
, 0x00);
1048 /* Set Y buf pitch */
1049 setvideoreg(Index_VI_Disp_Y_Buf_Pitch_Low
, (uint8_t) (pitch
));
1050 setvideoregmask(Index_VI_Disp_Y_UV_Buf_Pitch_Middle
,
1051 (uint8_t) (pitch
>> 8), 0x0f);
1053 /* Set Y start address */
1054 setvideoreg(Index_VI_Disp_Y_Buf_Start_Low
, (uint8_t) (pOverlay
->PSY
));
1055 setvideoreg(Index_VI_Disp_Y_Buf_Start_Middle
,
1056 (uint8_t) ((pOverlay
->PSY
) >> 8));
1057 setvideoreg(Index_VI_Disp_Y_Buf_Start_High
,
1058 (uint8_t) ((pOverlay
->PSY
) >> 16));
1060 /* set 310/325 series overflow bits for Y plane */
1061 if (sis_vga_engine
== SIS_315_VGA
) {
1062 setvideoreg(Index_VI_Disp_Y_Buf_Pitch_High
,
1063 (uint8_t) (pitch
>> 12));
1064 setvideoreg(Index_VI_Y_Buf_Start_Over
,
1065 ((uint8_t) ((pOverlay
->PSY
) >> 24) & 0x01));
1068 /* Set U/V data if using plane formats */
1069 if ((pOverlay
->pixelFormat
== IMGFMT_YV12
) ||
1070 (pOverlay
->pixelFormat
== IMGFMT_I420
)) {
1074 PSU
= pOverlay
->PSU
;
1075 PSV
= pOverlay
->PSV
;
1078 setvideoreg(Index_VI_Disp_UV_Buf_Pitch_Low
,
1079 (uint8_t) (pitch
>> 1));
1080 setvideoregmask(Index_VI_Disp_Y_UV_Buf_Pitch_Middle
,
1081 (uint8_t) (pitch
>> 5), 0xf0);
1083 /* set U/V start address */
1084 setvideoreg(Index_VI_U_Buf_Start_Low
, (uint8_t) PSU
);
1085 setvideoreg(Index_VI_U_Buf_Start_Middle
, (uint8_t) (PSU
>> 8));
1086 setvideoreg(Index_VI_U_Buf_Start_High
, (uint8_t) (PSU
>> 16));
1088 setvideoreg(Index_VI_V_Buf_Start_Low
, (uint8_t) PSV
);
1089 setvideoreg(Index_VI_V_Buf_Start_Middle
, (uint8_t) (PSV
>> 8));
1090 setvideoreg(Index_VI_V_Buf_Start_High
, (uint8_t) (PSV
>> 16));
1092 /* 310/325 series overflow bits */
1093 if (sis_vga_engine
== SIS_315_VGA
) {
1094 setvideoreg(Index_VI_Disp_UV_Buf_Pitch_High
,
1095 (uint8_t) (pitch
>> 13));
1096 setvideoreg(Index_VI_U_Buf_Start_Over
,
1097 ((uint8_t) (PSU
>> 24) & 0x01));
1098 setvideoreg(Index_VI_V_Buf_Start_Over
,
1099 ((uint8_t) (PSV
>> 24) & 0x01));
1103 if (sis_vga_engine
== SIS_315_VGA
) {
1104 /* Trigger register copy for 310 series */
1105 setvideoreg(Index_VI_Control_Misc3
, 1 << index
);
1108 /* set scale factor */
1109 setvideoreg(Index_VI_Hor_Post_Up_Scale_Low
,
1110 (uint8_t) (pOverlay
->HUSF
));
1111 setvideoreg(Index_VI_Hor_Post_Up_Scale_High
,
1112 (uint8_t) ((pOverlay
->HUSF
) >> 8));
1113 setvideoreg(Index_VI_Ver_Up_Scale_Low
, (uint8_t) (pOverlay
->VUSF
));
1114 setvideoreg(Index_VI_Ver_Up_Scale_High
,
1115 (uint8_t) ((pOverlay
->VUSF
) >> 8));
1117 setvideoregmask(Index_VI_Scale_Control
, (pOverlay
->IntBit
<< 3)
1118 | (pOverlay
->wHPre
), 0x7f);
1120 /* set destination window position */
1121 setvideoreg(Index_VI_Win_Hor_Disp_Start_Low
, (uint8_t) left
);
1122 setvideoreg(Index_VI_Win_Hor_Disp_End_Low
, (uint8_t) right
);
1123 setvideoreg(Index_VI_Win_Hor_Over
, (uint8_t) h_over
);
1125 setvideoreg(Index_VI_Win_Ver_Disp_Start_Low
, (uint8_t) top
);
1126 setvideoreg(Index_VI_Win_Ver_Disp_End_Low
, (uint8_t) bottom
);
1127 setvideoreg(Index_VI_Win_Ver_Over
, (uint8_t) v_over
);
1129 setvideoregmask(Index_VI_Control_Misc1
, pOverlay
->bobEnable
, 0x1a);
1131 /* Lock the address registers */
1132 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x20);
1136 /* TW: Overlay MUST NOT be switched off while beam is over it */
1137 static void close_overlay(void)
1141 if ((sis_displaymode
== DISPMODE_SINGLE2
) ||
1142 (sis_displaymode
== DISPMODE_MIRROR
)) {
1143 if (sis_has_two_overlays
) {
1144 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x01);
1145 watchdog
= WATCHDOG_DELAY
;
1146 while (vblank_active_CRT2() && --watchdog
);
1147 watchdog
= WATCHDOG_DELAY
;
1148 while ((!vblank_active_CRT2()) && --watchdog
);
1149 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1150 watchdog
= WATCHDOG_DELAY
;
1151 while (vblank_active_CRT2() && --watchdog
);
1152 watchdog
= WATCHDOG_DELAY
;
1153 while ((!vblank_active_CRT2()) && --watchdog
);
1154 } else if (sis_displaymode
== DISPMODE_SINGLE2
) {
1155 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
1156 watchdog
= WATCHDOG_DELAY
;
1157 while (vblank_active_CRT1() && --watchdog
);
1158 watchdog
= WATCHDOG_DELAY
;
1159 while ((!vblank_active_CRT1()) && --watchdog
);
1160 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1161 watchdog
= WATCHDOG_DELAY
;
1162 while (vblank_active_CRT1() && --watchdog
);
1163 watchdog
= WATCHDOG_DELAY
;
1164 while ((!vblank_active_CRT1()) && --watchdog
);
1167 if ((sis_displaymode
== DISPMODE_SINGLE1
) ||
1168 (sis_displaymode
== DISPMODE_MIRROR
)) {
1169 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
1170 watchdog
= WATCHDOG_DELAY
;
1171 while (vblank_active_CRT1() && --watchdog
);
1172 watchdog
= WATCHDOG_DELAY
;
1173 while ((!vblank_active_CRT1()) && --watchdog
);
1174 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1175 watchdog
= WATCHDOG_DELAY
;
1176 while (vblank_active_CRT1() && --watchdog
);
1177 watchdog
= WATCHDOG_DELAY
;
1178 while ((!vblank_active_CRT1()) && --watchdog
);
1184 calc_scale_factor(SISOverlayPtr pOverlay
, int index
, int iscrt2
)
1186 uint32_t i
= 0, mult
= 0;
1189 int dstW
= pOverlay
->dstBox
.x2
- pOverlay
->dstBox
.x1
;
1190 int dstH
= pOverlay
->dstBox
.y2
- pOverlay
->dstBox
.y1
;
1191 int srcW
= pOverlay
->srcW
;
1192 int srcH
= pOverlay
->srcH
;
1193 /* uint16_t LCDheight = pSiS->LCDheight; */
1194 int srcPitch
= pOverlay
->origPitch
;
1195 int origdstH
= dstH
;
1197 /* get rid of warnings for now */
1201 /* TW: For double scan modes, we need to double the height
1202 * (Perhaps we also need to scale LVDS, but I'm not sure.)
1203 * On 310/325 series, we need to double the width as well.
1204 * Interlace mode vice versa.
1206 if (sis_vmode
& VMODE_DOUBLESCAN
) {
1207 dstH
= origdstH
<< 1;
1209 if (sis_vga_engine
== SIS_315_VGA
) {
1213 if (sis_vmode
& VMODE_INTERLACED
) {
1214 dstH
= origdstH
>> 1;
1218 if (dstW
< OVERLAY_MIN_WIDTH
)
1219 dstW
= OVERLAY_MIN_WIDTH
;
1221 pOverlay
->HUSF
= 0x00;
1222 pOverlay
->IntBit
= 0x05;
1223 pOverlay
->wHPre
= 0;
1224 } else if (dstW
> srcW
) {
1226 pOverlay
->HUSF
= (srcW
<< 16) / dstW
;
1227 pOverlay
->IntBit
= 0x04;
1228 pOverlay
->wHPre
= 0;
1232 /* TW: It seems, the hardware can't scale below factor .125 (=1/8) if the
1233 pitch isn't a multiple of 256.
1234 TODO: Test this on the 310/325 series!
1236 if ((srcPitch
% 256) || (srcPitch
< 256)) {
1237 if (((dstW
* 1000) / srcW
) < 125)
1238 dstW
= tmpW
= ((srcW
* 125) / 1000) + 1;
1242 pOverlay
->IntBit
= 0x01;
1243 while (srcW
>= tmpW
) {
1247 pOverlay
->wHPre
= (uint8_t) (i
- 1);
1250 pOverlay
->HUSF
= ((srcW
- dstW
) << 16) / dstW
;
1252 pOverlay
->HUSF
= 0x00;
1255 if (dstH
< OVERLAY_MIN_HEIGHT
)
1256 dstH
= OVERLAY_MIN_HEIGHT
;
1258 pOverlay
->VUSF
= 0x00;
1259 pOverlay
->IntBit
|= 0x0A;
1260 } else if (dstH
> srcH
) {
1262 pOverlay
->VUSF
= (srcH
<< 16) / dstH
;
1263 pOverlay
->IntBit
|= 0x08;
1267 i
= realI
= srcH
/ dstH
;
1268 pOverlay
->IntBit
|= 0x02;
1271 pOverlay
->VUSF
= ((srcH
- dstH
) << 16) / dstH
;
1272 /* TW: Needed for LCD-scaling modes */
1273 if ((flag
) && (mult
= (srcH
/ origdstH
)) >= 2)
1274 pOverlay
->pitch
/= mult
;
1276 if (((srcPitch
* i
) >> 2) > 0xFFF) {
1277 i
= (0xFFF * 2 / srcPitch
);
1278 pOverlay
->VUSF
= 0xFFFF;
1282 pOverlay
->VUSF
= ((srcH
- dstH
) << 16) / dstH
;
1284 pOverlay
->VUSF
= 0x00;
1286 /* set video frame buffer offset */
1287 pOverlay
->pitch
= (uint16_t) (srcPitch
* i
);
1292 static void set_line_buf_size(SISOverlayPtr pOverlay
)
1296 uint32_t line
= pOverlay
->srcW
;
1298 if ((pOverlay
->pixelFormat
== IMGFMT_YV12
) ||
1299 (pOverlay
->pixelFormat
== IMGFMT_I420
)) {
1300 preHIDF
= pOverlay
->wHPre
& 0x07;
1303 if ((line
& 0xffffff00) == line
)
1306 i
= (line
>> 8) + 1;
1307 pOverlay
->lineBufSize
= (uint8_t) (i
* 32 - 1);
1310 if ((line
& 0xfffffe00) == line
)
1313 i
= (line
>> 9) + 1;
1314 pOverlay
->lineBufSize
= (uint8_t) (i
* 64 - 1);
1317 if ((line
& 0xfffffc00) == line
)
1320 i
= (line
>> 10) + 1;
1321 pOverlay
->lineBufSize
= (uint8_t) (i
* 128 - 1);
1324 if ((line
& 0xfffff800) == line
)
1327 i
= (line
>> 11) + 1;
1328 pOverlay
->lineBufSize
= (uint8_t) (i
* 256 - 1);
1331 if ((line
& 0xffffff80) == line
)
1334 i
= (line
>> 7) + 1;
1335 pOverlay
->lineBufSize
= (uint8_t) (i
* 16 - 1);
1338 } else { /* YUV2, UYVY */
1339 if ((line
& 0xffffff8) == line
)
1342 i
= (line
>> 3) + 1;
1343 pOverlay
->lineBufSize
= (uint8_t) (i
- 1);
1347 static void merge_line_buf(int enable
)
1350 switch (sis_displaymode
) {
1351 case DISPMODE_SINGLE1
:
1352 if (sis_has_two_overlays
) {
1353 /* dual line merge */
1354 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1355 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1357 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1358 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1361 case DISPMODE_SINGLE2
:
1362 if (sis_has_two_overlays
) {
1364 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1365 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1367 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1368 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1371 case DISPMODE_MIRROR
:
1374 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1375 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1376 if (sis_has_two_overlays
) {
1378 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1379 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1384 switch (sis_displaymode
) {
1385 case DISPMODE_SINGLE1
:
1386 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1387 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1389 case DISPMODE_SINGLE2
:
1390 if (sis_has_two_overlays
) {
1391 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1392 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1394 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1395 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1398 case DISPMODE_MIRROR
:
1400 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1401 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1402 if (sis_has_two_overlays
) {
1403 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1404 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1412 static void set_format(SISOverlayPtr pOverlay
)
1416 switch (pOverlay
->pixelFormat
) {
1427 case IMGFMT_RGB15
: /* D[5:4] : 00 RGB555, 01 RGB 565 */
1437 setvideoregmask(Index_VI_Control_Misc0
, fmt
, 0x7c);
1440 static void set_colorkey(void)
1444 b
= (uint8_t) sis_grkey
.ckey
.blue
;
1445 g
= (uint8_t) sis_grkey
.ckey
.green
;
1446 r
= (uint8_t) sis_grkey
.ckey
.red
;
1448 /* set color key mode */
1449 setvideoregmask(Index_VI_Key_Overlay_OP
,
1450 sis_grkey
.ckey
.op
== CKEY_TRUE
?
1451 VI_ROP_DestKey
: VI_ROP_Always
, 0x0F);
1453 /* set colorkey values */
1454 setvideoreg(Index_VI_Overlay_ColorKey_Blue_Min
, (uint8_t) b
);
1455 setvideoreg(Index_VI_Overlay_ColorKey_Green_Min
, (uint8_t) g
);
1456 setvideoreg(Index_VI_Overlay_ColorKey_Red_Min
, (uint8_t) r
);
1458 setvideoreg(Index_VI_Overlay_ColorKey_Blue_Max
, (uint8_t) b
);
1459 setvideoreg(Index_VI_Overlay_ColorKey_Green_Max
, (uint8_t) g
);
1460 setvideoreg(Index_VI_Overlay_ColorKey_Red_Max
, (uint8_t) r
);
1463 static void set_brightness(uint8_t brightness
)
1465 setvideoreg(Index_VI_Brightness
, brightness
);
1468 static void set_contrast(uint8_t contrast
)
1470 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, contrast
, 0x07);
1473 /* Next 3 functions are 310/325 series only */
1475 static void set_saturation(char saturation
)
1479 if (saturation
< 0) {
1481 saturation
= -saturation
;
1483 temp
|= (saturation
& 0x07);
1484 temp
|= ((saturation
& 0x07) << 4);
1486 setvideoreg(Index_VI_Saturation
, temp
);
1489 static void set_hue(uint8_t hue
)
1491 setvideoreg(Index_VI_Hue
, (hue
& 0x08) ? (hue
^ 0x07) : hue
);
1494 VDXDriver sis_drv
= {
1499 .get_caps
= sis_get_caps
,
1500 .query_fourcc
= sis_query_fourcc
,
1502 .destroy
= sis_destroy
,
1503 .config_playback
= sis_config_playback
,
1504 .playback_on
= sis_playback_on
,
1505 .playback_off
= sis_playback_off
,
1506 .frame_sel
= sis_frame_select
,
1507 .get_eq
= sis_get_eq
,
1508 .set_eq
= sis_set_eq
,
1509 .get_gkey
= sis_get_gkeys
,
1510 .set_gkey
= sis_set_gkeys
,