diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/i830_dvo.c | 13 | ||||
-rw-r--r-- | src/tfp410/Makefile.am | 16 | ||||
-rw-r--r-- | src/tfp410/tfp410.c | 265 | ||||
-rw-r--r-- | src/tfp410/tfp410.h | 33 | ||||
-rw-r--r-- | src/tfp410/tfp410_module.c | 38 | ||||
-rw-r--r-- | src/tfp410/tfp410_reg.h | 104 |
8 files changed, 471 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac index 66992fc1..51203fe6 100644 --- a/configure.ac +++ b/configure.ac @@ -230,5 +230,6 @@ AC_OUTPUT([ src/ivch/Makefile src/reg_dumper/Makefile src/sil164/Makefile + src/tfp410/Makefile man/Makefile ]) diff --git a/src/Makefile.am b/src/Makefile.am index 2b5799c9..858ffd17 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,7 @@ if HAVE_PCIACCESS REGDUMPER = reg_dumper endif -SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 $(REGDUMPER) +SUBDIRS = xvmc bios_reader ch7017 ch7xxx ivch sil164 tfp410 $(REGDUMPER) # this is obnoxious: # -module lets us name the module exactly how we want diff --git a/src/i830_dvo.c b/src/i830_dvo.c index 5666d263..2521ee3d 100644 --- a/src/i830_dvo.c +++ b/src/i830_dvo.c @@ -36,11 +36,16 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sil164/sil164.h" #include "ch7xxx/ch7xxx.h" +#include "tfp410/tfp410.h" static const char *SIL164Symbols[] = { "Sil164VidOutput", NULL }; +static const char *TFP410Symbols[] = { + "Tfp410VidOutput", + NULL +}; static const char *CH7xxxSymbols[] = { "CH7xxxVidOutput", NULL @@ -84,6 +89,14 @@ struct _I830DVODriver i830_dvo_drivers[] = .address = 0x04, /* Might also be 0x44, 0x84, 0xc4 */ .symbols = ivch_symbols }, + { + .type = I830_OUTPUT_DVO_TMDS, + .modulename = "tfp410", + .fntablename = "TFP410VidOutput", + .dvo_reg = DVOC, + .address = (TFP410_ADDR_1<<1), + .symbols = TFP410Symbols + }, /* { I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods", 0xea, ch7017_symbols, NULL, NULL, NULL } diff --git a/src/tfp410/Makefile.am b/src/tfp410/Makefile.am new file mode 100644 index 00000000..89a27d03 --- /dev/null +++ b/src/tfp410/Makefile.am @@ -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 = @WARN_CFLAGS@ @XMODES_CFLAGS@ @XORG_CFLAGS@ @DRI_CFLAGS@ + +tfp410_la_LTLIBRARIES = tfp410.la +tfp410_la_LDFLAGS = -module -avoid-version +tfp410_ladir = @moduledir@/drivers + +tfp410_la_SOURCES = \ + tfp410.c \ + tfp410_module.c \ + tfp410.h \ + tfp410_reg.h diff --git a/src/tfp410/tfp410.c b/src/tfp410/tfp410.c new file mode 100644 index 00000000..fecb64c8 --- /dev/null +++ b/src/tfp410/tfp410.c @@ -0,0 +1,265 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2007 Dave Mueller + * + * 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, sublicense, + * 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 NONINFRINGEMENT. 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. + * + * Authors: + * Dave Mueller <dave.mueller@gmx.ch> + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "compiler.h" +#include "miscstruct.h" +#include "xf86i2c.h" +#include "xf86Crtc.h" +#define DPMS_SERVER +#include <X11/extensions/dpms.h> + +#include "../i2c_vid.h" +#include "tfp410.h" +#include "tfp410_reg.h" + +static Bool +tfp410ReadByte(TFP410Ptr tfp, int addr, CARD8 *ch) +{ + if (!xf86I2CReadByte(&(tfp->d), addr, ch)) { + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to read from %s Slave %d.\n", + tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static Bool +tfp410WriteByte(TFP410Ptr tfp, int addr, CARD8 ch) +{ + if (!xf86I2CWriteByte(&(tfp->d), addr, ch)) { + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, + "Unable to write to %s Slave %d.\n", + tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); + return FALSE; + } + return TRUE; +} + +static int +tfp410GetID(TFP410Ptr tfp, int addr) +{ + unsigned char ch1, ch2; + + if (tfp410ReadByte(tfp, addr+0, &ch1) && + tfp410ReadByte(tfp, addr+1, &ch2)) { + + return ((ch2<<8) & 0xFF00) | (ch1 & 0x00FF); + } + return -1; +} + +/* Ti TFP410 driver for chip on i2c bus */ +static void * +tfp410_init(I2CBusPtr b, I2CSlaveAddr addr) +{ + /* this will detect the tfp410 chip on the specified i2c bus */ + TFP410Ptr tfp; + int id; + + xf86DrvMsg(b->scrnIndex, X_INFO, "detecting tfp410\n"); + + tfp = xcalloc(1, sizeof(TFP410Rec)); + if (tfp == NULL) + return NULL; + + tfp->d.DevName = "TFP410 TMDS Controller"; + tfp->d.SlaveAddr = addr; + tfp->d.pI2CBus = b; + tfp->d.StartTimeout = b->StartTimeout; + tfp->d.BitTimeout = b->BitTimeout; + tfp->d.AcknTimeout = b->AcknTimeout; + tfp->d.ByteTimeout = b->ByteTimeout; + tfp->d.DriverPrivate.ptr = tfp; + + if ((id = tfp410GetID(tfp, TFP410_VID_LO)) != TFP410_VID) { + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, + "tfp410 not detected got VID %X: from %s Slave %d.\n", + id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); + goto out; + } + + if ((id = tfp410GetID(tfp, TFP410_DID_LO)) != TFP410_DID) { + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, + "tfp410 not detected got DID %X: from %s Slave %d.\n", + id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); + goto out; + } + + if (!xf86I2CDevInit(&(tfp->d))) { + goto out; + } + + return tfp; + +out: + xfree(tfp); + return NULL; +} + +static xf86OutputStatus +tfp410_detect(I2CDevPtr d) +{ + TFP410Ptr tfp = TFPPTR(d); + xf86OutputStatus ret = XF86OutputStatusDisconnected; + unsigned char ctl2; + + if (tfp410ReadByte(tfp, TFP410_CTL_2, &ctl2)) { + if (ctl2 & TFP410_CTL_2_HTPLG) + ret = XF86OutputStatusConnected; + else + ret = XF86OutputStatusDisconnected; + } + + return ret; +} + +static ModeStatus +tfp410_mode_valid(I2CDevPtr d, DisplayModePtr mode) +{ + return MODE_OK; +} + +static void +tfp410_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode) +{ + /* As long as the basics are set up, since we don't have clock dependencies + * in the mode setup, we can just leave the registers alone and everything + * will work fine. + */ + /* don't do much */ + return; +} + +/* set the tfp410 power state */ +static void +tfp410_dpms(I2CDevPtr d, int mode) +{ + TFP410Ptr tfp = TFPPTR(d); + unsigned char ctl1; + + if (!tfp410ReadByte(tfp, TFP410_CTL_1, &ctl1)) + return; + + if (mode == DPMSModeOn) + ctl1 |= TFP410_CTL_1_PD; + else + ctl1 &= ~TFP410_CTL_1_PD; + + tfp410WriteByte(tfp, TFP410_CTL_1, ctl1); +} + +static void +tfp410_dump_regs(I2CDevPtr d) +{ + TFP410Ptr tfp = TFPPTR(d); + CARD8 val, val2; + + tfp410ReadByte(tfp, TFP410_REV, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_REV: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_CTL_1, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_CTL1: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_CTL_2, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_CTL2: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_CTL_3, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_CTL3: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_USERCFG, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_USERCFG: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_DE_DLY, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_DE_DLY: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_DE_CTL, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_DE_CTL: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_DE_TOP, &val); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_DE_TOP: 0x%02X\n", val); + tfp410ReadByte(tfp, TFP410_DE_CNT_LO, &val); + tfp410ReadByte(tfp, TFP410_DE_CNT_HI, &val2); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_DE_CNT: 0x%02X%02X\n", val2, val); + tfp410ReadByte(tfp, TFP410_DE_LIN_LO, &val); + tfp410ReadByte(tfp, TFP410_DE_LIN_HI, &val2); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_DE_LIN: 0x%02X%02X\n", val2, val); + tfp410ReadByte(tfp, TFP410_H_RES_LO, &val); + tfp410ReadByte(tfp, TFP410_H_RES_HI, &val2); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_H_RES: 0x%02X%02X\n", val2, val); + tfp410ReadByte(tfp, TFP410_V_RES_LO, &val); + tfp410ReadByte(tfp, TFP410_V_RES_HI, &val2); + xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, + "TFP410_V_RES: 0x%02X%02X\n", val2, val); +} + +static void +tfp410_save(I2CDevPtr d) +{ + TFP410Ptr tfp = TFPPTR(d); + + if (!tfp410ReadByte(tfp, TFP410_CTL_1, &tfp->SavedReg.ctl1)) + return; + + if (!tfp410ReadByte(tfp, TFP410_CTL_2, &tfp->SavedReg.ctl2)) + return; +} + +static void +tfp410_restore(I2CDevPtr d) +{ + TFP410Ptr tfp = TFPPTR(d); + + /* Restore it powered down initially */ + tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1 & ~0x1); + + tfp410WriteByte(tfp, TFP410_CTL_2, tfp->SavedReg.ctl2); + tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1); +} + +I830I2CVidOutputRec TFP410VidOutput = { + .init = tfp410_init, + .detect = tfp410_detect, + .mode_valid = tfp410_mode_valid, + .mode_set = tfp410_mode_set, + .dpms = tfp410_dpms, + .dump_regs = tfp410_dump_regs, + .save = tfp410_save, + .restore = tfp410_restore, +}; diff --git a/src/tfp410/tfp410.h b/src/tfp410/tfp410.h new file mode 100644 index 00000000..fb3f4524 --- /dev/null +++ b/src/tfp410/tfp410.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2007 Dave Mueller + * + * 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, sublicense, + * 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 NONINFRINGEMENT. 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. + * + * Authors: + * Dave Mueller <dave.mueller@gmx.ch> + * + */ + +#ifndef TFP410_H +#define TFP410_H + +#define TFP410_ADDR_1 0x38 + +#endif diff --git a/src/tfp410/tfp410_module.c b/src/tfp410/tfp410_module.c new file mode 100644 index 00000000..c05b21a6 --- /dev/null +++ b/src/tfp410/tfp410_module.c @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 4 -*- */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86Module.h" + +static MODULESETUPPROTO(tfp410Setup); + +static XF86ModuleVersionInfo tfp410VersRec = { + "tfp410", + 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 tfp410ModuleData = { + &tfp410VersRec, + tfp410Setup, + NULL +}; + +static pointer +tfp410Setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + return (pointer)1; +} diff --git a/src/tfp410/tfp410_reg.h b/src/tfp410/tfp410_reg.h new file mode 100644 index 00000000..45afa9b0 --- /dev/null +++ b/src/tfp410/tfp410_reg.h @@ -0,0 +1,104 @@ +/* -*- c-basic-offset: 4 -*- */ +/* + * Copyright © 2007 Dave Mueller + * + * 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, sublicense, + * 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 NONINFRINGEMENT. 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. + * + * Authors: + * Dave Mueller <dave.mueller@gmx.ch> + * + */ + +#ifndef TFP410_REG_H +#define TFP410_REG_H + +/* register definitions according to the TFP410 data sheet */ +#define TFP410_VID 0x014C +#define TFP410_DID 0x0410 + +#define TFP410_VID_LO 0x00 +#define TFP410_VID_HI 0x01 +#define TFP410_DID_LO 0x02 +#define TFP410_DID_HI 0x03 +#define TFP410_REV 0x04 + +#define TFP410_CTL_1 0x08 +#define TFP410_CTL_1_TDIS (1<<6) +#define TFP410_CTL_1_VEN (1<<5) +#define TFP410_CTL_1_HEN (1<<4) +#define TFP410_CTL_1_DSEL (1<<3) +#define TFP410_CTL_1_BSEL (1<<2) +#define TFP410_CTL_1_EDGE (1<<1) +#define TFP410_CTL_1_PD (1<<0) + +#define TFP410_CTL_2 0x09 +#define TFP410_CTL_2_VLOW (1<<7) +#define TFP410_CTL_2_MSEL_MASK (0x7<<4) +#define TFP410_CTL_2_MSEL (1<<4) +#define TFP410_CTL_2_TSEL (1<<3) +#define TFP410_CTL_2_RSEN (1<<2) +#define TFP410_CTL_2_HTPLG (1<<1) +#define TFP410_CTL_2_MDI (1<<0) + +#define TFP410_CTL_3 0x0A +#define TFP410_CTL_3_DK_MASK (0x7<<5) +#define TFP410_CTL_3_DK (1<<5) +#define TFP410_CTL_3_DKEN (1<<4) +#define TFP410_CTL_3_CTL_MASK (0x7<<1) +#define TFP410_CTL_3_CTL (1<<1) + +#define TFP410_USERCFG 0x0B + +#define TFP410_DE_DLY 0x32 + +#define TFP410_DE_CTL 0x33 +#define TFP410_DE_CTL_DEGEN (1<<6) +#define TFP410_DE_CTL_VSPOL (1<<5) +#define TFP410_DE_CTL_HSPOL (1<<4) +#define TFP410_DE_CTL_DEDLY8 (1<<0) + +#define TFP410_DE_TOP 0x34 + +#define TFP410_DE_CNT_LO 0x36 +#define TFP410_DE_CNT_HI 0x37 + +#define TFP410_DE_LIN_LO 0x38 +#define TFP410_DE_LIN_HI 0x39 + +#define TFP410_H_RES_LO 0x3A +#define TFP410_H_RES_HI 0x3B + +#define TFP410_V_RES_LO 0x3C +#define TFP410_V_RES_HI 0x3D + +typedef struct _TFP410SaveRec { + CARD8 ctl1; + CARD8 ctl2; +} TFP410SaveRec; + +typedef struct { + I2CDevRec d; + TFP410SaveRec SavedReg; + TFP410SaveRec ModeReg; +} TFP410Rec, *TFP410Ptr; + +#define TFPPTR(d) ((TFP410Ptr)(d->DriverPrivate.ptr)) + +#endif |