1fa225cbcSrjs/* -*- c-basic-offset: 4 -*- */ 2fa225cbcSrjs/************************************************************************** 3fa225cbcSrjs 4fa225cbcSrjsCopyright © 2006 Dave Airlie 5fa225cbcSrjs 6fa225cbcSrjsAll Rights Reserved. 7fa225cbcSrjs 8fa225cbcSrjsPermission is hereby granted, free of charge, to any person obtaining a 9fa225cbcSrjscopy of this software and associated documentation files (the 10fa225cbcSrjs"Software"), to deal in the Software without restriction, including 11fa225cbcSrjswithout limitation the rights to use, copy, modify, merge, publish, 12fa225cbcSrjsdistribute, sub license, and/or sell copies of the Software, and to 13fa225cbcSrjspermit persons to whom the Software is furnished to do so, subject to 14fa225cbcSrjsthe following conditions: 15fa225cbcSrjs 16fa225cbcSrjsThe above copyright notice and this permission notice (including the 17fa225cbcSrjsnext paragraph) shall be included in all copies or substantial portions 18fa225cbcSrjsof the Software. 19fa225cbcSrjs 20fa225cbcSrjsTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21fa225cbcSrjsOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22fa225cbcSrjsMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23fa225cbcSrjsIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 24fa225cbcSrjsANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25fa225cbcSrjsTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26fa225cbcSrjsSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27fa225cbcSrjs 28fa225cbcSrjs**************************************************************************/ 29fa225cbcSrjs 30fa225cbcSrjs#ifdef HAVE_CONFIG_H 31fa225cbcSrjs#include "config.h" 32fa225cbcSrjs#endif 33fa225cbcSrjs 34fa225cbcSrjs#include <stdint.h> 35fa225cbcSrjs 36fa225cbcSrjs#include "xf86.h" 37fa225cbcSrjs#include "xf86_OSproc.h" 38fa225cbcSrjs#include "compiler.h" 39fa225cbcSrjs#include "miscstruct.h" 40fa225cbcSrjs#include "xf86i2c.h" 41fa225cbcSrjs#include "xf86Crtc.h" 42fa225cbcSrjs#ifdef HAVE_XEXTPROTO_71 43fa225cbcSrjs#include <X11/extensions/dpmsconst.h> 44fa225cbcSrjs#else 45fa225cbcSrjs#define DPMS_SERVER 46fa225cbcSrjs#include <X11/extensions/dpms.h> 47fa225cbcSrjs#endif 48fa225cbcSrjs 49fa225cbcSrjs 50fa225cbcSrjs#include "../i2c_vid.h" 51fa225cbcSrjs#include "sil164.h" 52fa225cbcSrjs#include "sil164_reg.h" 53fa225cbcSrjs 54fa225cbcSrjstypedef struct _Sil164SaveRec { 55fa225cbcSrjs uint8_t reg8; 56fa225cbcSrjs uint8_t reg9; 57fa225cbcSrjs uint8_t regc; 58fa225cbcSrjs} SIL164SaveRec; 59fa225cbcSrjs 60fa225cbcSrjstypedef struct { 61fa225cbcSrjs I2CDevRec d; 62fa225cbcSrjs Bool quiet; 63fa225cbcSrjs SIL164SaveRec SavedReg; 64fa225cbcSrjs SIL164SaveRec ModeReg; 65fa225cbcSrjs} SIL164Rec, *SIL164Ptr; 66fa225cbcSrjs 67fa225cbcSrjs#define SILPTR(d) ((SIL164Ptr)(d->DriverPrivate.ptr)) 68fa225cbcSrjs 69fa225cbcSrjsstatic Bool 70fa225cbcSrjssil164ReadByte(SIL164Ptr sil, int addr, uint8_t *ch) 71fa225cbcSrjs{ 72fa225cbcSrjs if (!xf86I2CReadByte(&(sil->d), addr, ch)) { 73fa225cbcSrjs if (!sil->quiet) { 74fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, 75fa225cbcSrjs "Unable to read from %s Slave %d.\n", 76fa225cbcSrjs sil->d.pI2CBus->BusName, sil->d.SlaveAddr); 77fa225cbcSrjs } 78fa225cbcSrjs return FALSE; 79fa225cbcSrjs } 80fa225cbcSrjs return TRUE; 81fa225cbcSrjs} 82fa225cbcSrjs 83fa225cbcSrjsstatic Bool 84fa225cbcSrjssil164WriteByte(SIL164Ptr sil, int addr, uint8_t ch) 85fa225cbcSrjs{ 86fa225cbcSrjs if (!xf86I2CWriteByte(&(sil->d), addr, ch)) { 87fa225cbcSrjs if (!sil->quiet) { 88fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, 89fa225cbcSrjs "Unable to write to %s Slave %d.\n", 90fa225cbcSrjs sil->d.pI2CBus->BusName, sil->d.SlaveAddr); 91fa225cbcSrjs } 92fa225cbcSrjs return FALSE; 93fa225cbcSrjs } 94fa225cbcSrjs return TRUE; 95fa225cbcSrjs} 96fa225cbcSrjs 97fa225cbcSrjs/* Silicon Image 164 driver for chip on i2c bus */ 98fa225cbcSrjsstatic void * 99fa225cbcSrjssil164_init(I2CBusPtr b, I2CSlaveAddr addr) 100fa225cbcSrjs{ 101fa225cbcSrjs /* this will detect the SIL164 chip on the specified i2c bus */ 102fa225cbcSrjs SIL164Ptr sil; 103fa225cbcSrjs unsigned char ch; 104fa225cbcSrjs 105fa225cbcSrjs sil = xcalloc(1, sizeof(SIL164Rec)); 106fa225cbcSrjs if (sil == NULL) 107fa225cbcSrjs return NULL; 108fa225cbcSrjs 109fa225cbcSrjs sil->d.DevName = "SIL164 TMDS Controller"; 110fa225cbcSrjs sil->d.SlaveAddr = addr; 111fa225cbcSrjs sil->d.pI2CBus = b; 112fa225cbcSrjs sil->d.StartTimeout = b->StartTimeout; 113fa225cbcSrjs sil->d.BitTimeout = b->BitTimeout; 114fa225cbcSrjs sil->d.AcknTimeout = b->AcknTimeout; 115fa225cbcSrjs sil->d.ByteTimeout = b->ByteTimeout; 116fa225cbcSrjs sil->d.DriverPrivate.ptr = sil; 117fa225cbcSrjs sil->quiet = TRUE; 118fa225cbcSrjs 119fa225cbcSrjs if (!sil164ReadByte(sil, SIL164_VID_LO, &ch)) 120fa225cbcSrjs goto out; 121fa225cbcSrjs 122fa225cbcSrjs if (ch!=(SIL164_VID & 0xFF)) { 123fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, 124fa225cbcSrjs "sil164 not detected got %d: from %s Slave %d.\n", 125fa225cbcSrjs ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); 126fa225cbcSrjs goto out; 127fa225cbcSrjs } 128fa225cbcSrjs 129fa225cbcSrjs if (!sil164ReadByte(sil, SIL164_DID_LO, &ch)) 130fa225cbcSrjs goto out; 131fa225cbcSrjs 132fa225cbcSrjs if (ch!=(SIL164_DID & 0xFF)) { 133fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_ERROR, 134fa225cbcSrjs "sil164 not detected got %d: from %s Slave %d.\n", 135fa225cbcSrjs ch, sil->d.pI2CBus->BusName, sil->d.SlaveAddr); 136fa225cbcSrjs goto out; 137fa225cbcSrjs } 138fa225cbcSrjs sil->quiet = FALSE; 139fa225cbcSrjs 140fa225cbcSrjs if (!xf86I2CDevInit(&(sil->d))) { 141fa225cbcSrjs goto out; 142fa225cbcSrjs } 143fa225cbcSrjs 144fa225cbcSrjs return sil; 145fa225cbcSrjs 146fa225cbcSrjsout: 147fa225cbcSrjs xfree(sil); 148fa225cbcSrjs return NULL; 149fa225cbcSrjs} 150fa225cbcSrjs 151fa225cbcSrjsstatic xf86OutputStatus 152fa225cbcSrjssil164_detect(I2CDevPtr d) 153fa225cbcSrjs{ 154fa225cbcSrjs SIL164Ptr sil = SILPTR(d); 155fa225cbcSrjs uint8_t reg9; 156fa225cbcSrjs 157fa225cbcSrjs sil164ReadByte(sil, SIL164_REG9, ®9); 158fa225cbcSrjs 159fa225cbcSrjs if (reg9 & SIL164_9_HTPLG) 160fa225cbcSrjs return XF86OutputStatusConnected; 161fa225cbcSrjs else 162fa225cbcSrjs return XF86OutputStatusDisconnected; 163fa225cbcSrjs} 164fa225cbcSrjs 165fa225cbcSrjsstatic ModeStatus 166fa225cbcSrjssil164_mode_valid(I2CDevPtr d, DisplayModePtr mode) 167fa225cbcSrjs{ 168fa225cbcSrjs return MODE_OK; 169fa225cbcSrjs} 170fa225cbcSrjs 171fa225cbcSrjsstatic void 172fa225cbcSrjssil164_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode) 173fa225cbcSrjs{ 174fa225cbcSrjs /* As long as the basics are set up, since we don't have clock dependencies 175fa225cbcSrjs * in the mode setup, we can just leave the registers alone and everything 176fa225cbcSrjs * will work fine. 177fa225cbcSrjs */ 178fa225cbcSrjs /* recommended programming sequence from doc */ 179fa225cbcSrjs /*sil164WriteByte(sil, 0x08, 0x30); 180fa225cbcSrjs sil164WriteByte(sil, 0x09, 0x00); 181fa225cbcSrjs sil164WriteByte(sil, 0x0a, 0x90); 182fa225cbcSrjs sil164WriteByte(sil, 0x0c, 0x89); 183fa225cbcSrjs sil164WriteByte(sil, 0x08, 0x31);*/ 184fa225cbcSrjs /* don't do much */ 185fa225cbcSrjs return; 186fa225cbcSrjs} 187fa225cbcSrjs 188fa225cbcSrjs/* set the SIL164 power state */ 189fa225cbcSrjsstatic void 190fa225cbcSrjssil164_dpms(I2CDevPtr d, int mode) 191fa225cbcSrjs{ 192fa225cbcSrjs SIL164Ptr sil = SILPTR(d); 193fa225cbcSrjs int ret; 194fa225cbcSrjs unsigned char ch; 195fa225cbcSrjs 196fa225cbcSrjs ret = sil164ReadByte(sil, SIL164_REG8, &ch); 197fa225cbcSrjs if (ret == FALSE) 198fa225cbcSrjs return; 199fa225cbcSrjs 200fa225cbcSrjs if (mode == DPMSModeOn) 201fa225cbcSrjs ch |= SIL164_8_PD; 202fa225cbcSrjs else 203fa225cbcSrjs ch &= ~SIL164_8_PD; 204fa225cbcSrjs 205fa225cbcSrjs sil164WriteByte(sil, SIL164_REG8, ch); 206fa225cbcSrjs 207fa225cbcSrjs return; 208fa225cbcSrjs} 209fa225cbcSrjs 210fa225cbcSrjsstatic void 211fa225cbcSrjssil164_dump_regs(I2CDevPtr d) 212fa225cbcSrjs{ 213fa225cbcSrjs SIL164Ptr sil = SILPTR(d); 214fa225cbcSrjs uint8_t val; 215fa225cbcSrjs 216fa225cbcSrjs sil164ReadByte(sil, SIL164_FREQ_LO, &val); 217fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_LO: 0x%02x\n", 218fa225cbcSrjs val); 219fa225cbcSrjs sil164ReadByte(sil, SIL164_FREQ_HI, &val); 220fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_FREQ_HI: 0x%02x\n", 221fa225cbcSrjs val); 222fa225cbcSrjs sil164ReadByte(sil, SIL164_REG8, &val); 223fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG8: 0x%02x\n", val); 224fa225cbcSrjs sil164ReadByte(sil, SIL164_REG9, &val); 225fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REG9: 0x%02x\n", val); 226fa225cbcSrjs sil164ReadByte(sil, SIL164_REGC, &val); 227fa225cbcSrjs xf86DrvMsg(sil->d.pI2CBus->scrnIndex, X_INFO, "SIL164_REGC: 0x%02x\n", val); 228fa225cbcSrjs} 229fa225cbcSrjs 230fa225cbcSrjsstatic void 231fa225cbcSrjssil164_save(I2CDevPtr d) 232fa225cbcSrjs{ 233fa225cbcSrjs SIL164Ptr sil = SILPTR(d); 234fa225cbcSrjs 235fa225cbcSrjs if (!sil164ReadByte(sil, SIL164_REG8, &sil->SavedReg.reg8)) 236fa225cbcSrjs return; 237fa225cbcSrjs 238fa225cbcSrjs if (!sil164ReadByte(sil, SIL164_REG9, &sil->SavedReg.reg9)) 239fa225cbcSrjs return; 240fa225cbcSrjs 241fa225cbcSrjs if (!sil164ReadByte(sil, SIL164_REGC, &sil->SavedReg.regc)) 242fa225cbcSrjs return; 243fa225cbcSrjs 244fa225cbcSrjs return; 245fa225cbcSrjs} 246fa225cbcSrjs 247fa225cbcSrjsstatic void 248fa225cbcSrjssil164_restore(I2CDevPtr d) 249fa225cbcSrjs{ 250fa225cbcSrjs SIL164Ptr sil = SILPTR(d); 251fa225cbcSrjs 252fa225cbcSrjs /* Restore it powered down initially */ 253fa225cbcSrjs sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8 & ~0x1); 254fa225cbcSrjs 255fa225cbcSrjs sil164WriteByte(sil, SIL164_REG9, sil->SavedReg.reg9); 256fa225cbcSrjs sil164WriteByte(sil, SIL164_REGC, sil->SavedReg.regc); 257fa225cbcSrjs sil164WriteByte(sil, SIL164_REG8, sil->SavedReg.reg8); 258fa225cbcSrjs} 259fa225cbcSrjs 260fa225cbcSrjs 261fa225cbcSrjs_X_EXPORT I830I2CVidOutputRec SIL164VidOutput = { 262fa225cbcSrjs .init = sil164_init, 263fa225cbcSrjs .detect = sil164_detect, 264fa225cbcSrjs .mode_valid = sil164_mode_valid, 265fa225cbcSrjs .mode_set = sil164_mode_set, 266fa225cbcSrjs .dpms = sil164_dpms, 267fa225cbcSrjs .dump_regs = sil164_dump_regs, 268fa225cbcSrjs .save = sil164_save, 269fa225cbcSrjs .restore = sil164_restore, 270fa225cbcSrjs}; 271