diff options
author | JUNG, Christian <christian.jung@shsservices.org> | 2015-01-10 17:47:48 -0700 |
---|---|---|
committer | James Simmons <jsimmons@infradead.org> | 2015-01-10 17:48:02 -0700 |
commit | a8c2f04e2ef21e64f2e91dd6f3e237f80e8c80c6 (patch) | |
tree | 3d93636d7d2a44ff3b02687830021a2b20e6bd29 | |
parent | 02480da73b76df500aaca8dd6eff9d56acdb58d2 (diff) |
Add support for VT1632 DVI transmitter for UMS mode.
Signed-off-by: JUNG, Christian <christian.jung@shsservices.org>
Reviewed-by: James Simmons <jsimmons@infradead.org>
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/via_driver.h | 2 | ||||
-rw-r--r-- | src/via_outputs.c | 190 | ||||
-rw-r--r-- | src/via_vt1632.c | 204 | ||||
-rw-r--r-- | src/via_vt1632.h | 54 |
5 files changed, 452 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 7f67bed..c3c38cc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,8 @@ openchrome_drv_la_SOURCES = \ via_xv.h \ via_vt162x.c \ via_vt162x.h \ + via_vt1632.c \ + via_vt1632.h \ via_xvpriv.h if DRI diff --git a/src/via_driver.h b/src/via_driver.h index b1b077d..be0e73d 100644 --- a/src/via_driver.h +++ b/src/via_driver.h @@ -86,6 +86,8 @@ #endif #include <errno.h> +#include "via_vt1632.h" + #include "compat-api.h" #define VIA_AGP_UPL_SIZE (1024*128) #define VIA_DMA_DL_SIZE (1024*128) diff --git a/src/via_outputs.c b/src/via_outputs.c index 1876937..84a383e 100644 --- a/src/via_outputs.c +++ b/src/via_outputs.c @@ -888,6 +888,10 @@ ViaOutputsDetect(ScrnInfoPtr pScrn) if ((pVia->Chipset != VIA_P4M900) || (pVia->ActiveDevice & VIA_DEVICE_TV)) via_tv_init(pScrn); + if (pVia->Chipset == VIA_VM800) { + via_dvi_init(pScrn); + } + if (pVia->ActiveDevice & VIA_DEVICE_DFP) { switch (pVia->Chipset) { case VIA_CX700: @@ -1370,3 +1374,189 @@ ViaModeSecondCRTC(ScrnInfoPtr pScrn, DisplayModePtr mode) hwp->disablePalette(hwp); } + +static void +via_dvi_create_resources(xf86OutputPtr output) +{ +} + +#ifdef RANDR_12_INTERFACE +static Bool +via_dvi_set_property(xf86OutputPtr output, Atom property, + RRPropertyValuePtr value) +{ + return FALSE; +} + +static Bool +via_dvi_get_property(xf86OutputPtr output, Atom property) +{ + return FALSE; +} +#endif + +static void +via_dvi_dpms(xf86OutputPtr output, int mode) +{ + ScrnInfoPtr pScrn = output->scrn; + + switch (mode) { + case DPMSModeOn: + ViaDFPPower(pScrn, TRUE); + break; + + case DPMSModeStandby: + case DPMSModeSuspend: + case DPMSModeOff: + ViaDFPPower(pScrn, FALSE); + break; + } + +} + +static void +via_dvi_save(xf86OutputPtr output) +{ + via_vt1632_save(output); +} + +static void +via_dvi_restore(xf86OutputPtr output) +{ + via_vt1632_restore(output); +} + +static int +via_dvi_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + return via_vt1632_mode_valid(output, pMode); +} + +static Bool +via_dvi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + return TRUE; +} + +static void +via_dvi_prepare(xf86OutputPtr output) +{ +} + +static void +via_dvi_commit(xf86OutputPtr output) +{ +} + +static void +via_dvi_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + ScrnInfoPtr pScrn = output->scrn; + vgaHWPtr hwp = VGAHWPTR(pScrn); + + via_vt1632_power(output, FALSE); + ViaModeSecondCRTC(pScrn, mode); + via_vt1632_mode_set(output, mode, adjusted_mode); + via_vt1632_power(output, TRUE); +} + +static xf86OutputStatus +via_dvi_detect(xf86OutputPtr output) +{ + xf86OutputStatus status = XF86OutputStatusDisconnected; + ScrnInfoPtr pScrn = output->scrn; + VIAPtr pVia = VIAPTR(pScrn); + xf86MonPtr mon; + + mon = xf86OutputGetEDID(output, pVia->pI2CBus2); + if (mon && DIGITAL(mon->features.input_type)) { + xf86OutputSetEDID(output, mon); + status = XF86OutputStatusConnected; + } else { + status = via_vt1632_detect(output); + } + return status; +} + +static void +via_dvi_destroy(xf86OutputPtr output) +{ +} + +static const xf86OutputFuncsRec via_dvi_funcs = { + .create_resources = via_dvi_create_resources, +#ifdef RANDR_12_INTERFACE + .set_property = via_dvi_set_property, + .get_property = via_dvi_get_property, +#endif + .dpms = via_dvi_dpms, + .save = via_dvi_save, + .restore = via_dvi_restore, + .mode_valid = via_dvi_mode_valid, + .mode_fixup = via_dvi_mode_fixup, + .prepare = via_dvi_prepare, + .commit = via_dvi_commit, + .mode_set = via_dvi_mode_set, + .detect = via_dvi_detect, + .get_modes = xf86OutputGetEDIDModes, + .destroy = via_dvi_destroy, +}; + +void +via_dvi_init(ScrnInfoPtr pScrn) +{ + VIAPtr pVia = VIAPTR(pScrn); + xf86OutputPtr output = NULL; + struct ViaVT1632PrivateData *private_data = NULL; + I2CBusPtr pBus = NULL; + I2CDevPtr pDev = NULL; + + if (!pVia->pI2CBus2 || !pVia->pI2CBus3) { + return; + } + + pDev = xf86CreateI2CDevRec(); + if (!pDev) { + return; + } + + pDev->DevName = "VT1632"; + pDev->SlaveAddr = 0x10; + + if (xf86I2CProbeAddress(pVia->pI2CBus3, pDev->SlaveAddr)) { + pDev->pI2CBus = pVia->pI2CBus3; + } else if (xf86I2CProbeAddress(pVia->pI2CBus2, pDev->SlaveAddr)) { + pDev->pI2CBus = pVia->pI2CBus2; + } else { + xf86DestroyI2CDevRec(pDev, TRUE); + return; + } + + if (!xf86I2CDevInit(pDev)) { + xf86DestroyI2CDevRec(pDev, TRUE); + return; + } + + if (!via_vt1632_probe(pScrn, pDev)) { + xf86DestroyI2CDevRec(pDev, TRUE); + return; + } + + private_data = via_vt1632_init(pScrn, pDev); + if (!private_data) { + xf86DestroyI2CDevRec(pDev, TRUE); + return; + } + + output = xf86OutputCreate(pScrn, &via_dvi_funcs, "DVI-1"); + if (output) { + output->driver_private = private_data; + output->possible_crtcs = 0x2; + output->possible_clones = 0; + output->interlaceAllowed = FALSE; + output->doubleScanAllowed = FALSE; + } +} + diff --git a/src/via_vt1632.c b/src/via_vt1632.c new file mode 100644 index 0000000..bc41128 --- /dev/null +++ b/src/via_vt1632.c @@ -0,0 +1,204 @@ +/* + * Copyright 2014 SHS SERVICES GmbH + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "via_driver.h" +#include "via_vt1632.h" + +static Bool +xf86I2CMaskByte(I2CDevPtr d, I2CByte subaddr, I2CByte value, I2CByte mask) +{ + I2CByte tmp; + Bool ret; + + ret = xf86I2CReadByte(d, subaddr, &tmp); + if (!ret) + return FALSE; + + tmp &= ~mask; + tmp |= (value & mask); + + return xf86I2CWriteByte(d, subaddr, tmp); +} + +static void +via_vt1632_dump_registers(ScrnInfoPtr pScrn, I2CDevPtr pDev) +{ + int i; + CARD8 tmp; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "VT1632: dumping registers:\n")); + for (i = 0; i <= 0x0f; i++) { + xf86I2CReadByte(pDev, i, &tmp); + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "VT1632: 0x%02x: 0x%02x\n", i, tmp)); + } +} + + +void +via_vt1632_power(xf86OutputPtr output, BOOL on) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + + + if (on == TRUE) { + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "VT1632: power on\n")); + xf86I2CMaskByte(Private->VT1632I2CDev, 0x08, 0x01, 0x01); + } else { + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "VT1632: power off\n")); + xf86I2CMaskByte(Private->VT1632I2CDev, 0x08, 0x00, 0x01); + } +} + +void +via_vt1632_save(xf86OutputPtr output) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, + "VT1632: saving state of registers 0x08, 0x09, 0x0A and 0x0C\n")); + + xf86I2CReadByte(Private->VT1632I2CDev, 0x08, &Private->Register08); + xf86I2CReadByte(Private->VT1632I2CDev, 0x09, &Private->Register09); + xf86I2CReadByte(Private->VT1632I2CDev, 0x0A, &Private->Register0A); + xf86I2CReadByte(Private->VT1632I2CDev, 0x0C, &Private->Register0C); +} + +void +via_vt1632_restore(xf86OutputPtr output) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, + "VT1632: restoring register 0x08, 0x09, 0x0A and 0x0C\n")); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x08, Private->Register08); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x09, Private->Register09); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x0A, Private->Register0A); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x0C, Private->Register0C); +} + +int +via_vt1632_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + + if (pMode->Clock < Private->DotclockMin) + return MODE_CLOCK_LOW; + + if (pMode->Clock > Private->DotclockMax) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + +void +via_vt1632_mode_set(xf86OutputPtr output, DisplayModePtr mode, + DisplayModePtr adjusted_mode) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + ScrnInfoPtr pScrn = output->scrn; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, + "VT1632: enabling DVI encoder\n")); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x0C, 0x89); + xf86I2CWriteByte(Private->VT1632I2CDev, 0x08, + VIA_VT1632_VEN | VIA_VT1632_HEN | VIA_VT1632_EDGE | + VIA_VT1632_PDB); + via_vt1632_dump_registers(pScrn, Private->VT1632I2CDev); +} + +xf86OutputStatus +via_vt1632_detect(xf86OutputPtr output) +{ + struct ViaVT1632PrivateData * Private = output->driver_private; + xf86OutputStatus status = XF86OutputStatusDisconnected; + ScrnInfoPtr pScrn = output->scrn; + CARD8 tmp; + + xf86I2CReadByte(Private->VT1632I2CDev, 0x09, &tmp); + if (tmp && 0x02) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1632: DVI is connected\n"); + status = XF86OutputStatusConnected; + } + + return status; +} + +BOOL +via_vt1632_probe(ScrnInfoPtr pScrn, I2CDevPtr pDev) { + CARD8 buf = 0; + CARD16 VendorID = 0; + CARD16 DeviceID = 0; + + xf86I2CReadByte(pDev, 0, &buf); + VendorID = buf; + xf86I2CReadByte(pDev, 1, &buf); + VendorID |= buf << 8; + + xf86I2CReadByte(pDev, 2, &buf); + DeviceID = buf; + xf86I2CReadByte(pDev, 3, &buf); + DeviceID |= buf << 8; + + if (VendorID != 0x1106 || DeviceID != 0x3192) { + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1632 DVI transmitter detected\n"); + + return TRUE; +} + +struct ViaVT1632PrivateData * +via_vt1632_init(ScrnInfoPtr pScrn, I2CDevPtr pDev) +{ + VIAPtr pVia = VIAPTR(pScrn); + struct ViaVT1632PrivateData * Private = NULL; + CARD8 buf = 0; + + Private = xnfcalloc(1, sizeof(struct ViaVT1632PrivateData)); + if (!Private) { + return NULL; + } + Private->VT1632I2CDev = pDev; + + xf86I2CReadByte(pDev, 0x06, &buf); + Private->DotclockMin = buf * 1000; + + xf86I2CReadByte(pDev, 0x07, &buf); + Private->DotclockMax = (buf + 65) * 1000; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1632: dotclock range %d-%dMHz\n", + Private->DotclockMin / 1000, + Private->DotclockMax / 1000); + + via_vt1632_dump_registers(pScrn, pDev); + + return Private; +} diff --git a/src/via_vt1632.h b/src/via_vt1632.h new file mode 100644 index 0000000..535bf17 --- /dev/null +++ b/src/via_vt1632.h @@ -0,0 +1,54 @@ +/* + * Copyright 2014 SHS SERVICES GmbH + * + * 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 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. + */ + +#ifndef _VIA_VT1632_H_ +#define _VIA_VT1632_H_ 1 + +#define VIA_VT1632_VEN 0x20 +#define VIA_VT1632_HEN 0x10 +#define VIA_VT1632_DSEL 0x08 +#define VIA_VT1632_BSEL 0x04 +#define VIA_VT1632_EDGE 0x02 +#define VIA_VT1632_PDB 0x01 + +struct ViaVT1632PrivateData { + I2CDevPtr VT1632I2CDev; + + int DotclockMin; + int DotclockMax; + CARD8 Register08; + CARD8 Register09; + CARD8 Register0A; + CARD8 Register0C; +}; + +void via_vt1632_power(xf86OutputPtr output, BOOL on); +void via_vt1632_save(xf86OutputPtr output); +void via_vt1632_restore(xf86OutputPtr output); +int via_vt1632_mode_valid(xf86OutputPtr output, DisplayModePtr pMode); +void via_vt1632_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode); +xf86OutputStatus via_vt1632_detect(xf86OutputPtr output); +BOOL via_vt1632_probe(ScrnInfoPtr pScrn, I2CDevPtr pDev); +struct ViaVT1632PrivateData * via_vt1632_init(ScrnInfoPtr pScrn, I2CDevPtr pDev); + +#endif /* _VIA_VT1632_H_ */ |