/*
* VIDIX driver for SiS chipsets.
* Copyright (C) 2003 Jake Page, Sugar Media.
*
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* MPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Based on SiS Xv driver
* Copyright 2002-2003 by Thomas Winischhofer, Vienna, Austria.
* 2003/10/08 integrated into mplayer/vidix architecture -- Alex Beregszaszi
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.h>
#include "vidix.h"
#include "vidixlib.h"
#include "fourcc.h"
#include "dha.h"
#include "pci_ids.h"
#include "pci_names.h"
#include "config.h"
#include "sis_regs.h"
#include "sis_defs.h"
/** Random defines **/
#define WATCHDOG_DELAY 500000 /* Watchdog counter for retrace waiting */
#define IMAGE_MIN_WIDTH 32 /* Min and max source image sizes */
#define IMAGE_MIN_HEIGHT 24
#define IMAGE_MAX_WIDTH 720
#define IMAGE_MAX_HEIGHT 576
#define IMAGE_MAX_WIDTH_M650 1920
#define IMAGE_MAX_HEIGHT_M650 1080
#define OVERLAY_MIN_WIDTH 32 /* Minimum overlay sizes */
#define OVERLAY_MIN_HEIGHT 24
#define DISPMODE_SINGLE1 0x1 /* TW: CRT1 only */
#define DISPMODE_SINGLE2 0x2 /* TW: CRT2 only */
#define DISPMODE_MIRROR 0x4 /* TW: CRT1 + CRT2 MIRROR */
#define VMODE_INTERLACED 0x1
#define VMODE_DOUBLESCAN 0x2
typedef struct {
short x1, y1, x2, y2;
} BoxRec;
typedef struct {
int pixelFormat;
uint16_t pitch;
uint16_t origPitch;
uint8_t keyOP;
uint16_t HUSF;
uint16_t VUSF;
uint8_t IntBit;
uint8_t wHPre;
uint16_t srcW;
uint16_t srcH;
BoxRec dstBox;
uint32_t PSY;
uint32_t PSV;
uint32_t PSU;
uint8_t bobEnable;
uint8_t contrastCtrl;
uint8_t contrastFactor;
uint8_t lineBufSize;
uint8_t(*VBlankActiveFunc) ();
uint16_t SCREENheight;
} SISOverlayRec, *SISOverlayPtr;
/** static variable definitions **/
static int sis_probed = 0;
static pciinfo_t pci_info;
unsigned int sis_verbose = 0;
static void *sis_mem_base;
/* static void *sis_reg_base; */
unsigned short sis_iobase;
unsigned int sis_vga_engine = UNKNOWN_VGA;
static unsigned int sis_displaymode = DISPMODE_SINGLE1;
static unsigned int sis_has_two_overlays = 0;
static unsigned int sis_bridge_is_slave = 0;
static unsigned int sis_shift_value = 1;
static unsigned int sis_vmode = 0;
unsigned int sis_vbflags = DISPTYPE_DISP1;
unsigned int sis_overlay_on_crt1 = 1;
int sis_crt1_off = -1;
unsigned int sis_detected_crt2_devices;
unsigned int sis_force_crt2_type = CRT2_DEFAULT;
int sis_device_id = -1;
static int sis_format;
static int sis_Yoff = 0;
static int sis_Voff = 0;
static int sis_Uoff = 0;
static int sis_screen_width = 640;
static int sis_screen_height = 480;
static int sis_frames[VID_PLAY_MAXFRAMES];
static vidix_grkey_t sis_grkey;
static vidix_capability_t sis_cap = {
"SiS 300/310/325 Video Driver",
"Jake Page",
TYPE_OUTPUT,
{0, 0, 0, 0},
2048,
2048,
4,
4,
-1,
FLAG_UPSCALER | FLAG_DOWNSCALER | FLAG_EQUALIZER,
VENDOR_SIS,
-1,
{0, 0, 0, 0}
};
static vidix_video_eq_t sis_equal = {
VEQ_CAP_BRIGHTNESS | VEQ_CAP_CONTRAST,
200, 0, 0, 0, 0, 0, 0, 0
};
static unsigned short sis_card_ids[] = {
DEVICE_SIS_300,
DEVICE_SIS_315H,
DEVICE_SIS_315,
DEVICE_SIS_315PRO,
DEVICE_SIS_330,
DEVICE_SIS_540_VGA,
DEVICE_SIS_550_VGA,
DEVICE_SIS_630_VGA,
DEVICE_SIS_650_VGA
};
/** function declarations **/
extern void sis_init_video_bridge(void);
static void set_overlay(SISOverlayPtr pOverlay, int index);
static void close_overlay(void);
static void calc_scale_factor(SISOverlayPtr pOverlay,
int index, int iscrt2);
static void set_line_buf_size(SISOverlayPtr pOverlay);
static void merge_line_buf(int enable);
static void set_format(SISOverlayPtr pOverlay);
static void set_colorkey(void);
static void set_brightness(uint8_t brightness);
static void set_contrast(uint8_t contrast);
static void set_saturation(char saturation);
static void set_hue(uint8_t hue);
/* IO Port access functions */
static uint8_t getvideoreg(uint8_t reg)
{
uint8_t ret;
inSISIDXREG(SISVID, reg, ret);
return (ret);
}
static void setvideoreg(uint8_t reg, uint8_t data)
{
outSISIDXREG(SISVID, reg, data);
}
static void setvideoregmask(uint8_t reg, uint8_t data, uint8_t mask)
{
uint8_t old;
inSISIDXREG(SISVID, reg, old);
data = (data & mask) | (old & (~mask));
outSISIDXREG(SISVID, reg, data);
}
static void setsrregmask(uint8_t reg, uint8_t data, uint8_t mask)
{
uint8_t old;
inSISIDXREG(SISSR, reg, old);
data = (data & mask) | (old & (~mask));
outSISIDXREG(SISSR, reg, data);
}
/* vblank checking*/
static uint8_t vblank_active_CRT1(void)
{
/* this may be too simplistic? */
return (inSISREG(SISINPSTAT) & 0x08);
}
static uint8_t vblank_active_CRT2(void)
{
uint8_t ret;
if (sis_vga_engine == SIS_315_VGA) {
inSISIDXREG(SISPART1, Index_310_CRT2_FC_VR, ret);
} else {
inSISIDXREG(SISPART1, Index_CRT2_FC_VR, ret);
}
return ((ret & 0x02) ^ 0x02);
}
static int find_chip(unsigned chip_id)
{
unsigned i;
for (i = 0; i < sizeof(sis_card_ids) / sizeof(unsigned short); i++) {
if (chip_id == sis_card_ids[i])
return i;
}
return -1;
}
static int sis_probe(int verbose, int force)
{
pciinfo_t lst[MAX_PCI_DEVICES];
unsigned i, num_pci;
int err;
sis_verbose = verbose;
force = force;
err = pci_scan(lst, &num_pci);
if (err) {
printf("[SiS] Error occurred during pci scan: %s\n", strerror(err));
return err;
} else {
err = ENXIO;
for (i = 0; i < num_pci; i++) {
if (lst[i].vendor == VENDOR_SIS) {
int idx;
const char *dname;
idx = find_chip(lst[i].device);
if (idx == -1)
continue;
dname = pci_device_name(VENDOR_SIS, lst[i].device);
dname = dname ? dname : "Unknown chip";
if (sis_verbose > 0)
printf("[SiS] Found chip: %s (0x%X)\n",
dname, lst[i].device);
sis_device_id = sis_cap.device_id = lst[i].device;
err = 0;
memcpy(&pci_info, &lst[i], sizeof(pciinfo_t));
sis_has_two_overlays = 0;
switch (sis_cap.device_id) {
case DEVICE_SIS_300:
case DEVICE_SIS_630_VGA:
sis_has_two_overlays = 1;
case DEVICE_SIS_540_VGA:
sis_vga_engine = SIS_300_VGA;
break;
case DEVICE_SIS_330:
case DEVICE_SIS_550_VGA:
sis_has_two_overlays = 1;
case DEVICE_SIS_315H:
case DEVICE_SIS_315:
case DEVICE_SIS_315PRO:
case DEVICE_SIS_650_VGA:
/* M650 & 651 have 2 overlays */
/* JCP: I think this works, but not really tested yet */
if (enable_app_io() == 0 )
{
unsigned char CR5F;
unsigned char tempreg1, tempreg2;
inSISIDXREG(SISCR, 0x5F, CR5F);
CR5F &= 0xf0;
andSISIDXREG(SISCR, 0x5c, 0x07);
inSISIDXREG(SISCR, 0x5c, tempreg1);
tempreg1 &= 0xf8;
setSISIDXREG(SISCR, 0x5c, 0x07, 0xf8);
inSISIDXREG(SISCR, 0x5c, tempreg2);
tempreg2 &= 0xf8;
if ((!tempreg1) || (tempreg2)) {
i
|