1fa225cbcSrjs/* -*- c-basic-offset: 4 -*- */ 2fa225cbcSrjs/* 3fa225cbcSrjs * Copyright © 2007 Dave Mueller 4fa225cbcSrjs * 5fa225cbcSrjs * Permission is hereby granted, free of charge, to any person obtaining a 6fa225cbcSrjs * copy of this software and associated documentation files (the "Software"), 7fa225cbcSrjs * to deal in the Software without restriction, including without limitation 8fa225cbcSrjs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9fa225cbcSrjs * and/or sell copies of the Software, and to permit persons to whom the 10fa225cbcSrjs * Software is furnished to do so, subject to the following conditions: 11fa225cbcSrjs * 12fa225cbcSrjs * The above copyright notice and this permission notice (including the next 13fa225cbcSrjs * paragraph) shall be included in all copies or substantial portions of the 14fa225cbcSrjs * Software. 15fa225cbcSrjs * 16fa225cbcSrjs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17fa225cbcSrjs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18fa225cbcSrjs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19fa225cbcSrjs * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20fa225cbcSrjs * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21fa225cbcSrjs * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22fa225cbcSrjs * IN THE SOFTWARE. 23fa225cbcSrjs * 24fa225cbcSrjs * Authors: 25fa225cbcSrjs * Dave Mueller <dave.mueller@gmx.ch> 26fa225cbcSrjs * 27fa225cbcSrjs */ 28fa225cbcSrjs 29fa225cbcSrjs#ifdef HAVE_CONFIG_H 30fa225cbcSrjs#include "config.h" 31fa225cbcSrjs#endif 32fa225cbcSrjs 33fa225cbcSrjs#include <stdint.h> 34fa225cbcSrjs 35fa225cbcSrjs#include "xf86.h" 36fa225cbcSrjs#include "xf86_OSproc.h" 37fa225cbcSrjs#include "compiler.h" 38fa225cbcSrjs#include "miscstruct.h" 39fa225cbcSrjs#include "xf86i2c.h" 40fa225cbcSrjs#include "xf86Crtc.h" 41fa225cbcSrjs#ifdef HAVE_XEXTPROTO_71 42fa225cbcSrjs#include <X11/extensions/dpmsconst.h> 43fa225cbcSrjs#else 44fa225cbcSrjs#define DPMS_SERVER 45fa225cbcSrjs#include <X11/extensions/dpms.h> 46fa225cbcSrjs#endif 47fa225cbcSrjs 48fa225cbcSrjs 49fa225cbcSrjs#include "../i2c_vid.h" 50fa225cbcSrjs#include "tfp410.h" 51fa225cbcSrjs#include "tfp410_reg.h" 52fa225cbcSrjs 53fa225cbcSrjstypedef struct _TFP410SaveRec { 54fa225cbcSrjs uint8_t ctl1; 55fa225cbcSrjs uint8_t ctl2; 56fa225cbcSrjs} TFP410SaveRec; 57fa225cbcSrjs 58fa225cbcSrjstypedef struct { 59fa225cbcSrjs I2CDevRec d; 60fa225cbcSrjs Bool quiet; 61fa225cbcSrjs 62fa225cbcSrjs TFP410SaveRec SavedReg; 63fa225cbcSrjs TFP410SaveRec ModeReg; 64fa225cbcSrjs} TFP410Rec, *TFP410Ptr; 65fa225cbcSrjs 66fa225cbcSrjs#define TFPPTR(d) ((TFP410Ptr)(d->DriverPrivate.ptr)) 67fa225cbcSrjs 68fa225cbcSrjsstatic Bool 69fa225cbcSrjstfp410ReadByte(TFP410Ptr tfp, int addr, uint8_t *ch) 70fa225cbcSrjs{ 71fa225cbcSrjs if (!xf86I2CReadByte(&(tfp->d), addr, ch)) { 72fa225cbcSrjs if (!tfp->quiet) { 73fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, 74fa225cbcSrjs "Unable to read from %s Slave %d.\n", 75fa225cbcSrjs tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); 76fa225cbcSrjs } 77fa225cbcSrjs return FALSE; 78fa225cbcSrjs } 79fa225cbcSrjs return TRUE; 80fa225cbcSrjs} 81fa225cbcSrjs 82fa225cbcSrjsstatic Bool 83fa225cbcSrjstfp410WriteByte(TFP410Ptr tfp, int addr, uint8_t ch) 84fa225cbcSrjs{ 85fa225cbcSrjs if (!xf86I2CWriteByte(&(tfp->d), addr, ch)) { 86fa225cbcSrjs if (!tfp->quiet) { 87fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, 88fa225cbcSrjs "Unable to write to %s Slave %d.\n", 89fa225cbcSrjs tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); 90fa225cbcSrjs } 91fa225cbcSrjs return FALSE; 92fa225cbcSrjs } 93fa225cbcSrjs return TRUE; 94fa225cbcSrjs} 95fa225cbcSrjs 96fa225cbcSrjsstatic int 97fa225cbcSrjstfp410GetID(TFP410Ptr tfp, int addr) 98fa225cbcSrjs{ 99fa225cbcSrjs unsigned char ch1, ch2; 100fa225cbcSrjs 101fa225cbcSrjs if (tfp410ReadByte(tfp, addr+0, &ch1) && 102fa225cbcSrjs tfp410ReadByte(tfp, addr+1, &ch2)) { 103fa225cbcSrjs 104fa225cbcSrjs return ((ch2<<8) & 0xFF00) | (ch1 & 0x00FF); 105fa225cbcSrjs } 106fa225cbcSrjs return -1; 107fa225cbcSrjs} 108fa225cbcSrjs 109fa225cbcSrjs/* Ti TFP410 driver for chip on i2c bus */ 110fa225cbcSrjsstatic void * 111fa225cbcSrjstfp410_init(I2CBusPtr b, I2CSlaveAddr addr) 112fa225cbcSrjs{ 113fa225cbcSrjs /* this will detect the tfp410 chip on the specified i2c bus */ 114fa225cbcSrjs TFP410Ptr tfp; 115fa225cbcSrjs int id; 116fa225cbcSrjs 117fa225cbcSrjs tfp = xcalloc(1, sizeof(TFP410Rec)); 118fa225cbcSrjs if (tfp == NULL) 119fa225cbcSrjs return NULL; 120fa225cbcSrjs 121fa225cbcSrjs tfp->d.DevName = "TFP410 TMDS Controller"; 122fa225cbcSrjs tfp->d.SlaveAddr = addr; 123fa225cbcSrjs tfp->d.pI2CBus = b; 124fa225cbcSrjs tfp->d.StartTimeout = b->StartTimeout; 125fa225cbcSrjs tfp->d.BitTimeout = b->BitTimeout; 126fa225cbcSrjs tfp->d.AcknTimeout = b->AcknTimeout; 127fa225cbcSrjs tfp->d.ByteTimeout = b->ByteTimeout; 128fa225cbcSrjs tfp->d.DriverPrivate.ptr = tfp; 129fa225cbcSrjs tfp->quiet = TRUE; 130fa225cbcSrjs 131fa225cbcSrjs if ((id = tfp410GetID(tfp, TFP410_VID_LO)) != TFP410_VID) { 132fa225cbcSrjs if (id != 0xffffffff) { 133fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, 134fa225cbcSrjs "tfp410 not detected got VID %X: from %s Slave %d.\n", 135fa225cbcSrjs id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); 136fa225cbcSrjs } 137fa225cbcSrjs goto out; 138fa225cbcSrjs } 139fa225cbcSrjs 140fa225cbcSrjs if ((id = tfp410GetID(tfp, TFP410_DID_LO)) != TFP410_DID) { 141fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_ERROR, 142fa225cbcSrjs "tfp410 not detected got DID %X: from %s Slave %d.\n", 143fa225cbcSrjs id, tfp->d.pI2CBus->BusName, tfp->d.SlaveAddr); 144fa225cbcSrjs goto out; 145fa225cbcSrjs } 146fa225cbcSrjs tfp->quiet = FALSE; 147fa225cbcSrjs 148fa225cbcSrjs if (!xf86I2CDevInit(&(tfp->d))) { 149fa225cbcSrjs goto out; 150fa225cbcSrjs } 151fa225cbcSrjs 152fa225cbcSrjs return tfp; 153fa225cbcSrjs 154fa225cbcSrjsout: 155fa225cbcSrjs xfree(tfp); 156fa225cbcSrjs return NULL; 157fa225cbcSrjs} 158fa225cbcSrjs 159fa225cbcSrjsstatic xf86OutputStatus 160fa225cbcSrjstfp410_detect(I2CDevPtr d) 161fa225cbcSrjs{ 162fa225cbcSrjs TFP410Ptr tfp = TFPPTR(d); 163fa225cbcSrjs xf86OutputStatus ret = XF86OutputStatusDisconnected; 164fa225cbcSrjs unsigned char ctl2; 165fa225cbcSrjs 166fa225cbcSrjs if (tfp410ReadByte(tfp, TFP410_CTL_2, &ctl2)) { 167fa225cbcSrjs if (ctl2 & TFP410_CTL_2_HTPLG) 168fa225cbcSrjs ret = XF86OutputStatusConnected; 169fa225cbcSrjs else 170fa225cbcSrjs ret = XF86OutputStatusDisconnected; 171fa225cbcSrjs } 172fa225cbcSrjs 173fa225cbcSrjs return ret; 174fa225cbcSrjs} 175fa225cbcSrjs 176fa225cbcSrjsstatic ModeStatus 177fa225cbcSrjstfp410_mode_valid(I2CDevPtr d, DisplayModePtr mode) 178fa225cbcSrjs{ 179fa225cbcSrjs return MODE_OK; 180fa225cbcSrjs} 181fa225cbcSrjs 182fa225cbcSrjsstatic void 183fa225cbcSrjstfp410_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode) 184fa225cbcSrjs{ 185fa225cbcSrjs /* As long as the basics are set up, since we don't have clock dependencies 186fa225cbcSrjs * in the mode setup, we can just leave the registers alone and everything 187fa225cbcSrjs * will work fine. 188fa225cbcSrjs */ 189fa225cbcSrjs /* don't do much */ 190fa225cbcSrjs return; 191fa225cbcSrjs} 192fa225cbcSrjs 193fa225cbcSrjs/* set the tfp410 power state */ 194fa225cbcSrjsstatic void 195fa225cbcSrjstfp410_dpms(I2CDevPtr d, int mode) 196fa225cbcSrjs{ 197fa225cbcSrjs TFP410Ptr tfp = TFPPTR(d); 198fa225cbcSrjs unsigned char ctl1; 199fa225cbcSrjs 200fa225cbcSrjs if (!tfp410ReadByte(tfp, TFP410_CTL_1, &ctl1)) 201fa225cbcSrjs return; 202fa225cbcSrjs 203fa225cbcSrjs if (mode == DPMSModeOn) 204fa225cbcSrjs ctl1 |= TFP410_CTL_1_PD; 205fa225cbcSrjs else 206fa225cbcSrjs ctl1 &= ~TFP410_CTL_1_PD; 207fa225cbcSrjs 208fa225cbcSrjs tfp410WriteByte(tfp, TFP410_CTL_1, ctl1); 209fa225cbcSrjs} 210fa225cbcSrjs 211fa225cbcSrjsstatic void 212fa225cbcSrjstfp410_dump_regs(I2CDevPtr d) 213fa225cbcSrjs{ 214fa225cbcSrjs TFP410Ptr tfp = TFPPTR(d); 215fa225cbcSrjs uint8_t val, val2; 216fa225cbcSrjs 217fa225cbcSrjs tfp410ReadByte(tfp, TFP410_REV, &val); 218fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 219fa225cbcSrjs "TFP410_REV: 0x%02X\n", val); 220fa225cbcSrjs tfp410ReadByte(tfp, TFP410_CTL_1, &val); 221fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 222fa225cbcSrjs "TFP410_CTL1: 0x%02X\n", val); 223fa225cbcSrjs tfp410ReadByte(tfp, TFP410_CTL_2, &val); 224fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 225fa225cbcSrjs "TFP410_CTL2: 0x%02X\n", val); 226fa225cbcSrjs tfp410ReadByte(tfp, TFP410_CTL_3, &val); 227fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 228fa225cbcSrjs "TFP410_CTL3: 0x%02X\n", val); 229fa225cbcSrjs tfp410ReadByte(tfp, TFP410_USERCFG, &val); 230fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 231fa225cbcSrjs "TFP410_USERCFG: 0x%02X\n", val); 232fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_DLY, &val); 233fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 234fa225cbcSrjs "TFP410_DE_DLY: 0x%02X\n", val); 235fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_CTL, &val); 236fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 237fa225cbcSrjs "TFP410_DE_CTL: 0x%02X\n", val); 238fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_TOP, &val); 239fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 240fa225cbcSrjs "TFP410_DE_TOP: 0x%02X\n", val); 241fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_CNT_LO, &val); 242fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_CNT_HI, &val2); 243fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 244fa225cbcSrjs "TFP410_DE_CNT: 0x%02X%02X\n", val2, val); 245fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_LIN_LO, &val); 246fa225cbcSrjs tfp410ReadByte(tfp, TFP410_DE_LIN_HI, &val2); 247fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 248fa225cbcSrjs "TFP410_DE_LIN: 0x%02X%02X\n", val2, val); 249fa225cbcSrjs tfp410ReadByte(tfp, TFP410_H_RES_LO, &val); 250fa225cbcSrjs tfp410ReadByte(tfp, TFP410_H_RES_HI, &val2); 251fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 252fa225cbcSrjs "TFP410_H_RES: 0x%02X%02X\n", val2, val); 253fa225cbcSrjs tfp410ReadByte(tfp, TFP410_V_RES_LO, &val); 254fa225cbcSrjs tfp410ReadByte(tfp, TFP410_V_RES_HI, &val2); 255fa225cbcSrjs xf86DrvMsg(tfp->d.pI2CBus->scrnIndex, X_INFO, 256fa225cbcSrjs "TFP410_V_RES: 0x%02X%02X\n", val2, val); 257fa225cbcSrjs} 258fa225cbcSrjs 259fa225cbcSrjsstatic void 260fa225cbcSrjstfp410_save(I2CDevPtr d) 261fa225cbcSrjs{ 262fa225cbcSrjs TFP410Ptr tfp = TFPPTR(d); 263fa225cbcSrjs 264fa225cbcSrjs if (!tfp410ReadByte(tfp, TFP410_CTL_1, &tfp->SavedReg.ctl1)) 265fa225cbcSrjs return; 266fa225cbcSrjs 267fa225cbcSrjs if (!tfp410ReadByte(tfp, TFP410_CTL_2, &tfp->SavedReg.ctl2)) 268fa225cbcSrjs return; 269fa225cbcSrjs} 270fa225cbcSrjs 271fa225cbcSrjsstatic void 272fa225cbcSrjstfp410_restore(I2CDevPtr d) 273fa225cbcSrjs{ 274fa225cbcSrjs TFP410Ptr tfp = TFPPTR(d); 275fa225cbcSrjs 276fa225cbcSrjs /* Restore it powered down initially */ 277fa225cbcSrjs tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1 & ~0x1); 278fa225cbcSrjs 279fa225cbcSrjs tfp410WriteByte(tfp, TFP410_CTL_2, tfp->SavedReg.ctl2); 280fa225cbcSrjs tfp410WriteByte(tfp, TFP410_CTL_1, tfp->SavedReg.ctl1); 281fa225cbcSrjs} 282fa225cbcSrjs 283fa225cbcSrjs_X_EXPORT I830I2CVidOutputRec TFP410VidOutput = { 284fa225cbcSrjs .init = tfp410_init, 285fa225cbcSrjs .detect = tfp410_detect, 286fa225cbcSrjs .mode_valid = tfp410_mode_valid, 287fa225cbcSrjs .mode_set = tfp410_mode_set, 288fa225cbcSrjs .dpms = tfp410_dpms, 289fa225cbcSrjs .dump_regs = tfp410_dump_regs, 290fa225cbcSrjs .save = tfp410_save, 291fa225cbcSrjs .restore = tfp410_restore, 292fa225cbcSrjs}; 293