612 lines
18 KiB
C
612 lines
18 KiB
C
|
/*
|
||
|
* Copyright 2005-2016 The OpenChrome Project
|
||
|
* [https://www.freedesktop.org/wiki/Openchrome]
|
||
|
* Copyright 2004-2005 The Unichrome Project [unichrome.sf.net]
|
||
|
* Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
|
||
|
* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sub license,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice (including the
|
||
|
* next paragraph) shall be included in all copies or substantial portions
|
||
|
* of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
* DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* via_analog.c
|
||
|
*
|
||
|
* Handles the initialization and management of analog VGA related
|
||
|
* resources.
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#include "via_driver.h"
|
||
|
#include <unistd.h>
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Enables or disables analog (VGA) output.
|
||
|
*/
|
||
|
static void
|
||
|
viaAnalogPower(ScrnInfoPtr pScrn, Bool outputState)
|
||
|
{
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogPower.\n"));
|
||
|
|
||
|
viaAnalogSetPower(pScrn, outputState);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Analog (VGA) Power: %s\n",
|
||
|
outputState ? "On" : "Off");
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogPower.\n"));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Set analog (VGA) sync polarity.
|
||
|
*/
|
||
|
static void
|
||
|
viaAnalogSyncPolarity(ScrnInfoPtr pScrn, unsigned int flags)
|
||
|
{
|
||
|
CARD8 syncPolarity = 0x00;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogSyncPolarity.\n"));
|
||
|
|
||
|
if (flags & V_NHSYNC) {
|
||
|
syncPolarity |= BIT(0);
|
||
|
}
|
||
|
|
||
|
if (flags & V_NVSYNC) {
|
||
|
syncPolarity |= BIT(1);
|
||
|
}
|
||
|
|
||
|
viaAnalogSetSyncPolarity(pScrn, syncPolarity);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Analog (VGA) Horizontal Sync Polarity: %s\n",
|
||
|
(syncPolarity & BIT(0)) ? "-" : "+");
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Analog (VGA) Vertical Sync Polarity: %s\n",
|
||
|
(syncPolarity & BIT(1)) ? "-" : "+");
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogSyncPolarity.\n"));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Specifies IGA1 or IGA2 for analog VGA DAC source.
|
||
|
*/
|
||
|
static void
|
||
|
viaAnalogDisplaySource(ScrnInfoPtr pScrn, int index)
|
||
|
{
|
||
|
CARD8 displaySource = index;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogDisplaySource.\n"));
|
||
|
|
||
|
viaAnalogSetDisplaySource(pScrn, displaySource & 0x01);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Analog (VGA) Display Source: IGA%d\n",
|
||
|
(displaySource & 0x01) + 1);
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogDisplaySource.\n"));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Intializes analog VGA related registers.
|
||
|
*/
|
||
|
static void
|
||
|
viaAnalogInitReg(ScrnInfoPtr pScrn)
|
||
|
{
|
||
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
||
|
VIAPtr pVia = VIAPTR(pScrn);
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogInitReg.\n"));
|
||
|
|
||
|
/* 3X5.37[7] - DAC Power Save Control 1
|
||
|
* 0: Depend on Rx3X5.37[5:4] setting
|
||
|
* 1: DAC always goes into power save mode
|
||
|
* 3X5.37[6] - DAC Power Down Control
|
||
|
* 0: Depend on Rx3X5.47[2] setting
|
||
|
* 1: DAC never goes to power down mode
|
||
|
* 3X5.37[5:4] - DAC Power Save Control 2
|
||
|
* 00: DAC never goes to power save mode
|
||
|
* 01: DAC goes to power save mode by line
|
||
|
* 10: DAC goes to power save mode by frame
|
||
|
* 11: DAC goes to power save mode by line and frame
|
||
|
* 3X5.37[3] - DAC PEDESTAL Control
|
||
|
* 3X5.37[2:0] - DAC Factor
|
||
|
* (Default: 100) */
|
||
|
ViaCrtcMask(hwp, 0x37, 0x04, 0xFF);
|
||
|
|
||
|
switch (pVia->Chipset) {
|
||
|
case VIA_CX700:
|
||
|
case VIA_VX800:
|
||
|
case VIA_VX855:
|
||
|
case VIA_VX900:
|
||
|
/* Make sure 3C5.01[5] does not turn off analog (VGA) DAC. */
|
||
|
viaAnalogSetDACOff(pScrn, FALSE);
|
||
|
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogInitReg.\n"));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Detect a VGA connector.
|
||
|
*
|
||
|
* The code here was borrowed from VIA Technologies X.Org X Server
|
||
|
* DDX code. (In particular, from viaDetectCRTVsync function
|
||
|
* inside via_output.c.)
|
||
|
*/
|
||
|
static Bool
|
||
|
viaAnalogDetectConnector(ScrnInfoPtr pScrn)
|
||
|
{
|
||
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
||
|
VIAPtr pVia = VIAPTR(pScrn);
|
||
|
Bool connectorDetected = FALSE;
|
||
|
CARD8 sr40, cr36, cr37, cr43, cr44, cr47;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogDetectConnector.\n"));
|
||
|
|
||
|
sr40 = hwp->readSeq(hwp, 0x40);
|
||
|
cr36 = hwp->readCrtc(hwp, 0x36);
|
||
|
cr37 = hwp->readCrtc(hwp, 0x37);
|
||
|
cr43 = hwp->readCrtc(hwp, 0x43);
|
||
|
cr44 = hwp->readCrtc(hwp, 0x44);
|
||
|
cr47 = hwp->readCrtc(hwp, 0x47);
|
||
|
|
||
|
if ((pVia->Chipset == VIA_CX700)
|
||
|
|| (pVia->Chipset == VIA_VX800)
|
||
|
|| (pVia->Chipset == VIA_VX855)
|
||
|
|| (pVia->Chipset == VIA_VX900)) {
|
||
|
ViaCrtcMask(hwp, 0x43, 0x90, BIT(7) | BIT(6) | BIT(5) | BIT(4));
|
||
|
hwp->writeCrtc(hwp, 0x44, 0x00);
|
||
|
}
|
||
|
|
||
|
/* Turn on DAC. */
|
||
|
ViaCrtcMask(hwp, 0x37, 0x04, 0xff);
|
||
|
ViaCrtcMask(hwp, 0x47, 0x00, BIT(2));
|
||
|
|
||
|
/* Power On DPMS. */
|
||
|
ViaCrtcMask(hwp, 0x36, 0x00, BIT(7) | BIT(6) | BIT(5) | BIT(4));
|
||
|
|
||
|
/* Wait for vblank. */
|
||
|
usleep(16);
|
||
|
|
||
|
/* Enable CRT Sense. */
|
||
|
ViaSeqMask(hwp, 0x40, BIT(7), BIT(7));
|
||
|
|
||
|
if ((pVia->Chipset == VIA_CX700)
|
||
|
|| (pVia->Chipset == VIA_VX800)
|
||
|
|| (pVia->Chipset == VIA_VX855)
|
||
|
|| (pVia->Chipset == VIA_VX900)) {
|
||
|
ViaSeqMask(hwp, 0x40, 0x00, BIT(7));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
VT3324, VT3353: SR40[7]=1 --> SR40[7] = 0 --> check 3C2[4]
|
||
|
other: SR40[7]=1 --> check 3C2[4] --> SR40[7]=0
|
||
|
*/
|
||
|
if (hwp->readST00(hwp) & BIT(4)) {
|
||
|
connectorDetected = TRUE;
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"VGA connector detected.\n"));
|
||
|
} else {
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"VGA connector not detected.\n"));
|
||
|
}
|
||
|
|
||
|
if ((pVia->Chipset != VIA_CX700)
|
||
|
&& (pVia->Chipset != VIA_VX800)
|
||
|
&& (pVia->Chipset != VIA_VX855)
|
||
|
&& (pVia->Chipset != VIA_VX900)) {
|
||
|
ViaSeqMask(hwp, 0x40, 0x00, BIT(7));
|
||
|
}
|
||
|
|
||
|
/* Restore */
|
||
|
hwp->writeCrtc(hwp, 0x47, cr47);
|
||
|
|
||
|
if ((pVia->Chipset == VIA_CX700)
|
||
|
|| (pVia->Chipset == VIA_VX800)
|
||
|
|| (pVia->Chipset == VIA_VX855)
|
||
|
|| (pVia->Chipset == VIA_VX900)) {
|
||
|
hwp->writeCrtc(hwp, 0x44, cr44);
|
||
|
hwp->writeCrtc(hwp, 0x43, cr43);
|
||
|
}
|
||
|
|
||
|
hwp->writeCrtc(hwp, 0x37, cr37);
|
||
|
hwp->writeCrtc(hwp, 0x36, cr36);
|
||
|
hwp->writeSeq(hwp, 0x40, sr40);
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogDetectConnector.\n"));
|
||
|
return connectorDetected;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
via_analog_create_resources(xf86OutputPtr output)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_dpms(xf86OutputPtr output, int mode)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_dpms.\n"));
|
||
|
|
||
|
switch (mode) {
|
||
|
case DPMSModeOn:
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_ON);
|
||
|
viaAnalogPower(pScrn, TRUE);
|
||
|
break;
|
||
|
case DPMSModeStandby:
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_STANDBY);
|
||
|
viaAnalogPower(pScrn, TRUE);
|
||
|
break;
|
||
|
case DPMSModeSuspend:
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_SUSPEND);
|
||
|
viaAnalogPower(pScrn, TRUE);
|
||
|
break;
|
||
|
case DPMSModeOff:
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_OFF);
|
||
|
viaAnalogPower(pScrn, FALSE);
|
||
|
break;
|
||
|
default:
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"Invalid DPMS Mode: %d\n",
|
||
|
mode);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_dpms.\n"));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_save(xf86OutputPtr output)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_restore(xf86OutputPtr output)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
via_analog_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
|
||
|
if (!ViaModeDotClockTranslate(pScrn, pMode))
|
||
|
return MODE_NOCLOCK;
|
||
|
return MODE_OK;
|
||
|
}
|
||
|
|
||
|
static Bool
|
||
|
via_analog_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
|
||
|
DisplayModePtr adjusted_mode)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_prepare(xf86OutputPtr output)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_prepare.\n"));
|
||
|
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_OFF);
|
||
|
viaAnalogPower(pScrn, FALSE);
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_prepare.\n"));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_commit(xf86OutputPtr output)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_commit.\n"));
|
||
|
|
||
|
viaAnalogSetDPMSControl(pScrn, VIA_ANALOG_DPMS_ON);
|
||
|
viaAnalogPower(pScrn, TRUE);
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_commit.\n"));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
via_analog_mode_set(xf86OutputPtr output, DisplayModePtr mode,
|
||
|
DisplayModePtr adjusted_mode)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
drmmode_crtc_private_ptr iga = output->crtc->driver_private;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_mode_set.\n"));
|
||
|
|
||
|
if (output->crtc) {
|
||
|
viaAnalogInitReg(pScrn);
|
||
|
viaAnalogSyncPolarity(pScrn, adjusted_mode->Flags);
|
||
|
viaAnalogDisplaySource(pScrn, iga->index);
|
||
|
}
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_mode_set.\n"));
|
||
|
}
|
||
|
|
||
|
static xf86OutputStatus
|
||
|
via_analog_detect(xf86OutputPtr output)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
xf86OutputStatus status = XF86OutputStatusDisconnected;
|
||
|
Bool connectorDetected;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_detect.\n"));
|
||
|
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||
|
"Probing for a VGA connector . . .\n");
|
||
|
|
||
|
connectorDetected = viaAnalogDetectConnector(pScrn);
|
||
|
if (!connectorDetected) {
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||
|
"VGA connector not detected.\n");
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
status = XF86OutputStatusConnected;
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||
|
"VGA connector detected.\n");
|
||
|
exit:
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_detect.\n"));
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static DisplayModePtr
|
||
|
via_analog_get_modes(xf86OutputPtr output)
|
||
|
{
|
||
|
ScrnInfoPtr pScrn = output->scrn;
|
||
|
xf86MonPtr pMon;
|
||
|
DisplayModePtr pDisplay_Mode = NULL;
|
||
|
I2CBusPtr pI2CBus;
|
||
|
VIAPtr pVia = VIAPTR(pScrn);
|
||
|
VIADisplayPtr pVIADisplay = pVia->pVIADisplay;
|
||
|
VIAAnalogPtr pVIAAnalog = (VIAAnalogPtr) output->driver_private;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered via_analog_get_modes.\n"));
|
||
|
|
||
|
if (pVIAAnalog->i2cBus & VIA_I2C_BUS1) {
|
||
|
pI2CBus = pVIADisplay->pI2CBus1;
|
||
|
} else {
|
||
|
pI2CBus = NULL;
|
||
|
}
|
||
|
|
||
|
if (pI2CBus) {
|
||
|
pMon = xf86OutputGetEDID(output, pI2CBus);
|
||
|
if (pMon && (!pMon->features.input_type)) {
|
||
|
xf86OutputSetEDID(output, pMon);
|
||
|
pDisplay_Mode = xf86OutputGetEDIDModes(output);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||
|
"Detected a monitor connected to VGA.\n");
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pVIAAnalog->i2cBus & VIA_I2C_BUS2) {
|
||
|
pI2CBus = pVIADisplay->pI2CBus2;
|
||
|
} else {
|
||
|
pI2CBus = NULL;
|
||
|
}
|
||
|
|
||
|
if (pI2CBus) {
|
||
|
pMon = xf86OutputGetEDID(output, pI2CBus);
|
||
|
if (pMon && (!pMon->features.input_type)) {
|
||
|
xf86OutputSetEDID(output, pMon);
|
||
|
pDisplay_Mode = xf86OutputGetEDIDModes(output);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
|
||
|
"Detected a monitor connected to VGA.\n");
|
||
|
goto exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting via_analog_get_modes.\n"));
|
||
|
return pDisplay_Mode;
|
||
|
}
|
||
|
|
||
|
#ifdef RANDR_12_INTERFACE
|
||
|
static Bool
|
||
|
via_analog_set_property(xf86OutputPtr output, Atom property,
|
||
|
RRPropertyValuePtr value)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifdef RANDR_13_INTERFACE
|
||
|
static Bool
|
||
|
via_analog_get_property(xf86OutputPtr output, Atom property)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void
|
||
|
via_analog_destroy(xf86OutputPtr output)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static const xf86OutputFuncsRec via_analog_funcs = {
|
||
|
.create_resources = via_analog_create_resources,
|
||
|
.dpms = via_analog_dpms,
|
||
|
.save = via_analog_save,
|
||
|
.restore = via_analog_restore,
|
||
|
.mode_valid = via_analog_mode_valid,
|
||
|
.mode_fixup = via_analog_mode_fixup,
|
||
|
.prepare = via_analog_prepare,
|
||
|
.commit = via_analog_commit,
|
||
|
.mode_set = via_analog_mode_set,
|
||
|
.detect = via_analog_detect,
|
||
|
.get_modes = via_analog_get_modes,
|
||
|
#ifdef RANDR_12_INTERFACE
|
||
|
.set_property = via_analog_set_property,
|
||
|
#endif
|
||
|
#ifdef RANDR_13_INTERFACE
|
||
|
.get_property = via_analog_get_property,
|
||
|
#endif
|
||
|
.destroy = via_analog_destroy,
|
||
|
};
|
||
|
|
||
|
void
|
||
|
viaAnalogProbe(ScrnInfoPtr pScrn)
|
||
|
{
|
||
|
vgaHWPtr hwp = VGAHWPTR(pScrn);
|
||
|
VIAPtr pVia = VIAPTR(pScrn);
|
||
|
VIADisplayPtr pVIADisplay = pVia->pVIADisplay;
|
||
|
CARD8 sr13, sr5a;
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogProbe.\n"));
|
||
|
|
||
|
/* Detect the presence of VGA. */
|
||
|
switch (pVia->Chipset) {
|
||
|
case VIA_CX700:
|
||
|
case VIA_VX800:
|
||
|
case VIA_VX855:
|
||
|
case VIA_VX900:
|
||
|
sr5a = hwp->readSeq(hwp, 0x5A);
|
||
|
|
||
|
/* Setting SR5A[0] to 1.
|
||
|
* This allows the reading out the alternative
|
||
|
* pin strapping information from SR12 and SR13. */
|
||
|
ViaSeqMask(hwp, 0x5A, BIT(0), BIT(0));
|
||
|
|
||
|
sr13 = hwp->readSeq(hwp, 0x13);
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"SR13: 0x%02X\n", sr13));
|
||
|
if (!(sr13 & BIT(2))) {
|
||
|
pVIADisplay->analogPresence = TRUE;
|
||
|
pVIADisplay->analogI2CBus = VIA_I2C_BUS2 | VIA_I2C_BUS1;
|
||
|
pVIADisplay->mappedI2CBus |= VIA_I2C_BUS2 | VIA_I2C_BUS1;
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Detected the presence of VGA.\n"));
|
||
|
} else {
|
||
|
pVIADisplay->analogPresence = FALSE;
|
||
|
pVIADisplay->analogI2CBus = VIA_I2C_NONE;
|
||
|
}
|
||
|
|
||
|
hwp->writeSeq(hwp, 0x5A, sr5a);
|
||
|
break;
|
||
|
default:
|
||
|
/* For all other devices, assume VGA presence. */
|
||
|
pVIADisplay->analogPresence = TRUE;
|
||
|
pVIADisplay->analogI2CBus = VIA_I2C_BUS2 | VIA_I2C_BUS1;
|
||
|
pVIADisplay->mappedI2CBus |= VIA_I2C_BUS2 | VIA_I2C_BUS1;
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Detected the presence of VGA.\n"));
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogProbe.\n"));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
viaAnalogInit(ScrnInfoPtr pScrn)
|
||
|
{
|
||
|
xf86OutputPtr output;
|
||
|
VIAPtr pVia = VIAPTR(pScrn);
|
||
|
VIADisplayPtr pVIADisplay = pVia->pVIADisplay;
|
||
|
VIAAnalogPtr pVIAAnalog;
|
||
|
char outputNameBuffer[32];
|
||
|
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Entered viaAnalogInit.\n"));
|
||
|
|
||
|
if (!pVIADisplay->analogPresence) {
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
pVIAAnalog = (VIAAnalogPtr) xnfcalloc(1, sizeof(VIAAnalogRec));
|
||
|
if (!pVIAAnalog) {
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"Failed to allocate storage for "
|
||
|
"analog (VGA).\n"));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
/* The code to dynamically designate the output name for
|
||
|
* xrandr was borrowed from xf86-video-r128 DDX. */
|
||
|
sprintf(outputNameBuffer, "VGA-%d", (pVIADisplay->numberVGA + 1));
|
||
|
output = xf86OutputCreate(pScrn, &via_analog_funcs, outputNameBuffer);
|
||
|
if (!output) {
|
||
|
free(pVIAAnalog);
|
||
|
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
|
||
|
"Failed to allocate X Server display output "
|
||
|
"record for analog (VGA).\n");
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
/* Increment the number of analog VGA connectors. */
|
||
|
pVIADisplay->numberVGA++;
|
||
|
|
||
|
/* Hint about which I2C bus to access for obtaining EDID. */
|
||
|
pVIAAnalog->i2cBus = pVIADisplay->analogI2CBus;
|
||
|
|
||
|
output->driver_private = pVIAAnalog;
|
||
|
|
||
|
/* While there are two (2) display controllers registered with the
|
||
|
* X.Org Server, it is often desirable to fix the analog VGA output
|
||
|
* to IGA1 since LVDS FP (Flat Panel) typically prefers IGA2. (While
|
||
|
* it is not used at this point, only IGA2 contains panel resolution
|
||
|
* scaling functionality. IGA1 does not have this.)
|
||
|
* With this arrangement, DVI should end up getting assigned to IGA2
|
||
|
* since DVI can go to either display controller without limitations.
|
||
|
* This should be the case for TV as well. */
|
||
|
output->possible_crtcs = BIT(1) | BIT(0);
|
||
|
|
||
|
output->possible_clones = 0;
|
||
|
output->interlaceAllowed = FALSE;
|
||
|
output->doubleScanAllowed = FALSE;
|
||
|
|
||
|
exit:
|
||
|
DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
|
||
|
"Exiting viaAnalogInit.\n"));
|
||
|
}
|