Initial add of DVO support code. Probes my sil164.

This is a mostly-untested merge of airlied's work.  The I2C modules are intended
to be moved into the core server or a separate driver module when they're
functional and we're happy with the API.
This commit is contained in:
Eric Anholt 2006-07-07 13:41:33 -07:00
parent e1064f52b0
commit df333cc9a8
18 changed files with 995 additions and 24 deletions

View File

@ -125,5 +125,7 @@ AC_OUTPUT([
src/Makefile
src/xvmc/Makefile
src/bios_reader/Makefile
src/ch7xxx/Makefile
src/sil164/Makefile
man/Makefile
])

View File

@ -18,7 +18,7 @@
# 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.
SUBDIRS = xvmc bios_reader
SUBDIRS = xvmc bios_reader ch7xxx sil164
# this is obnoxious:
# -module lets us name the module exactly how we want
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
@ -54,6 +54,7 @@ i810_drv_la_SOURCES = \
i830_display.c \
i830_display.h \
i830_driver.c \
i830_dvo.c \
i830.h \
i830_gtf.c \
i830_i2c.c \

16
src/ch7xxx/Makefile.am Normal file
View File

@ -0,0 +1,16 @@
# this is obnoxious:
# -module lets us name the module exactly how we want
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
# _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
ch7xxx_la_LTLIBRARIES = ch7xxx.la
ch7xxx_la_LDFLAGS = -module -avoid-version
ch7xxx_ladir = @moduledir@/drivers
ch7xxx_la_SOURCES = \
ch7xxx.c \
ch7xxx_module.c \
ch7xxx.h \
ch7xxx_reg.h

272
src/ch7xxx/ch7xxx.c Normal file
View File

@ -0,0 +1,272 @@
/**************************************************************************
Copyright © 2006 Dave Airlie
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 AUTHOR 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.
**************************************************************************/
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "compiler.h"
#include "miscstruct.h"
#include "xf86i2c.h"
#include <string.h>
#include "../i2c_vid.h"
#include "ch7xxx.h"
#include "ch7xxx_reg.h"
static void ch7xxxSaveRegs(void *d);
static CARD8 ch7xxxFreqRegs[][7] =
{ { 0, 0x23, 0x08, 0x16, 0x30, 0x60, 0x00 },
{ 0, 0x23, 0x04, 0x26, 0x30, 0x60, 0x00 },
{ 0, 0x2D, 0x07, 0x26, 0x30, 0xE0, 0x00 } };
static Bool ch7xxxReadByte(CH7xxxPtr ch7xxx, int addr, unsigned char *ch)
{
if (!xf86I2CReadByte(&(ch7xxx->d), addr, ch)) {
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
static Bool ch7xxxWriteByte(CH7xxxPtr ch7xxx, int addr, unsigned char ch)
{
if (!xf86I2CWriteByte(&(ch7xxx->d), addr, ch)) {
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
/* Ch7xxxicon Image 164 driver for chip on i2c bus */
static void *ch7xxxDetect(I2CBusPtr b, I2CSlaveAddr addr)
{
/* this will detect the CH7xxx chip on the specified i2c bus */
CH7xxxPtr ch7xxx;
unsigned char ch;
xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting ch7xxx\n");
ch7xxx = xcalloc(1, sizeof(CH7xxxRec));
if (ch7xxx == NULL)
return NULL;
ch7xxx->d.DevName = "CH7xxx TMDS Controller";
ch7xxx->d.SlaveAddr = addr;
ch7xxx->d.pI2CBus = b;
ch7xxx->d.StartTimeout = b->StartTimeout;
ch7xxx->d.BitTimeout = b->BitTimeout;
ch7xxx->d.AcknTimeout = b->AcknTimeout;
ch7xxx->d.ByteTimeout = b->ByteTimeout;
ch7xxx->d.DriverPrivate.ptr = ch7xxx;
if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_VID, &ch))
goto out;
ErrorF("VID is %02X", ch);
if (ch!=(CH7xxx_VID & 0xFF))
{
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
goto out;
}
if (!ch7xxxReadByte(ch7xxx, CH7xxx_REG_DID, &ch))
goto out;
ErrorF("DID is %02X", ch);
if (ch!=(CH7xxx_DID & 0xFF))
{
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx not detected got %d: from %s Slave %d.\n", ch, ch7xxx->d.pI2CBus->BusName, ch7xxx->d.SlaveAddr);
goto out;
}
if (!xf86I2CDevInit(&(ch7xxx->d)))
{
goto out;
}
return ch7xxx;
out:
xfree(ch7xxx);
return NULL;
}
static Bool ch7xxxInit(I2CDevPtr d)
{
CH7xxxPtr ch7xxx = CH7PTR(d);
/* not much to do */
return TRUE;
}
static ModeStatus ch7xxxModeValid(I2CDevPtr d, DisplayModePtr mode)
{
CH7xxxPtr ch7xxx = CH7PTR(d);
return MODE_OK;
}
static void ch7xxxMode(I2CDevPtr d, DisplayModePtr mode)
{
CH7xxxPtr ch7xxx = CH7PTR(d);
int ret;
unsigned char pm, idf;
unsigned char tpcp, tpd, tpf, cm;
CARD8 *freq_regs;
int i;
ErrorF("Clock is %d\n", mode->Clock);
if (mode->Clock < 75000)
freq_regs = ch7xxxFreqRegs[0];
else if (mode->Clock < 125000)
freq_regs = ch7xxxFreqRegs[1];
else
freq_regs = ch7xxxFreqRegs[2];
for (i = 0x31; i < 0x37; i++) {
ch7xxx->ModeReg.regs[i] = freq_regs[i - 0x31];
ch7xxxWriteByte(ch7xxx, i, ch7xxx->ModeReg.regs[i]);
}
#if 0
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx idf is 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", idf, tpcp, tpd, tpf);
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", pm);
if (mode->Clock < 65000) {
tpcp = 0x08;
tpd = 0x16;
tpf = 0x60;
} else {
tpcp = 0x06;
tpd = 0x26;
tpf = 0xa0;
}
idf &= ~(CH7xxx_IDF_HSP | CH7xxx_IDF_VSP);
if (mode->Flags & V_PHSYNC)
idf |= CH7xxx_IDF_HSP;
if (mode->Flags & V_PVSYNC)
idf |= CH7xxx_IDF_HSP;
/* setup PM Registers */
pm &= ~CH7xxx_PM_FPD;
pm |= CH7xxx_PM_DVIL | CH7xxx_PM_DVIP;
// cm |= 1;
ch7xxxWriteByte(ch7xxx, CH7xxx_CM, cm);
ch7xxxWriteByte(ch7xxx, CH7xxx_TPCP, tpcp);
ch7xxxWriteByte(ch7xxx, CH7xxx_TPD, tpd);
ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, tpf);
ch7xxxWriteByte(ch7xxx, CH7xxx_TPF, idf);
ch7xxxWriteByte(ch7xxx, CH7xxx_PM, pm);
#endif
/* don't do much */
return;
}
/* set the CH7xxx power state */
static void ch7xxxPower(I2CDevPtr d, Bool On)
{
CH7xxxPtr ch7xxx = CH7PTR(d);
int ret;
unsigned char ch;
ret = ch7xxxReadByte(ch7xxx, CH7xxx_PM, &ch);
if (ret == FALSE)
return;
xf86DrvMsg(ch7xxx->d.pI2CBus->scrnIndex, X_ERROR, "ch7xxx pm is %02X\n", ch);
#if 0
ret = ch7xxxReadByte(ch7xxx, CH7xxx_REG8, &ch);
if (ret)
return;
if (On)
ch |= CH7xxx_8_PD;
else
ch &= ~CH7xxx_8_PD;
ch7xxxWriteByte(ch7xxx, CH7xxx_REG8, ch);
#endif
return;
}
static void ch7xxxPrintRegs(I2CDevPtr d)
{
CH7xxxPtr ch7xxx = CH7PTR(d);
int i;
ch7xxxSaveRegs(d);
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
if (( i % 8 ) == 0 )
ErrorF("\n %02X: ", i);
ErrorF("%02X ", ch7xxx->ModeReg.regs[i]);
}
}
static void ch7xxxSaveRegs(void *d)
{
CH7xxxPtr ch7xxx = CH7PTR(((I2CDevPtr)d));
int ret;
int i;
for (i = 0; i < CH7xxx_NUM_REGS; i++) {
ret = ch7xxxReadByte(ch7xxx, i, &ch7xxx->SavedReg.regs[i]);
if (ret == FALSE)
break;
}
memcpy(ch7xxx->ModeReg.regs, ch7xxx->SavedReg.regs, CH7xxx_NUM_REGS);
return;
}
I830I2CVidOutputRec CH7xxxVidOutput = {
ch7xxxDetect,
ch7xxxInit,
ch7xxxModeValid,
ch7xxxMode,
ch7xxxPower,
ch7xxxPrintRegs,
ch7xxxSaveRegs,
NULL,
};

33
src/ch7xxx/ch7xxx.h Normal file
View File

@ -0,0 +1,33 @@
/**************************************************************************
Copyright 2006 Dave Airlie <airlied@linux.ie>
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
on 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 COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
**************************************************************************/
#ifndef CH7xxx_H
#define CH7xxx_H
#define CH7xxx_ADDR_1 0x76
#define CH7xxx_SYMBOL_LIST "CH7xxxVidOutput"
#endif

View File

@ -0,0 +1,36 @@
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86Module.h"
static MODULESETUPPROTO(ch7xxxSetup);
static XF86ModuleVersionInfo ch7xxxVersRec =
{
"ch7xxx",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
1, 0, 0,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_NONE,
{ 0,0,0,0 }
};
_X_EXPORT XF86ModuleData ch7xxxModuleData = {
&ch7xxxVersRec,
ch7xxxSetup,
NULL
};
static pointer
ch7xxxSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
return (pointer)1;
}

91
src/ch7xxx/ch7xxx_reg.h Normal file
View File

@ -0,0 +1,91 @@
/**************************************************************************
Copyright 2006 Dave Airlie <airlied@linux.ie>
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
on 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 COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
**************************************************************************/
#ifndef CH7xxx_REG_H
#define CH7xxx_REG_H
#define CH7xxx_REG_VID 0x4a
#define CH7xxx_REG_DID 0x4b
#define CH7011_VID 0x83
#define CH7009A_VID 0x84
#define CH7009B_VID 0x85
#define CH7301_VID 0x95
#define CH7xxx_VID 0x84
#define CH7xxx_DID 0x17
#define CH7xxx_NUM_REGS 0x4c
typedef struct _CH7xxxSaveRec {
CARD8 regs[CH7xxx_NUM_REGS];
} CH7xxxSaveRec;
typedef struct {
I2CDevRec d;
CH7xxxSaveRec SavedReg;
CH7xxxSaveRec ModeReg;
} CH7xxxRec, *CH7xxxPtr;
#define CH7PTR(d) ((CH7xxxPtr)(d->DriverPrivate.ptr))
#define CH7xxx_CM 0x1C
#define CH7xxx_CM_XCM (1<<0)
#define CH7xxx_CM_MCP (1<<2)
#define CH7xxx_INPUT_CLOCK 0x1D
#define CH7xxx_GPIO 0x1E
#define CH7xxx_IDF 0x1F
#define CH7xxx_IDF_HSP (1<<3)
#define CH7xxx_IDF_VSP (1<<4)
#define CH7301_CONNECTION_DETECT 0x20
#define CH7301_DAC_CNTL 0x21
#define CH7301_HOTPLUG 0x23
#define CH7xxx_TCTL 0x31
#define CH7xxx_TPCP 0x33
#define CH7xxx_TPD 0x34
#define CH7xxx_TPVT 0x35
#define CH7xxx_TPF 0x36
#define CH7301_TCT 0x37
#define CH7301_TEST_PATTERN 0x48
#define CH7xxx_PM 0x49
#define CH7xxx_PM_FPD (1<<0)
#define CH7301_PM_DACPD0 (1<<1)
#define CH7301_PM_DACPD1 (1<<2)
#define CH7301_PM_DACPD2 (1<<3)
#define CH7xxx_PM_DVIL (1<<6)
#define CH7xxx_PM_DVIP (1<<7)
#define CH7301_SYNC_POLARITY 0x56
#define CH7301_SYNC_RGB_YUV (1<<0)
#define CH7301_SYNC_POL_DVI (1<<5)
#endif

16
src/i2c_vid.h Normal file
View File

@ -0,0 +1,16 @@
/* this needs to go in the server */
#ifndef I2C_VID_H
#define I2C_VID_H
typedef struct _I830I2CVidOutputRec {
void *(*Detect)(I2CBusPtr b, I2CSlaveAddr addr);
Bool (*Init)(I2CDevPtr d);
ModeStatus (*ModeValid)(I2CDevPtr d, DisplayModePtr mode);
void (*Mode)(I2CDevPtr d, DisplayModePtr mode);
void (*Power)(I2CDevPtr d, Bool On);
void (*PrintRegs)(I2CDevPtr d);
void (*SaveRegs)(void *d);
void (*RestoreRegs)(I2CDevPtr d);
} I830I2CVidOutputRec, *I830I2CVidOutputPtr;
#endif

View File

@ -823,11 +823,35 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define DVOA 0x61120
#define DVOB 0x61140
#define DVOC 0x61160
#define DVO_ENABLE (1<<31)
#define DVO_ENABLE (1 << 31)
#define DVO_PIPE_B_SELECT (1 << 30)
#define DVO_PIPE_STALL_UNUSED (0 << 28)
#define DVO_PIPE_STALL (1 << 28)
#define DVO_PIPE_STALL_TV (2 << 28)
#define DVO_USE_VGA_SYNC (1 << 15)
#define DVO_DATA_ORDER_I740 (0 << 14)
#define DVO_DATA_ORDER_FP (1 << 14)
#define DVO_VSYNC_DISABLE (1 << 11)
#define DVO_HSYNC_DISABLE (1 << 10)
#define DVO_VSYNC_TRISTATE (1 << 9)
#define DVO_HSYNC_TRISTATE (1 << 8)
#define DVO_BORDER_ENABLE (1 << 7)
#define DVO_DATA_ORDER_GBRG (1 << 6)
#define DVO_DATA_ORDER_RGGB (0 << 6)
#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6)
#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6)
#define DVO_VSYNC_ACTIVE_HIGH (1 << 4)
#define DVO_HSYNC_ACTIVE_HIGH (1 << 3)
#define DVO_BLANK_ACTIVE_HIGH (1 << 2)
#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */
#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */
#define DVO_PRESERVE_MASK (0x7<<24)
#define DVOA_SRCDIM 0x61124
#define DVOB_SRCDIM 0x61144
#define DVOC_SRCDIM 0x61164
#define DVO_SRCDIM_HORIZONTAL_SHIFT 12
#define DVO_SRCDIM_VERTICAL_SHIFT 0
#define LVDS 0x61180
# define LVDS_PORT_EN (1 << 31)

View File

@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "common.h"
#include "i830_sdvo.h"
#include "i2c_vid.h"
/* I830 Video BIOS support */
@ -182,10 +183,8 @@ struct _I830DVODriver {
char *fntablename;
int address;
const char **symbols;
#if 0
I830I2CVidOutputRec *vid_rec;
#endif
void *devpriv;
void *dev_priv;
pointer modhandle;
};
@ -593,6 +592,10 @@ extern Bool I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem);
extern Bool I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg,
char *name);
/* i830_dvo.c */
Bool I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
struct _I830DVODriver **retdrv);
/* i830_memory.c */
Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);

View File

@ -258,8 +258,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
CARD32 dpll = 0, fp = 0, temp;
CARD32 htot, hblank, hsync, vtot, vblank, vsync, dspcntr;
CARD32 pipesrc, dspsize, adpa;
CARD32 sdvob = 0, sdvoc= 0;
Bool ok, is_sdvo;
CARD32 sdvob = 0, sdvoc = 0, dvo = 0;
Bool ok, is_sdvo, is_dvo;
int refclk, pixel_clock, sdvo_pixel_multiply;
int outputs;
DisplayModePtr pMasterMode = pMode;
@ -359,9 +359,16 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
/* We'll change how we control outputs soon, but to get the SDVO code up
* and running, just check for these two possibilities.
*/
is_sdvo = TRUE;
if (IS_I9XX(pI830)) {
is_sdvo = TRUE;
is_dvo = FALSE;
} else {
is_dvo = TRUE;
is_sdvo = FALSE;
}
} else {
is_sdvo = FALSE;
is_dvo = FALSE;
}
htot = (pMode->CrtcHDisplay - 1) | ((pMode->CrtcHTotal - 1) << 16);
@ -471,6 +478,27 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
else
dpll |= PLL_REF_INPUT_DREFCLK;
if (is_dvo) {
dpll |= DPLL_DVO_HIGH_SPEED;
/* Save the data order, since I don't know what it should be set to. */
dvo = INREG(DVOB) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
dvo |= DVO_DATA_ORDER_FP | DVO_BORDER_ENABLE;
if (pipe == 1)
dvo |= DVO_PIPE_B_SELECT;
if (pMode->Flags & V_PHSYNC)
dvo |= DVO_HSYNC_ACTIVE_HIGH;
if (pMode->Flags & V_PVSYNC)
dvo |= DVO_VSYNC_ACTIVE_HIGH;
if (IS_I865G(pI830))
dvo |= DVO_OUTPUT_SOURCE_SIZE_PIXELS;
OUTREG(DVOB, dvo & ~DVO_ENABLE);
}
if (is_sdvo) {
dpll |= DPLL_DVO_HIGH_SPEED;
@ -654,6 +682,15 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
if (outputs & PIPE_CRT_ACTIVE)
OUTREG(ADPA, adpa);
if (is_dvo) {
OUTREG(DVOB_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT));
/* OUTREG(DVOC_SRCDIM, (pMode->HDisplay << DVO_SRCDIM_HORIZONTAL_SHIFT) |
(pMode->VDisplay << DVO_SRCDIM_VERTICAL_SHIFT)); */
OUTREG(DVOB, dvo);
/* OUTREG(DVOC, dvoc); */
}
if (is_sdvo) {
OUTREG(SDVOB, sdvob);
OUTREG(SDVOC, sdvoc);

View File

@ -1053,6 +1053,7 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
int i = 0;
Bool ret;
/* everyone has at least a single analog output */
pI830->output[i].type = I830_OUTPUT_ANALOG;
@ -1073,6 +1074,13 @@ I830SetupOutputBusses(ScrnInfoPtr pScrn)
pI830->output[i].type = I830_OUTPUT_DVO;
I830I2CInit(pScrn, &pI830->output[i].pDDCBus, GPIOD, "DVODDC_D");
I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
&pI830->output[i].i2c_drv);
if (ret) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
pI830->output[i].i2c_drv->modulename,
pI830->output[i].pI2CBus->DriverPrivate.uval);
}
i++;
break;
case PCI_CHIP_E7221_G:
@ -1158,22 +1166,6 @@ I830DetectMonitors(ScrnInfoPtr pScrn)
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08lX\n", i,
pI830->output[i].pDDCBus->DriverPrivate.uval);
xf86PrintEDID(pI830->output[i].MonInfo);
#if 0
/* if we are on an i2C bus > 0 and we see a monitor - try to
* find a controller chip
*/
if (pI830->output[i].MonInfo) {
int ret;
ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus,
&pI830->output[i].i2c_drv);
if (ret==TRUE) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
pI830->output[i].i2c_drv->modulename,
pI830->output[i].pI2CBus->DriverPrivate.uval);
}
}
#endif
break;
case I830_OUTPUT_SDVO:
if (pI830->output[i].sdvo_drv != NULL) {
@ -2769,6 +2761,12 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->saveSWF[16] = INREG(SWF32);
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].type == I830_OUTPUT_DVO &&
pI830->output[i].i2c_drv != NULL)
{
pI830->output[i].i2c_drv->vid_rec->SaveRegs(
pI830->output[i].i2c_drv->dev_priv);
}
if (pI830->output[i].type == I830_OUTPUT_SDVO &&
pI830->output[i].sdvo_drv != NULL)
{
@ -2888,6 +2886,12 @@ RestoreHWState(ScrnInfoPtr pScrn)
}
for (i = 0; i < pI830->num_outputs; i++) {
if (pI830->output[i].type == I830_OUTPUT_DVO &&
pI830->output[i].i2c_drv != NULL)
{
pI830->output[i].i2c_drv->vid_rec->RestoreRegs(
pI830->output[i].i2c_drv->dev_priv);
}
if (pI830->output[i].type == I830_OUTPUT_SDVO &&
pI830->output[i].sdvo_drv != NULL)
{

84
src/i830_dvo.c Normal file
View File

@ -0,0 +1,84 @@
/**************************************************************************
Copyright 2006 Dave Airlie <airlied@linux.ie>
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
on 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 COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
**************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "i830.h"
#include "sil164/sil164.h"
#include "ch7xxx/ch7xxx.h"
static const char *SIL164Symbols[] = {
SIL164_SYMBOL_LIST
};
static const char *CH7xxxSymbols[] = {
CH7xxx_SYMBOL_LIST
};
/* driver list */
struct _I830DVODriver i830_dvo_drivers[] =
{
{ I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
{ I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL}
};
#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
Bool
I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
struct _I830DVODriver **retdrv)
{
int i;
void *ret_ptr;
struct _I830DVODriver *drv;
for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
drv = &i830_dvo_drivers[i];
drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
if (drv->modhandle == NULL)
continue;
xf86LoaderReqSymLists(drv->symbols, NULL);
ret_ptr = NULL;
drv->vid_rec = LoaderSymbol(drv->fntablename);
if (drv->vid_rec != NULL)
ret_ptr = drv->vid_rec->Detect(pI2CBus, drv->address);
if (ret_ptr != NULL) {
drv->dev_priv = ret_ptr;
*retdrv = drv;
return TRUE;
}
xf86UnloadSubModule(drv->modhandle);
}
return FALSE;
}

16
src/sil164/Makefile.am Normal file
View File

@ -0,0 +1,16 @@
# this is obnoxious:
# -module lets us name the module exactly how we want
# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
# _ladir passes a dummy rpath to libtool so the thing will actually link
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
AM_CFLAGS = @XORG_CFLAGS@ @DRI_CFLAGS@
sil164_la_LTLIBRARIES = sil164.la
sil164_la_LDFLAGS = -module -avoid-version
sil164_ladir = @moduledir@/drivers
sil164_la_SOURCES = \
sil164.c \
sil164_module.c \
sil164.h \
sil164_reg.h

192
src/sil164/sil164.c Normal file
View File

@ -0,0 +1,192 @@
/**************************************************************************
Copyright © 2006 Dave Airlie
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 AUTHOR 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.
**************************************************************************/
#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "compiler.h"
#include "miscstruct.h"
#include "xf86i2c.h"
#include "../i2c_vid.h"
#include "sil164.h"
#include "sil164_reg.h"
static Bool sil164ReadByte(SIL164Ptr sil, int addr, unsigned char *ch)
{
if (!xf86I2CReadByte(&(sil->d), addr, ch)) {
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
static Bool sil164WriteByte(SIL164Ptr sil, int addr, unsigned char ch)
{
if (!xf86I2CWriteByte(&(sil->d), addr, ch)) {
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "Unable to write to %s Slave %d.\n", sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
/* Silicon Image 164 driver for chip on i2c bus */
static void *sil164Detect(I2CBusPtr b, I2CSlaveAddr addr)
{
/* this will detect the SIL164 chip on the specified i2c bus */
SIL164Ptr sil;
unsigned char ch;
xf86DrvMsg(b->scrnIndex, X_ERROR, "detecting sil164\n");
sil = xcalloc(1, sizeof(SIL164Rec));
if (sil == NULL)
return NULL;
sil->d.DevName = "SIL164 TMDS Controller";
sil->d.SlaveAddr = addr;
sil->d.pI2CBus = b;
sil->d.StartTimeout = b->StartTimeout;
sil->d.BitTimeout = b->BitTimeout;
sil->d.AcknTimeout = b->AcknTimeout;
sil->d.ByteTimeout = b->ByteTimeout;
sil->d.DriverPrivate.ptr = sil;
if (!sil164ReadByte(sil, SIL164_VID_LO, &ch))
goto out;
if (ch!=(SIL164_VID & 0xFF))
{
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
goto out;
}
if (!sil164ReadByte(sil, SIL164_DID_LO, &ch))
goto out;
if (ch!=(SIL164_DID & 0xFF))
{
xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, "sil164 not detected got %d: from %s Slave %d.\n", ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr);
goto out;
}
if (!xf86I2CDevInit(&(sil->d)))
{
goto out;
}
return sil;
out:
xfree(sil);
return NULL;
}
static Bool sil164Init(I2CDevPtr d)
{
SIL164Ptr sil = SILPTR(d);
/* not much to do */
return TRUE;
}
static ModeStatus sil164ModeValid(I2CDevPtr d, DisplayModePtr mode)
{
SIL164Ptr sil = SILPTR(d);
return MODE_OK;
}
static void sil164Mode(I2CDevPtr d, DisplayModePtr mode)
{
SIL164Ptr sil = SILPTR(d);
/* don't do much */
return;
}
/* set the SIL164 power state */
static void sil164Power(I2CDevPtr d, Bool On)
{
SIL164Ptr sil = SILPTR(d);
int ret;
unsigned char ch;
ret = sil164ReadByte(sil, SIL164_REG8, &ch);
if (ret == FALSE)
return;
if (On)
ch |= SIL164_8_PD;
else
ch &= ~SIL164_8_PD;
sil164WriteByte(sil, SIL164_REG8, ch);
return;
}
static void sil164PrintRegs(I2CDevPtr d)
{
SIL164Ptr sil = SILPTR(d);
}
static void sil164SaveRegs(I2CDevPtr d)
{
SIL164Ptr sil = SILPTR(d);
if (!sil164ReadByte(sil, SIL164_FREQ_LO, &sil->SavedReg.freq_lo))
return;
if (!sil164ReadByte(sil, SIL164_FREQ_HI, &sil->SavedReg.freq_hi))
return;
if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8))
return;
if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9))
return;
if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc))
return;
return;
}
I830I2CVidOutputRec SIL164VidOutput = {
sil164Detect,
sil164Init,
sil164ModeValid,
sil164Mode,
sil164Power,
sil164PrintRegs,
sil164SaveRegs,
NULL,
};

33
src/sil164/sil164.h Normal file
View File

@ -0,0 +1,33 @@
/**************************************************************************
Copyright 2006 Dave Airlie <airlied@linux.ie>
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
on 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 COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
**************************************************************************/
#ifndef SIL164_H
#define SIL164_H
#define SIL164_ADDR_1 0x38
#define SIL164_SYMBOL_LIST "SIL164VidOutput"
#endif

View File

@ -0,0 +1,36 @@
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86Module.h"
static MODULESETUPPROTO(sil164Setup);
static XF86ModuleVersionInfo sil164VersRec =
{
"sil164",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
1, 0, 0,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_NONE,
{ 0,0,0,0 }
};
_X_EXPORT XF86ModuleData sil164ModuleData = {
&sil164VersRec,
sil164Setup,
NULL
};
static pointer
sil164Setup(pointer module, pointer opts, int *errmaj, int *errmin) {
return (pointer)1;
}

75
src/sil164/sil164_reg.h Normal file
View File

@ -0,0 +1,75 @@
/**************************************************************************
Copyright 2006 Dave Airlie <airlied@linux.ie>
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
on 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 COPYRIGHT HOLDERS AND/OR THEIR SUPPLIERS 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.
**************************************************************************/
#ifndef SIL164_REG_H
#define SIL164_REG_H
#define SIL164_VID 0x0001
#define SIL164_DID 0x0006
#define SIL164_VID_LO 0x00
#define SIL164_VID_HI 0x01
#define SIL164_DID_LO 0x02
#define SIL164_DID_HI 0x03
#define SIL164_REV 0x04
#define SIL164_RSVD 0x05
#define SIL164_FREQ_LO 0x06
#define SIL164_FREQ_HI 0x07
#define SIL164_REG8 0x08
#define SIL164_8_VEN (1<<5)
#define SIL164_8_HEN (1<<4)
#define SIL164_8_DSEL (1<<3)
#define SIL164_8_BSEL (1<<2)
#define SIL164_8_EDGE (1<<1)
#define SIL164_8_PD (1<<0)
#define SIL164_REG9 0x09
#define SIL164_9_VLOW (1<<7)
#define SIL164_9_MSEL_MASK (0x7<<4)
#define SIL164_9_TSEL (1<<3)
#define SIL164_9_RSEN (1<<2)
#define SIL164_9_HTPLG (1<<1)
#define SIL164_9_MDI (1<<0)
#define SIL164_REGC 0x0c
typedef struct _Sil164SaveRec {
CARD8 freq_lo;
CARD8 freq_hi;
CARD8 reg8;
CARD8 reg9;
CARD8 regc;
} SIL164SaveRec;
typedef struct {
I2CDevRec d;
SIL164SaveRec SavedReg;
SIL164SaveRec ModeReg;
} SIL164Rec, *SIL164Ptr;
#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr))
#endif