ffb_ddc.c revision dbbd9e4b
1dbbd9e4bSmacallan/* 2dbbd9e4bSmacallan * Acceleration for the Creator and Creator3D framebuffer - DDC support. 3dbbd9e4bSmacallan * 4dbbd9e4bSmacallan * Copyright (C) 2000 David S. Miller (davem@redhat.com) 5dbbd9e4bSmacallan * 6dbbd9e4bSmacallan * Permission is hereby granted, free of charge, to any person obtaining a copy 7dbbd9e4bSmacallan * of this software and associated documentation files (the "Software"), to deal 8dbbd9e4bSmacallan * in the Software without restriction, including without limitation the rights 9dbbd9e4bSmacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10dbbd9e4bSmacallan * copies of the Software, and to permit persons to whom the Software is 11dbbd9e4bSmacallan * furnished to do so, subject to the following conditions: 12dbbd9e4bSmacallan * 13dbbd9e4bSmacallan * The above copyright notice and this permission notice shall be included in 14dbbd9e4bSmacallan * all copies or substantial portions of the Software. 15dbbd9e4bSmacallan * 16dbbd9e4bSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17dbbd9e4bSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18dbbd9e4bSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19dbbd9e4bSmacallan * DAVID MILLER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20dbbd9e4bSmacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21dbbd9e4bSmacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22dbbd9e4bSmacallan * 23dbbd9e4bSmacallan */ 24dbbd9e4bSmacallan/* $XFree86$ */ 25dbbd9e4bSmacallan 26dbbd9e4bSmacallan#ifdef HAVE_CONFIG_H 27dbbd9e4bSmacallan#include "config.h" 28dbbd9e4bSmacallan#endif 29dbbd9e4bSmacallan 30dbbd9e4bSmacallan#include "ffb.h" 31dbbd9e4bSmacallan 32dbbd9e4bSmacallan#include "ffb_dac.h" 33dbbd9e4bSmacallan 34dbbd9e4bSmacallan#include "xf86.h" 35dbbd9e4bSmacallan#include "xf86_OSproc.h" 36dbbd9e4bSmacallan 37dbbd9e4bSmacallan#include "xf86DDC.h" 38dbbd9e4bSmacallan 39dbbd9e4bSmacallan/* XXX This needs a lot more work. Only an attempt at the PAC2 version 40dbbd9e4bSmacallan * XXX is below, and that is untested. The BT498 manual is unclear about 41dbbd9e4bSmacallan * XXX several details and I must figure them out by trial and error. 42dbbd9e4bSmacallan */ 43dbbd9e4bSmacallan 44dbbd9e4bSmacallan/* Wait for the next VSYNC. */ 45dbbd9e4bSmacallanstatic void 46dbbd9e4bSmacallanWaitForVSYNC(ffb_dacPtr dac) 47dbbd9e4bSmacallan{ 48dbbd9e4bSmacallan unsigned int vsap = DACCFG_READ(dac, FFBDAC_CFG_VSAP); 49dbbd9e4bSmacallan unsigned int vcnt; 50dbbd9e4bSmacallan 51dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 52dbbd9e4bSmacallan while (vcnt > vsap) 53dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 54dbbd9e4bSmacallan while (vcnt <= vsap) 55dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 56dbbd9e4bSmacallan 57dbbd9e4bSmacallan} 58dbbd9e4bSmacallan 59dbbd9e4bSmacallan/* The manual seems to imply this is needed, but it's really clumsy 60dbbd9e4bSmacallan * so we can test if it really is a requirement with this. 61dbbd9e4bSmacallan */ 62dbbd9e4bSmacallan#define MDATA_NEEDS_BLANK 63dbbd9e4bSmacallan 64dbbd9e4bSmacallan/* DDC1/DDC2 support */ 65dbbd9e4bSmacallanstatic unsigned int 66dbbd9e4bSmacallanFFBDacDdc1Read(ScrnInfoPtr pScrn) 67dbbd9e4bSmacallan{ 68dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 69dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 70dbbd9e4bSmacallan unsigned int val; 71dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 72dbbd9e4bSmacallan unsigned int uctrl; 73dbbd9e4bSmacallan#endif 74dbbd9e4bSmacallan 75dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 76dbbd9e4bSmacallan /* Force a blank of the screen. */ 77dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 78dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 79dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 80dbbd9e4bSmacallan#endif 81dbbd9e4bSmacallan 82dbbd9e4bSmacallan /* Tristate SCL pin. */ 83dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 84dbbd9e4bSmacallan FFBDAC_CFG_MPDATA_SCL); 85dbbd9e4bSmacallan 86dbbd9e4bSmacallan /* Pause until VSYNC is hit. */ 87dbbd9e4bSmacallan WaitForVSYNC(dac); 88dbbd9e4bSmacallan 89dbbd9e4bSmacallan /* Read the sense line to see what the monitor is driving 90dbbd9e4bSmacallan * it at. 91dbbd9e4bSmacallan */ 92dbbd9e4bSmacallan val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE); 93dbbd9e4bSmacallan val = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0; 94dbbd9e4bSmacallan 95dbbd9e4bSmacallan /* Stop tristating the SCL pin. */ 96dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0); 97dbbd9e4bSmacallan 98dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 99dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 100dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 101dbbd9e4bSmacallan#endif 102dbbd9e4bSmacallan 103dbbd9e4bSmacallan /* Return the result and we're done. */ 104dbbd9e4bSmacallan return val; 105dbbd9e4bSmacallan} 106dbbd9e4bSmacallan 107dbbd9e4bSmacallanstatic void 108dbbd9e4bSmacallanFFBI2CGetBits(I2CBusPtr b, int *clock, int *data) 109dbbd9e4bSmacallan{ 110dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]); 111dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 112dbbd9e4bSmacallan unsigned int val; 113dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 114dbbd9e4bSmacallan unsigned int uctrl; 115dbbd9e4bSmacallan#endif 116dbbd9e4bSmacallan 117dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 118dbbd9e4bSmacallan /* Force a blank of the screen. */ 119dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 120dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 121dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 122dbbd9e4bSmacallan#endif 123dbbd9e4bSmacallan 124dbbd9e4bSmacallan /* Tristate SCL+SDA pins. */ 125dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 126dbbd9e4bSmacallan (FFBDAC_CFG_MPDATA_SCL | FFBDAC_CFG_MPDATA_SDA)); 127dbbd9e4bSmacallan 128dbbd9e4bSmacallan /* Read the sense line to see what the monitor is driving 129dbbd9e4bSmacallan * them at. 130dbbd9e4bSmacallan */ 131dbbd9e4bSmacallan val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE); 132dbbd9e4bSmacallan *clock = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0; 133dbbd9e4bSmacallan *data = (val & FFBDAC_CFG_MPSENSE_SDA) ? 1 : 0; 134dbbd9e4bSmacallan 135dbbd9e4bSmacallan /* Stop tristating the SCL pin. */ 136dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0); 137dbbd9e4bSmacallan 138dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 139dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 140dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 141dbbd9e4bSmacallan#endif 142dbbd9e4bSmacallan} 143dbbd9e4bSmacallan 144dbbd9e4bSmacallanstatic void 145dbbd9e4bSmacallanFFBI2CPutBits(I2CBusPtr b, int clock, int data) 146dbbd9e4bSmacallan{ 147dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]); 148dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 149dbbd9e4bSmacallan unsigned int val; 150dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 151dbbd9e4bSmacallan unsigned int uctrl; 152dbbd9e4bSmacallan#endif 153dbbd9e4bSmacallan 154dbbd9e4bSmacallan val = 0; 155dbbd9e4bSmacallan if (clock) 156dbbd9e4bSmacallan val |= FFBDAC_CFG_MPDATA_SCL; 157dbbd9e4bSmacallan if (data) 158dbbd9e4bSmacallan val |= FFBDAC_CFG_MPDATA_SDA; 159dbbd9e4bSmacallan 160dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 161dbbd9e4bSmacallan /* Force a blank of the screen. */ 162dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 163dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 164dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 165dbbd9e4bSmacallan#endif 166dbbd9e4bSmacallan 167dbbd9e4bSmacallan /* Tristate requested pins. */ 168dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, val); 169dbbd9e4bSmacallan 170dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 171dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 172dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 173dbbd9e4bSmacallan#endif 174dbbd9e4bSmacallan} 175dbbd9e4bSmacallan 176dbbd9e4bSmacallanBool 177dbbd9e4bSmacallanFFBi2cInit(ScrnInfoPtr pScrn) 178dbbd9e4bSmacallan{ 179dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 180dbbd9e4bSmacallan I2CBusPtr I2CPtr; 181dbbd9e4bSmacallan 182dbbd9e4bSmacallan I2CPtr = xf86CreateI2CBusRec(); 183dbbd9e4bSmacallan if (!I2CPtr) 184dbbd9e4bSmacallan return FALSE; 185dbbd9e4bSmacallan 186dbbd9e4bSmacallan pFfb->I2C = I2CPtr; 187dbbd9e4bSmacallan 188dbbd9e4bSmacallan I2CPtr->BusName = "DDC"; 189dbbd9e4bSmacallan I2CPtr->scrnIndex = pScrn->scrnIndex; 190dbbd9e4bSmacallan I2CPtr->I2CPutBits = FFBI2CPutBits; 191dbbd9e4bSmacallan I2CPtr->I2CGetBits = FFBI2CGetBits; 192dbbd9e4bSmacallan I2CPtr->AcknTimeout = 5; 193dbbd9e4bSmacallan 194dbbd9e4bSmacallan if (!xf86I2CBusInit(I2CPtr)) 195dbbd9e4bSmacallan return FALSE; 196dbbd9e4bSmacallan 197dbbd9e4bSmacallan return TRUE; 198dbbd9e4bSmacallan} 199