summaryrefslogtreecommitdiff
path: root/src/ch7xxx
diff options
context:
space:
mode:
authorEric Anholt <anholt@leguin.anholt.net>2006-07-07 13:41:33 -0700
committerEric Anholt <anholt@leguin.anholt.net>2006-07-07 13:41:33 -0700
commitdf333cc9a848bc2299a52a7613fe4ffdff8038a2 (patch)
treee3e315114ffbe2cc13ab1472f518231dd0a9503a /src/ch7xxx
parente1064f52b0ff69ea7937897b8c951cc3e32cd752 (diff)
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.
Diffstat (limited to 'src/ch7xxx')
-rw-r--r--src/ch7xxx/Makefile.am16
-rw-r--r--src/ch7xxx/ch7xxx.c272
-rw-r--r--src/ch7xxx/ch7xxx.h33
-rw-r--r--src/ch7xxx/ch7xxx_module.c36
-rw-r--r--src/ch7xxx/ch7xxx_reg.h91
5 files changed, 448 insertions, 0 deletions
diff --git a/src/ch7xxx/Makefile.am b/src/ch7xxx/Makefile.am
new file mode 100644
index 00000000..645ac692
--- /dev/null
+++ b/src/ch7xxx/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 = @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
diff --git a/src/ch7xxx/ch7xxx.c b/src/ch7xxx/ch7xxx.c
new file mode 100644
index 00000000..77c49b53
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.c
@@ -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,
+};
diff --git a/src/ch7xxx/ch7xxx.h b/src/ch7xxx/ch7xxx.h
new file mode 100644
index 00000000..5ae0ab8c
--- /dev/null
+++ b/src/ch7xxx/ch7xxx.h
@@ -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
diff --git a/src/ch7xxx/ch7xxx_module.c b/src/ch7xxx/ch7xxx_module.c
new file mode 100644
index 00000000..19dc6cd1
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_module.c
@@ -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;
+}
diff --git a/src/ch7xxx/ch7xxx_reg.h b/src/ch7xxx/ch7xxx_reg.h
new file mode 100644
index 00000000..59de13b8
--- /dev/null
+++ b/src/ch7xxx/ch7xxx_reg.h
@@ -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