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"
40 #include "sis_bridge.h"
45 /** Random defines **/
47 #define WATCHDOG_DELAY 500000 /* Watchdog counter for retrace waiting */
48 #define IMAGE_MIN_WIDTH 32 /* Min and max source image sizes */
49 #define IMAGE_MIN_HEIGHT 24
50 #define IMAGE_MAX_WIDTH 720
51 #define IMAGE_MAX_HEIGHT 576
52 #define IMAGE_MAX_WIDTH_M650 1920
53 #define IMAGE_MAX_HEIGHT_M650 1080
55 #define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */
56 #define OVERLAY_MIN_HEIGHT 24
58 #define DISPMODE_SINGLE1 0x1 /* TW: CRT1 only */
59 #define DISPMODE_SINGLE2 0x2 /* TW: CRT2 only */
60 #define DISPMODE_MIRROR 0x4 /* TW: CRT1 + CRT2 MIRROR */
62 #define VMODE_INTERLACED 0x1
63 #define VMODE_DOUBLESCAN 0x2
92 uint8_t contrastFactor
;
96 uint8_t(*VBlankActiveFunc
) ();
98 uint16_t SCREENheight
;
100 } SISOverlayRec
, *SISOverlayPtr
;
103 /** static variable definitions **/
104 static int sis_probed
= 0;
105 static pciinfo_t pci_info
;
106 unsigned int sis_verbose
= 0;
108 static void *sis_mem_base
;
109 /* static void *sis_reg_base; */
110 unsigned short sis_iobase
;
112 unsigned int sis_vga_engine
= UNKNOWN_VGA
;
113 static unsigned int sis_displaymode
= DISPMODE_SINGLE1
;
114 static unsigned int sis_has_two_overlays
= 0;
115 static unsigned int sis_bridge_is_slave
= 0;
116 static unsigned int sis_shift_value
= 1;
117 static unsigned int sis_vmode
= 0;
118 unsigned int sis_vbflags
= DISPTYPE_DISP1
;
119 unsigned int sis_overlay_on_crt1
= 1;
120 int sis_crt1_off
= -1;
121 unsigned int sis_detected_crt2_devices
;
122 unsigned int sis_force_crt2_type
= CRT2_DEFAULT
;
123 int sis_device_id
= -1;
125 static int sis_format
;
126 static int sis_Yoff
= 0;
127 static int sis_Voff
= 0;
128 static int sis_Uoff
= 0;
129 static int sis_screen_width
= 640;
130 static int sis_screen_height
= 480;
132 static int sis_frames
[VID_PLAY_MAXFRAMES
];
134 static vidix_grkey_t sis_grkey
;
136 static vidix_capability_t sis_cap
= {
137 "SiS 300/310/325 Video Driver",
146 FLAG_UPSCALER
| FLAG_DOWNSCALER
| FLAG_EQUALIZER
,
152 static vidix_video_eq_t sis_equal
= {
153 VEQ_CAP_BRIGHTNESS
| VEQ_CAP_CONTRAST
,
154 200, 0, 0, 0, 0, 0, 0, 0
157 static unsigned short sis_card_ids
[] = {
169 /** function declarations **/
171 static void set_overlay(SISOverlayPtr pOverlay
, int index
);
172 static void close_overlay(void);
173 static void calc_scale_factor(SISOverlayPtr pOverlay
,
174 int index
, int iscrt2
);
175 static void set_line_buf_size(SISOverlayPtr pOverlay
);
176 static void merge_line_buf(int enable
);
177 static void set_format(SISOverlayPtr pOverlay
);
178 static void set_colorkey(void);
180 static void set_brightness(uint8_t brightness
);
181 static void set_contrast(uint8_t contrast
);
182 static void set_saturation(char saturation
);
183 static void set_hue(uint8_t hue
);
185 /* IO Port access functions */
186 static uint8_t getvideoreg(uint8_t reg
)
189 inSISIDXREG(SISVID
, reg
, ret
);
193 static void setvideoreg(uint8_t reg
, uint8_t data
)
195 outSISIDXREG(SISVID
, reg
, data
);
198 static void setvideoregmask(uint8_t reg
, uint8_t data
, uint8_t mask
)
202 inSISIDXREG(SISVID
, reg
, old
);
203 data
= (data
& mask
) | (old
& (~mask
));
204 outSISIDXREG(SISVID
, reg
, data
);
207 static void setsrregmask(uint8_t reg
, uint8_t data
, uint8_t mask
)
211 inSISIDXREG(SISSR
, reg
, old
);
212 data
= (data
& mask
) | (old
& (~mask
));
213 outSISIDXREG(SISSR
, reg
, data
);
217 static uint8_t vblank_active_CRT1(void)
219 /* this may be too simplistic? */
220 return inSISREG(SISINPSTAT
) & 0x08;
223 static uint8_t vblank_active_CRT2(void)
226 if (sis_vga_engine
== SIS_315_VGA
) {
227 inSISIDXREG(SISPART1
, Index_310_CRT2_FC_VR
, ret
);
229 inSISIDXREG(SISPART1
, Index_CRT2_FC_VR
, ret
);
231 return (ret
& 0x02) ^ 0x02;
234 static int find_chip(unsigned chip_id
)
237 for (i
= 0; i
< sizeof(sis_card_ids
) / sizeof(unsigned short); i
++) {
238 if (chip_id
== sis_card_ids
[i
])
244 static int sis_probe(int verbose
, int force
)
246 pciinfo_t lst
[MAX_PCI_DEVICES
];
250 sis_verbose
= verbose
;
252 err
= pci_scan(lst
, &num_pci
);
254 printf("[SiS] Error occurred during pci scan: %s\n", strerror(err
));
258 for (i
= 0; i
< num_pci
; i
++) {
259 if (lst
[i
].vendor
== VENDOR_SIS
) {
262 idx
= find_chip(lst
[i
].device
);
265 dname
= pci_device_name(VENDOR_SIS
, lst
[i
].device
);
266 dname
= dname
? dname
: "Unknown chip";
268 printf("[SiS] Found chip: %s (0x%X)\n",
269 dname
, lst
[i
].device
);
270 sis_device_id
= sis_cap
.device_id
= lst
[i
].device
;
272 memcpy(&pci_info
, &lst
[i
], sizeof(pciinfo_t
));
274 sis_has_two_overlays
= 0;
275 switch (sis_cap
.device_id
) {
277 case DEVICE_SIS_630_VGA
:
278 sis_has_two_overlays
= 1;
279 case DEVICE_SIS_540_VGA
:
280 sis_vga_engine
= SIS_300_VGA
;
283 case DEVICE_SIS_550_VGA
:
284 sis_has_two_overlays
= 1;
285 case DEVICE_SIS_315H
:
287 case DEVICE_SIS_315PRO
:
288 case DEVICE_SIS_650_VGA
:
289 /* M650 & 651 have 2 overlays */
290 /* JCP: I think this works, but not really tested yet */
291 if (enable_app_io() == 0 )
294 unsigned char tempreg1
, tempreg2
;
296 inSISIDXREG(SISCR
, 0x5F, CR5F
);
298 andSISIDXREG(SISCR
, 0x5c, 0x07);
299 inSISIDXREG(SISCR
, 0x5c, tempreg1
);
301 setSISIDXREG(SISCR
, 0x5c, 0x07, 0xf8);
302 inSISIDXREG(SISCR
, 0x5c, tempreg2
);
304 if ((!tempreg1
) || (tempreg2
)) {
306 sis_has_two_overlays
= 1;
309 sis_has_two_overlays
= 1; /* ? */
311 if (sis_has_two_overlays
) {
314 ("[SiS] detected M650/651 with 2 overlays\n");
318 sis_vga_engine
= SIS_315_VGA
;
321 /* should never get here */
322 sis_vga_engine
= UNKNOWN_VGA
;
328 if (err
&& sis_verbose
) {
329 printf("[SiS] Can't find chip\n");
337 static int sis_init(void)
339 uint8_t sr_data
, cr_data
, cr_data2
;
340 char *env_overlay_crt
;
343 printf("[SiS] driver was not probed but is being initialized\n");
347 if (enable_app_io() != 0)
349 printf("[SiS] can't enable register I/O\n");
353 /* JCP: this is WRONG. Need to coordinate w/ sisfb to use correct mem */
354 /* map 16MB scary hack for now. */
355 sis_mem_base
= map_phys_mem(pci_info
.base0
, 0x1000000);
356 /* sis_reg_base = map_phys_mem(pci_info.base1, 0x20000); */
357 sis_iobase
= pci_info
.base2
& 0xFFFC;
359 /* would like to use fb ioctl - or some other method - here to get
360 current resolution. */
361 inSISIDXREG(SISCR
, 0x12, cr_data
);
362 inSISIDXREG(SISCR
, 0x07, cr_data2
);
364 ((cr_data
& 0xff) | ((uint16_t) (cr_data2
& 0x02) << 7) |
365 ((uint16_t) (cr_data2
& 0x40) << 3) | ((uint16_t) (cr_data
& 0x02)
368 inSISIDXREG(SISSR
, 0x0b, sr_data
);
369 inSISIDXREG(SISCR
, 0x01, cr_data
);
370 sis_screen_width
= (((cr_data
& 0xff) |
371 ((uint16_t) (sr_data
& 0x0C) << 6)) + 1) * 8;
373 inSISIDXREG(SISSR
, Index_SR_Graphic_Mode
, sr_data
);
374 if (sr_data
& 0x20) /* interlaced mode */
375 sis_vmode
|= VMODE_INTERLACED
;
377 /* JCP: eventually I'd like to replace this with a call to sisfb
378 SISFB_GET_INFO ioctl to get video bridge info. Not for now,
379 since it requires a very new and not widely distributed version. */
380 sis_init_video_bridge();
382 env_overlay_crt
= getenv("VIDIX_CRT");
383 if (env_overlay_crt
) {
384 int crt
= atoi(env_overlay_crt
);
385 if (crt
== 1 || crt
== 2) {
386 sis_overlay_on_crt1
= (crt
== 1);
387 if (sis_verbose
> 0) {
389 ("[SiS] override: using overlay on CRT%d from VIDIX_CRT\n",
398 static void sis_destroy(void)
400 /* unmap_phys_mem(sis_reg_base, 0x20000); */
401 /* JCP: see above, hence also a hack. */
402 unmap_phys_mem(sis_mem_base
, 0x1000000);
406 static int sis_get_caps(vidix_capability_t
* to
)
408 memcpy(to
, &sis_cap
, sizeof(vidix_capability_t
));
412 static int is_supported_fourcc(uint32_t fourcc
)
427 static int sis_query_fourcc(vidix_fourcc_t
* to
)
429 if (is_supported_fourcc(to
->fourcc
)) {
430 to
->depth
= VID_DEPTH_8BPP
| VID_DEPTH_16BPP
| VID_DEPTH_32BPP
;
431 to
->flags
= VID_CAP_EXPAND
| VID_CAP_SHRINK
| VID_CAP_COLORKEY
;
434 to
->depth
= to
->flags
= 0;
438 static int bridge_in_slave_mode(void)
440 unsigned char usScratchP1_00
;
442 if (!(sis_vbflags
& VB_VIDEOBRIDGE
))
445 inSISIDXREG(SISPART1
, 0x00, usScratchP1_00
);
446 if (((sis_vga_engine
== SIS_300_VGA
)
447 && (usScratchP1_00
& 0xa0) == 0x20)
448 || ((sis_vga_engine
== SIS_315_VGA
)
449 && (usScratchP1_00
& 0x50) == 0x10)) {
456 /* This does not handle X dual head mode, since 1) vidix doesn't support it
457 and 2) it doesn't make sense for other gfx drivers */
458 static void set_dispmode(void)
460 sis_bridge_is_slave
= 0;
462 if (bridge_in_slave_mode())
463 sis_bridge_is_slave
= 1;
465 if ((sis_vbflags
& VB_DISPMODE_MIRROR
) ||
466 (sis_bridge_is_slave
&& (sis_vbflags
& DISPTYPE_DISP2
))) {
467 if (sis_has_two_overlays
)
468 sis_displaymode
= DISPMODE_MIRROR
; /* TW: CRT1+CRT2 (2 overlays) */
469 else if (!sis_overlay_on_crt1
)
470 sis_displaymode
= DISPMODE_SINGLE2
;
472 sis_displaymode
= DISPMODE_SINGLE1
;
474 if (sis_vbflags
& DISPTYPE_DISP1
) {
475 sis_displaymode
= DISPMODE_SINGLE1
; /* TW: CRT1 only */
477 sis_displaymode
= DISPMODE_SINGLE2
; /* TW: CRT2 only */
482 static void set_disptype_regs(void)
484 switch (sis_displaymode
) {
485 case DISPMODE_SINGLE1
: /* TW: CRT1 only */
486 if (sis_verbose
> 2) {
487 printf("[SiS] Setting up overlay on CRT1\n");
489 if (sis_has_two_overlays
) {
490 setsrregmask(0x06, 0x00, 0xc0);
491 setsrregmask(0x32, 0x00, 0xc0);
493 setsrregmask(0x06, 0x00, 0xc0);
494 setsrregmask(0x32, 0x00, 0xc0);
497 case DISPMODE_SINGLE2
: /* TW: CRT2 only */
498 if (sis_verbose
> 2) {
499 printf("[SiS] Setting up overlay on CRT2\n");
501 if (sis_has_two_overlays
) {
502 setsrregmask(0x06, 0x80, 0xc0);
503 setsrregmask(0x32, 0x80, 0xc0);
505 setsrregmask(0x06, 0x40, 0xc0);
506 setsrregmask(0x32, 0x40, 0xc0);
509 case DISPMODE_MIRROR
: /* TW: CRT1 + CRT2 */
511 if (sis_verbose
> 2) {
512 printf("[SiS] Setting up overlay on CRT1 AND CRT2!\n");
514 setsrregmask(0x06, 0x80, 0xc0);
515 setsrregmask(0x32, 0x80, 0xc0);
520 static void init_overlay(void)
522 /* Initialize first overlay (CRT1) */
524 /* Write-enable video registers */
525 setvideoregmask(Index_VI_Control_Misc2
, 0x80, 0x81);
527 /* Disable overlay */
528 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
530 /* Disable bobEnable */
531 setvideoregmask(Index_VI_Control_Misc1
, 0x02, 0x02);
533 /* Reset scale control and contrast */
534 setvideoregmask(Index_VI_Scale_Control
, 0x60, 0x60);
535 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x1F);
537 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low
, 0x00);
538 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle
, 0x00);
539 setvideoreg(Index_VI_UV_Buf_Preset_Low
, 0x00);
540 setvideoreg(Index_VI_UV_Buf_Preset_Middle
, 0x00);
541 setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High
, 0x00);
542 setvideoreg(Index_VI_Play_Threshold_Low
, 0x00);
543 setvideoreg(Index_VI_Play_Threshold_High
, 0x00);
545 /* may not want to init these here, could already be set to other
547 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
548 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x07);
549 setvideoreg(Index_VI_Brightness
, 0x20);
550 if (sis_vga_engine
== SIS_315_VGA
) {
551 setvideoreg(Index_VI_Hue
, 0x00);
552 setvideoreg(Index_VI_Saturation
, 0x00);
555 /* Initialize second overlay (CRT2) */
556 if (sis_has_two_overlays
) {
557 /* Write-enable video registers */
558 setvideoregmask(Index_VI_Control_Misc2
, 0x81, 0x81);
560 /* Disable overlay */
561 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
563 /* Disable bobEnable */
564 setvideoregmask(Index_VI_Control_Misc1
, 0x02, 0x02);
566 /* Reset scale control and contrast */
567 setvideoregmask(Index_VI_Scale_Control
, 0x60, 0x60);
568 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x1F);
570 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low
, 0x00);
571 setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle
, 0x00);
572 setvideoreg(Index_VI_UV_Buf_Preset_Low
, 0x00);
573 setvideoreg(Index_VI_UV_Buf_Preset_Middle
, 0x00);
574 setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High
, 0x00);
575 setvideoreg(Index_VI_Play_Threshold_Low
, 0x00);
576 setvideoreg(Index_VI_Play_Threshold_High
, 0x00);
578 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x01);
579 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, 0x04, 0x07);
580 setvideoreg(Index_VI_Brightness
, 0x20);
581 if (sis_vga_engine
== SIS_315_VGA
) {
582 setvideoreg(Index_VI_Hue
, 0x00);
583 setvideoreg(Index_VI_Saturation
, 0x00);
588 static int sis_set_eq(const vidix_video_eq_t
* eq
);
590 static int sis_config_playback(vidix_playback_t
* info
)
592 SISOverlayRec overlay
;
593 int srcOffsetX
= 0, srcOffsetY
= 0;
595 int index
= 0, iscrt2
= 0;
606 if (!is_supported_fourcc(info
->fourcc
))
609 /* set chipset/engine.dependent config info */
610 /* which CRT to use, etc.? */
611 switch (sis_vga_engine
) {
614 sis_equal
.cap
|= VEQ_CAP_SATURATION
| VEQ_CAP_HUE
;
622 sis_displaymode
= DISPMODE_SINGLE1
; /* xV driver code in set_dispmode() */
629 /* get basic dimension info */
635 drw_x
= info
->dest
.x
;
636 drw_y
= info
->dest
.y
;
637 drw_w
= info
->dest
.w
;
638 drw_h
= info
->dest
.h
;
640 switch (info
->fourcc
) {
643 pitch
= (src_w
+ 7) & ~7;
644 total_size
= (pitch
* src_h
* 3) >> 1;
650 pitch
= ((src_w
<< 1) + 3) & ~3;
651 total_size
= pitch
* src_h
;
657 /* "allocate" memory for overlay! */
658 /* start at 8MB = sisfb's "dri reserved space" -
659 really shouldn't hardcode though */
660 /* XXX: JCP - this can use the sisfb FBIO_ALLOC ioctl to safely
661 allocate "video heap" memory... */
662 dga_offset
= 0x800000;
664 /* use 7MB for now. need to calc/get real info from sisfb? */
665 /* this can result in a LOT of frames - probably not necessary */
666 info
->num_frames
= 0x700000 / (total_size
* 2);
667 if (info
->num_frames
> VID_PLAY_MAXFRAMES
)
668 info
->num_frames
= VID_PLAY_MAXFRAMES
;
670 info
->dga_addr
= sis_mem_base
+ dga_offset
;
671 info
->dest
.pitch
.y
= 16;
672 info
->dest
.pitch
.u
= 16;
673 info
->dest
.pitch
.v
= 16;
677 info
->frame_size
= (total_size
* 2); /* why times 2 ? */
678 for (i
= 0; i
< info
->num_frames
; i
++) {
679 info
->offsets
[i
] = info
->frame_size
* i
;
680 /* save ptrs to mem buffers */
681 sis_frames
[i
] = (dga_offset
+ info
->offsets
[i
]);
684 memset(&overlay
, 0, sizeof(overlay
));
685 overlay
.pixelFormat
= sis_format
= info
->fourcc
;
686 overlay
.pitch
= overlay
.origPitch
= pitch
;
689 overlay
.keyOP
= (sis_grkey
.ckey
.op
== CKEY_TRUE
?
690 VI_ROP_DestKey
: VI_ROP_Always
);
692 overlay
.bobEnable
= 0x00;
694 overlay
.SCREENheight
= sis_screen_height
;
696 /* probably will not support X virtual screen > phys very well? */
697 overlay
.dstBox
.x1
= drw_x
; /* - pScrn->frameX0; */
698 overlay
.dstBox
.x2
= drw_x
+ drw_w
; /* - pScrn->frameX0; ??? */
699 overlay
.dstBox
.y1
= drw_y
; /* - pScrn->frameY0; */
700 overlay
.dstBox
.y2
= drw_y
+ drw_h
; /* - pScrn->frameY0; ??? */
702 if ((overlay
.dstBox
.x1
> overlay
.dstBox
.x2
) ||
703 (overlay
.dstBox
.y1
> overlay
.dstBox
.y2
))
706 if ((overlay
.dstBox
.x2
< 0) || (overlay
.dstBox
.y2
< 0))
709 if (overlay
.dstBox
.x1
< 0) {
710 srcOffsetX
= src_w
* (-overlay
.dstBox
.x1
) / drw_w
;
711 overlay
.dstBox
.x1
= 0;
713 if (overlay
.dstBox
.y1
< 0) {
714 srcOffsetY
= src_h
* (-overlay
.dstBox
.y1
) / drw_h
;
715 overlay
.dstBox
.y1
= 0;
718 switch (info
->fourcc
) {
720 info
->dest
.pitch
.y
= 16;
721 sx
= (src_x
+ srcOffsetX
) & ~7;
722 sy
= (src_y
+ srcOffsetY
) & ~1;
723 info
->offset
.y
= sis_Yoff
= sx
+ sy
* pitch
;
724 /* JCP: NOTE reversed u & v here! Not sure why this is needed.
725 maybe mplayer & sis define U & V differently?? */
726 info
->offset
.u
= sis_Voff
=
727 src_h
* pitch
+ ((sx
+ sy
* pitch
/ 2) >> 1);
728 info
->offset
.v
= sis_Uoff
=
729 src_h
* pitch
* 5 / 4 + ((sx
+ sy
* pitch
/ 2) >> 1);
731 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
732 overlay
.PSV
= (sis_frames
[0] + sis_Voff
) >> sis_shift_value
;
733 overlay
.PSU
= (sis_frames
[0] + sis_Uoff
) >> sis_shift_value
;
736 sx
= (src_x
+ srcOffsetX
) & ~7;
737 sy
= (src_y
+ srcOffsetY
) & ~1;
738 info
->offset
.y
= sis_Yoff
= sx
+ sy
* pitch
;
739 /* JCP: see above... */
740 info
->offset
.u
= sis_Voff
=
741 src_h
* pitch
* 5 / 4 + ((sx
+ sy
* pitch
/ 2) >> 1);
742 info
->offset
.v
= sis_Uoff
=
743 src_h
* pitch
+ ((sx
+ sy
* pitch
/ 2) >> 1);
745 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
746 overlay
.PSV
= (sis_frames
[0] + sis_Voff
) >> sis_shift_value
;
747 overlay
.PSU
= (sis_frames
[0] + sis_Uoff
) >> sis_shift_value
;
754 sx
= (src_x
+ srcOffsetX
) & ~1;
755 sy
= (src_y
+ srcOffsetY
);
756 info
->offset
.y
= sis_Yoff
= sx
* 2 + sy
* pitch
;
758 overlay
.PSY
= (sis_frames
[0] + sis_Yoff
) >> sis_shift_value
;
762 /* FIXME: is it possible that srcW < 0? */
763 overlay
.srcW
= src_w
- (sx
- src_x
);
764 overlay
.srcH
= src_h
- (sy
- src_y
);
766 /* set merge line buffer */
767 merge_line_buf(overlay
.srcW
> 384);
769 /* calculate line buffer length */
770 set_line_buf_size(&overlay
);
772 if (sis_displaymode
== DISPMODE_SINGLE2
) {
773 if (sis_has_two_overlays
) {
774 /* TW: On chips with two overlays we use
775 * overlay 2 for CRT2 */
779 /* TW: On chips with only one overlay we
780 * use that only overlay for CRT2 */
784 overlay
.VBlankActiveFunc
= vblank_active_CRT2
;
785 /* overlay.GetScanLineFunc = get_scanline_CRT2; */
789 overlay
.VBlankActiveFunc
= vblank_active_CRT1
;
790 /* overlay.GetScanLineFunc = get_scanline_CRT1; */
793 /* calc scale factor (to use below) */
794 calc_scale_factor(&overlay
, index
, iscrt2
);
796 /* Select video1 (used for CRT1) or video2 (used for CRT2) */
797 setvideoregmask(Index_VI_Control_Misc2
, index
, 0x01);
799 set_format(&overlay
);
803 sis_set_eq(&sis_equal
);
805 /* set up video overlay registers */
806 set_overlay(&overlay
, index
);
808 /* prevent badness if bits are not at default setting */
809 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x01);
810 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x04);
812 /* JCP: Xv driver implementation loops back over above code to
818 static int sis_playback_on(void)
820 setvideoregmask(Index_VI_Control_Misc0
, 0x02, 0x02);
824 static int sis_playback_off(void)
826 unsigned char sridx
, cridx
;
827 sridx
= inSISREG(SISSR
);
828 cridx
= inSISREG(SISCR
);
830 outSISREG(SISSR
, sridx
);
831 outSISREG(SISCR
, cridx
);
836 static int sis_frame_select(unsigned int frame
)
842 if (sis_displaymode
== DISPMODE_SINGLE2
&& sis_has_two_overlays
) {
846 PSY
= (sis_frames
[frame
] + sis_Yoff
) >> sis_shift_value
;
848 /* Unlock address registers */
849 data
= getvideoreg(Index_VI_Control_Misc1
);
850 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
851 /* TEST: Is this required? */
852 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
854 /* TEST: Is this required? */
855 if (sis_vga_engine
== SIS_315_VGA
)
856 setvideoreg(Index_VI_Control_Misc3
, 0x00);
859 /* set Y start address */
860 setvideoreg(Index_VI_Disp_Y_Buf_Start_Low
, (uint8_t) (PSY
));
861 setvideoreg(Index_VI_Disp_Y_Buf_Start_Middle
, (uint8_t) ((PSY
) >> 8));
862 setvideoreg(Index_VI_Disp_Y_Buf_Start_High
, (uint8_t) ((PSY
) >> 16));
863 /* set 310/325 series overflow bits for Y plane */
864 if (sis_vga_engine
== SIS_315_VGA
) {
865 setvideoreg(Index_VI_Y_Buf_Start_Over
,
866 ((uint8_t) ((PSY
) >> 24) & 0x01));
869 /* Set U/V data if using plane formats */
870 if ((sis_format
== IMGFMT_YV12
) || (sis_format
== IMGFMT_I420
)) {
874 PSU
= (sis_frames
[frame
] + sis_Uoff
) >> sis_shift_value
;
875 PSV
= (sis_frames
[frame
] + sis_Voff
) >> sis_shift_value
;
877 /* set U/V start address */
878 setvideoreg(Index_VI_U_Buf_Start_Low
, (uint8_t) PSU
);
879 setvideoreg(Index_VI_U_Buf_Start_Middle
, (uint8_t) (PSU
>> 8));
880 setvideoreg(Index_VI_U_Buf_Start_High
, (uint8_t) (PSU
>> 16));
882 setvideoreg(Index_VI_V_Buf_Start_Low
, (uint8_t) PSV
);
883 setvideoreg(Index_VI_V_Buf_Start_Middle
, (uint8_t) (PSV
>> 8));
884 setvideoreg(Index_VI_V_Buf_Start_High
, (uint8_t) (PSV
>> 16));
886 /* 310/325 series overflow bits */
887 if (sis_vga_engine
== SIS_315_VGA
) {
888 setvideoreg(Index_VI_U_Buf_Start_Over
,
889 ((uint8_t) (PSU
>> 24) & 0x01));
890 setvideoreg(Index_VI_V_Buf_Start_Over
,
891 ((uint8_t) (PSV
>> 24) & 0x01));
895 if (sis_vga_engine
== SIS_315_VGA
) {
896 /* Trigger register copy for 310 series */
897 setvideoreg(Index_VI_Control_Misc3
, 1 << index
);
900 /* Lock the address registers */
901 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x20);
906 static int sis_get_gkeys(vidix_grkey_t
* grkey
)
908 memcpy(grkey
, &sis_grkey
, sizeof(vidix_grkey_t
));
912 static int sis_set_gkeys(const vidix_grkey_t
* grkey
)
914 memcpy(&sis_grkey
, grkey
, sizeof(vidix_grkey_t
));
919 static int sis_get_eq(vidix_video_eq_t
* eq
)
921 memcpy(eq
, &sis_equal
, sizeof(vidix_video_eq_t
));
925 static int sis_set_eq(const vidix_video_eq_t
* eq
)
927 int br
, sat
, cr
, hue
;
928 if (eq
->cap
& VEQ_CAP_BRIGHTNESS
)
929 sis_equal
.brightness
= eq
->brightness
;
930 if (eq
->cap
& VEQ_CAP_CONTRAST
)
931 sis_equal
.contrast
= eq
->contrast
;
932 if (eq
->cap
& VEQ_CAP_SATURATION
)
933 sis_equal
.saturation
= eq
->saturation
;
934 if (eq
->cap
& VEQ_CAP_HUE
)
935 sis_equal
.hue
= eq
->hue
;
936 if (eq
->cap
& VEQ_CAP_RGB_INTENSITY
) {
937 sis_equal
.red_intensity
= eq
->red_intensity
;
938 sis_equal
.green_intensity
= eq
->green_intensity
;
939 sis_equal
.blue_intensity
= eq
->blue_intensity
;
941 sis_equal
.flags
= eq
->flags
;
943 cr
= (sis_equal
.contrast
+ 1000) * 7 / 2000;
949 br
= sis_equal
.brightness
* 127 / 1000;
955 sat
= (sis_equal
.saturation
* 7) / 1000;
961 hue
= sis_equal
.hue
* 7 / 1000;
969 if (sis_vga_engine
== SIS_315_VGA
) {
977 static void set_overlay(SISOverlayPtr pOverlay
, int index
)
980 uint8_t h_over
= 0, v_over
= 0;
981 uint16_t top
, bottom
, left
, right
;
982 uint16_t screenX
= sis_screen_width
;
983 uint16_t screenY
= sis_screen_height
;
987 top
= pOverlay
->dstBox
.y1
;
988 bottom
= pOverlay
->dstBox
.y2
;
989 if (bottom
> screenY
) {
993 left
= pOverlay
->dstBox
.x1
;
994 right
= pOverlay
->dstBox
.x2
;
995 if (right
> screenX
) {
999 /* JCP: these aren't really tested... */
1000 /* TW: DoubleScan modes require Y coordinates * 2 */
1001 if (sis_vmode
& VMODE_DOUBLESCAN
) {
1005 /* TW: Interlace modes require Y coordinates / 2 */
1006 if (sis_vmode
& VMODE_INTERLACED
) {
1011 h_over
= (((left
>> 8) & 0x0f) | ((right
>> 4) & 0xf0));
1012 v_over
= (((top
>> 8) & 0x0f) | ((bottom
>> 4) & 0xf0));
1014 pitch
= pOverlay
->pitch
>> sis_shift_value
;
1016 /* set line buffer size */
1017 setvideoreg(Index_VI_Line_Buffer_Size
, pOverlay
->lineBufSize
);
1019 /* set color key mode */
1020 setvideoregmask(Index_VI_Key_Overlay_OP
, pOverlay
->keyOP
, 0x0F);
1022 /* TW: We don't have to wait for vertical retrace in all cases */
1023 /* JCP: be safe for now. */
1024 if (1 /*pPriv->mustwait */ ) {
1025 watchdog
= WATCHDOG_DELAY
;
1026 while (pOverlay
->VBlankActiveFunc() && --watchdog
);
1027 watchdog
= WATCHDOG_DELAY
;
1028 while ((!pOverlay
->VBlankActiveFunc()) && --watchdog
);
1029 if (!watchdog
&& sis_verbose
> 0) {
1030 printf("[SiS]: timed out waiting for vertical retrace\n");
1034 /* Unlock address registers */
1035 data
= getvideoreg(Index_VI_Control_Misc1
);
1036 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
1037 /* TEST: Is this required? */
1038 setvideoreg(Index_VI_Control_Misc1
, data
| 0x20);
1041 /* TEST: Is this required? */
1042 if (sis_vga_engine
== SIS_315_VGA
)
1043 setvideoreg(Index_VI_Control_Misc3
, 0x00);
1046 /* Set Y buf pitch */
1047 setvideoreg(Index_VI_Disp_Y_Buf_Pitch_Low
, (uint8_t) (pitch
));
1048 setvideoregmask(Index_VI_Disp_Y_UV_Buf_Pitch_Middle
,
1049 (uint8_t) (pitch
>> 8), 0x0f);
1051 /* Set Y start address */
1052 setvideoreg(Index_VI_Disp_Y_Buf_Start_Low
, (uint8_t) (pOverlay
->PSY
));
1053 setvideoreg(Index_VI_Disp_Y_Buf_Start_Middle
,
1054 (uint8_t) ((pOverlay
->PSY
) >> 8));
1055 setvideoreg(Index_VI_Disp_Y_Buf_Start_High
,
1056 (uint8_t) ((pOverlay
->PSY
) >> 16));
1058 /* set 310/325 series overflow bits for Y plane */
1059 if (sis_vga_engine
== SIS_315_VGA
) {
1060 setvideoreg(Index_VI_Disp_Y_Buf_Pitch_High
,
1061 (uint8_t) (pitch
>> 12));
1062 setvideoreg(Index_VI_Y_Buf_Start_Over
,
1063 ((uint8_t) ((pOverlay
->PSY
) >> 24) & 0x01));
1066 /* Set U/V data if using plane formats */
1067 if ((pOverlay
->pixelFormat
== IMGFMT_YV12
) ||
1068 (pOverlay
->pixelFormat
== IMGFMT_I420
)) {
1072 PSU
= pOverlay
->PSU
;
1073 PSV
= pOverlay
->PSV
;
1076 setvideoreg(Index_VI_Disp_UV_Buf_Pitch_Low
,
1077 (uint8_t) (pitch
>> 1));
1078 setvideoregmask(Index_VI_Disp_Y_UV_Buf_Pitch_Middle
,
1079 (uint8_t) (pitch
>> 5), 0xf0);
1081 /* set U/V start address */
1082 setvideoreg(Index_VI_U_Buf_Start_Low
, (uint8_t) PSU
);
1083 setvideoreg(Index_VI_U_Buf_Start_Middle
, (uint8_t) (PSU
>> 8));
1084 setvideoreg(Index_VI_U_Buf_Start_High
, (uint8_t) (PSU
>> 16));
1086 setvideoreg(Index_VI_V_Buf_Start_Low
, (uint8_t) PSV
);
1087 setvideoreg(Index_VI_V_Buf_Start_Middle
, (uint8_t) (PSV
>> 8));
1088 setvideoreg(Index_VI_V_Buf_Start_High
, (uint8_t) (PSV
>> 16));
1090 /* 310/325 series overflow bits */
1091 if (sis_vga_engine
== SIS_315_VGA
) {
1092 setvideoreg(Index_VI_Disp_UV_Buf_Pitch_High
,
1093 (uint8_t) (pitch
>> 13));
1094 setvideoreg(Index_VI_U_Buf_Start_Over
,
1095 ((uint8_t) (PSU
>> 24) & 0x01));
1096 setvideoreg(Index_VI_V_Buf_Start_Over
,
1097 ((uint8_t) (PSV
>> 24) & 0x01));
1101 if (sis_vga_engine
== SIS_315_VGA
) {
1102 /* Trigger register copy for 310 series */
1103 setvideoreg(Index_VI_Control_Misc3
, 1 << index
);
1106 /* set scale factor */
1107 setvideoreg(Index_VI_Hor_Post_Up_Scale_Low
,
1108 (uint8_t) (pOverlay
->HUSF
));
1109 setvideoreg(Index_VI_Hor_Post_Up_Scale_High
,
1110 (uint8_t) ((pOverlay
->HUSF
) >> 8));
1111 setvideoreg(Index_VI_Ver_Up_Scale_Low
, (uint8_t) (pOverlay
->VUSF
));
1112 setvideoreg(Index_VI_Ver_Up_Scale_High
,
1113 (uint8_t) ((pOverlay
->VUSF
) >> 8));
1115 setvideoregmask(Index_VI_Scale_Control
, (pOverlay
->IntBit
<< 3)
1116 | (pOverlay
->wHPre
), 0x7f);
1118 /* set destination window position */
1119 setvideoreg(Index_VI_Win_Hor_Disp_Start_Low
, (uint8_t) left
);
1120 setvideoreg(Index_VI_Win_Hor_Disp_End_Low
, (uint8_t) right
);
1121 setvideoreg(Index_VI_Win_Hor_Over
, (uint8_t) h_over
);
1123 setvideoreg(Index_VI_Win_Ver_Disp_Start_Low
, (uint8_t) top
);
1124 setvideoreg(Index_VI_Win_Ver_Disp_End_Low
, (uint8_t) bottom
);
1125 setvideoreg(Index_VI_Win_Ver_Over
, (uint8_t) v_over
);
1127 setvideoregmask(Index_VI_Control_Misc1
, pOverlay
->bobEnable
, 0x1a);
1129 /* Lock the address registers */
1130 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x20);
1134 /* TW: Overlay MUST NOT be switched off while beam is over it */
1135 static void close_overlay(void)
1139 if ((sis_displaymode
== DISPMODE_SINGLE2
) ||
1140 (sis_displaymode
== DISPMODE_MIRROR
)) {
1141 if (sis_has_two_overlays
) {
1142 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x01);
1143 watchdog
= WATCHDOG_DELAY
;
1144 while (vblank_active_CRT2() && --watchdog
);
1145 watchdog
= WATCHDOG_DELAY
;
1146 while ((!vblank_active_CRT2()) && --watchdog
);
1147 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1148 watchdog
= WATCHDOG_DELAY
;
1149 while (vblank_active_CRT2() && --watchdog
);
1150 watchdog
= WATCHDOG_DELAY
;
1151 while ((!vblank_active_CRT2()) && --watchdog
);
1152 } else if (sis_displaymode
== DISPMODE_SINGLE2
) {
1153 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
1154 watchdog
= WATCHDOG_DELAY
;
1155 while (vblank_active_CRT1() && --watchdog
);
1156 watchdog
= WATCHDOG_DELAY
;
1157 while ((!vblank_active_CRT1()) && --watchdog
);
1158 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1159 watchdog
= WATCHDOG_DELAY
;
1160 while (vblank_active_CRT1() && --watchdog
);
1161 watchdog
= WATCHDOG_DELAY
;
1162 while ((!vblank_active_CRT1()) && --watchdog
);
1165 if ((sis_displaymode
== DISPMODE_SINGLE1
) ||
1166 (sis_displaymode
== DISPMODE_MIRROR
)) {
1167 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x01);
1168 watchdog
= WATCHDOG_DELAY
;
1169 while (vblank_active_CRT1() && --watchdog
);
1170 watchdog
= WATCHDOG_DELAY
;
1171 while ((!vblank_active_CRT1()) && --watchdog
);
1172 setvideoregmask(Index_VI_Control_Misc0
, 0x00, 0x02);
1173 watchdog
= WATCHDOG_DELAY
;
1174 while (vblank_active_CRT1() && --watchdog
);
1175 watchdog
= WATCHDOG_DELAY
;
1176 while ((!vblank_active_CRT1()) && --watchdog
);
1182 calc_scale_factor(SISOverlayPtr pOverlay
, int index
, int iscrt2
)
1184 uint32_t i
= 0, mult
= 0;
1187 int dstW
= pOverlay
->dstBox
.x2
- pOverlay
->dstBox
.x1
;
1188 int dstH
= pOverlay
->dstBox
.y2
- pOverlay
->dstBox
.y1
;
1189 int srcW
= pOverlay
->srcW
;
1190 int srcH
= pOverlay
->srcH
;
1191 /* uint16_t LCDheight = pSiS->LCDheight; */
1192 int srcPitch
= pOverlay
->origPitch
;
1193 int origdstH
= dstH
;
1195 /* get rid of warnings for now */
1199 /* TW: For double scan modes, we need to double the height
1200 * (Perhaps we also need to scale LVDS, but I'm not sure.)
1201 * On 310/325 series, we need to double the width as well.
1202 * Interlace mode vice versa.
1204 if (sis_vmode
& VMODE_DOUBLESCAN
) {
1205 dstH
= origdstH
<< 1;
1207 if (sis_vga_engine
== SIS_315_VGA
) {
1211 if (sis_vmode
& VMODE_INTERLACED
) {
1212 dstH
= origdstH
>> 1;
1216 if (dstW
< OVERLAY_MIN_WIDTH
)
1217 dstW
= OVERLAY_MIN_WIDTH
;
1219 pOverlay
->HUSF
= 0x00;
1220 pOverlay
->IntBit
= 0x05;
1221 pOverlay
->wHPre
= 0;
1222 } else if (dstW
> srcW
) {
1224 pOverlay
->HUSF
= (srcW
<< 16) / dstW
;
1225 pOverlay
->IntBit
= 0x04;
1226 pOverlay
->wHPre
= 0;
1230 /* TW: It seems, the hardware can't scale below factor .125 (=1/8) if the
1231 pitch isn't a multiple of 256.
1232 TODO: Test this on the 310/325 series!
1234 if ((srcPitch
% 256) || (srcPitch
< 256)) {
1235 if (((dstW
* 1000) / srcW
) < 125)
1236 dstW
= tmpW
= ((srcW
* 125) / 1000) + 1;
1240 pOverlay
->IntBit
= 0x01;
1241 while (srcW
>= tmpW
) {
1245 pOverlay
->wHPre
= (uint8_t) (i
- 1);
1248 pOverlay
->HUSF
= ((srcW
- dstW
) << 16) / dstW
;
1250 pOverlay
->HUSF
= 0x00;
1253 if (dstH
< OVERLAY_MIN_HEIGHT
)
1254 dstH
= OVERLAY_MIN_HEIGHT
;
1256 pOverlay
->VUSF
= 0x00;
1257 pOverlay
->IntBit
|= 0x0A;
1258 } else if (dstH
> srcH
) {
1260 pOverlay
->VUSF
= (srcH
<< 16) / dstH
;
1261 pOverlay
->IntBit
|= 0x08;
1265 i
= realI
= srcH
/ dstH
;
1266 pOverlay
->IntBit
|= 0x02;
1269 pOverlay
->VUSF
= ((srcH
- dstH
) << 16) / dstH
;
1270 /* TW: Needed for LCD-scaling modes */
1271 if ((flag
) && (mult
= (srcH
/ origdstH
)) >= 2)
1272 pOverlay
->pitch
/= mult
;
1274 if (((srcPitch
* i
) >> 2) > 0xFFF) {
1275 i
= (0xFFF * 2 / srcPitch
);
1276 pOverlay
->VUSF
= 0xFFFF;
1280 pOverlay
->VUSF
= ((srcH
- dstH
) << 16) / dstH
;
1282 pOverlay
->VUSF
= 0x00;
1284 /* set video frame buffer offset */
1285 pOverlay
->pitch
= (uint16_t) (srcPitch
* i
);
1290 static void set_line_buf_size(SISOverlayPtr pOverlay
)
1294 uint32_t line
= pOverlay
->srcW
;
1296 if ((pOverlay
->pixelFormat
== IMGFMT_YV12
) ||
1297 (pOverlay
->pixelFormat
== IMGFMT_I420
)) {
1298 preHIDF
= pOverlay
->wHPre
& 0x07;
1301 if ((line
& 0xffffff00) == line
)
1304 i
= (line
>> 8) + 1;
1305 pOverlay
->lineBufSize
= (uint8_t) (i
* 32 - 1);
1308 if ((line
& 0xfffffe00) == line
)
1311 i
= (line
>> 9) + 1;
1312 pOverlay
->lineBufSize
= (uint8_t) (i
* 64 - 1);
1315 if ((line
& 0xfffffc00) == line
)
1318 i
= (line
>> 10) + 1;
1319 pOverlay
->lineBufSize
= (uint8_t) (i
* 128 - 1);
1322 if ((line
& 0xfffff800) == line
)
1325 i
= (line
>> 11) + 1;
1326 pOverlay
->lineBufSize
= (uint8_t) (i
* 256 - 1);
1329 if ((line
& 0xffffff80) == line
)
1332 i
= (line
>> 7) + 1;
1333 pOverlay
->lineBufSize
= (uint8_t) (i
* 16 - 1);
1336 } else { /* YUV2, UYVY */
1337 if ((line
& 0xffffff8) == line
)
1340 i
= (line
>> 3) + 1;
1341 pOverlay
->lineBufSize
= (uint8_t) (i
- 1);
1345 static void merge_line_buf(int enable
)
1348 switch (sis_displaymode
) {
1349 case DISPMODE_SINGLE1
:
1350 if (sis_has_two_overlays
) {
1351 /* dual line merge */
1352 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1353 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1355 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1356 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1359 case DISPMODE_SINGLE2
:
1360 if (sis_has_two_overlays
) {
1362 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1363 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1365 setvideoregmask(Index_VI_Control_Misc2
, 0x10, 0x11);
1366 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1369 case DISPMODE_MIRROR
:
1372 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1373 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1374 if (sis_has_two_overlays
) {
1376 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1377 setvideoregmask(Index_VI_Control_Misc1
, 0x04, 0x04);
1382 switch (sis_displaymode
) {
1383 case DISPMODE_SINGLE1
:
1384 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1385 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1387 case DISPMODE_SINGLE2
:
1388 if (sis_has_two_overlays
) {
1389 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1390 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1392 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1393 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1396 case DISPMODE_MIRROR
:
1398 setvideoregmask(Index_VI_Control_Misc2
, 0x00, 0x11);
1399 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1400 if (sis_has_two_overlays
) {
1401 setvideoregmask(Index_VI_Control_Misc2
, 0x01, 0x11);
1402 setvideoregmask(Index_VI_Control_Misc1
, 0x00, 0x04);
1410 static void set_format(SISOverlayPtr pOverlay
)
1414 switch (pOverlay
->pixelFormat
) {
1425 case IMGFMT_RGB15
: /* D[5:4] : 00 RGB555, 01 RGB 565 */
1435 setvideoregmask(Index_VI_Control_Misc0
, fmt
, 0x7c);
1438 static void set_colorkey(void)
1442 b
= (uint8_t) sis_grkey
.ckey
.blue
;
1443 g
= (uint8_t) sis_grkey
.ckey
.green
;
1444 r
= (uint8_t) sis_grkey
.ckey
.red
;
1446 /* set color key mode */
1447 setvideoregmask(Index_VI_Key_Overlay_OP
,
1448 sis_grkey
.ckey
.op
== CKEY_TRUE
?
1449 VI_ROP_DestKey
: VI_ROP_Always
, 0x0F);
1451 /* set colorkey values */
1452 setvideoreg(Index_VI_Overlay_ColorKey_Blue_Min
, (uint8_t) b
);
1453 setvideoreg(Index_VI_Overlay_ColorKey_Green_Min
, (uint8_t) g
);
1454 setvideoreg(Index_VI_Overlay_ColorKey_Red_Min
, (uint8_t) r
);
1456 setvideoreg(Index_VI_Overlay_ColorKey_Blue_Max
, (uint8_t) b
);
1457 setvideoreg(Index_VI_Overlay_ColorKey_Green_Max
, (uint8_t) g
);
1458 setvideoreg(Index_VI_Overlay_ColorKey_Red_Max
, (uint8_t) r
);
1461 static void set_brightness(uint8_t brightness
)
1463 setvideoreg(Index_VI_Brightness
, brightness
);
1466 static void set_contrast(uint8_t contrast
)
1468 setvideoregmask(Index_VI_Contrast_Enh_Ctrl
, contrast
, 0x07);
1471 /* Next 3 functions are 310/325 series only */
1473 static void set_saturation(char saturation
)
1477 if (saturation
< 0) {
1479 saturation
= -saturation
;
1481 temp
|= (saturation
& 0x07);
1482 temp
|= ((saturation
& 0x07) << 4);
1484 setvideoreg(Index_VI_Saturation
, temp
);
1487 static void set_hue(uint8_t hue
)
1489 setvideoreg(Index_VI_Hue
, (hue
& 0x08) ? (hue
^ 0x07) : hue
);
1492 VDXDriver sis_drv
= {
1497 .get_caps
= sis_get_caps
,
1498 .query_fourcc
= sis_query_fourcc
,
1500 .destroy
= sis_destroy
,
1501 .config_playback
= sis_config_playback
,
1502 .playback_on
= sis_playback_on
,
1503 .playback_off
= sis_playback_off
,
1504 .frame_sel
= sis_frame_select
,
1505 .get_eq
= sis_get_eq
,
1506 .set_eq
= sis_set_eq
,
1507 .get_gkey
= sis_get_gkeys
,
1508 .set_gkey
= sis_set_gkeys
,