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 25dbbd9e4bSmacallan#ifdef HAVE_CONFIG_H 26dbbd9e4bSmacallan#include "config.h" 27dbbd9e4bSmacallan#endif 28dbbd9e4bSmacallan 29dbbd9e4bSmacallan#include "ffb.h" 30dbbd9e4bSmacallan 31dbbd9e4bSmacallan#include "ffb_dac.h" 32dbbd9e4bSmacallan 33dbbd9e4bSmacallan#include "xf86.h" 34dbbd9e4bSmacallan#include "xf86_OSproc.h" 35dbbd9e4bSmacallan 36dbbd9e4bSmacallan#include "xf86DDC.h" 37dbbd9e4bSmacallan 38dbbd9e4bSmacallan/* XXX This needs a lot more work. Only an attempt at the PAC2 version 39dbbd9e4bSmacallan * XXX is below, and that is untested. The BT498 manual is unclear about 40dbbd9e4bSmacallan * XXX several details and I must figure them out by trial and error. 41dbbd9e4bSmacallan */ 42dbbd9e4bSmacallan 43dbbd9e4bSmacallan/* Wait for the next VSYNC. */ 44dbbd9e4bSmacallanstatic void 45dbbd9e4bSmacallanWaitForVSYNC(ffb_dacPtr dac) 46dbbd9e4bSmacallan{ 47dbbd9e4bSmacallan unsigned int vsap = DACCFG_READ(dac, FFBDAC_CFG_VSAP); 48dbbd9e4bSmacallan unsigned int vcnt; 49dbbd9e4bSmacallan 50dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 51dbbd9e4bSmacallan while (vcnt > vsap) 52dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 53dbbd9e4bSmacallan while (vcnt <= vsap) 54dbbd9e4bSmacallan vcnt = DACCFG_READ(dac, FFBDAC_CFG_TGVC); 55dbbd9e4bSmacallan 56dbbd9e4bSmacallan} 57dbbd9e4bSmacallan 58dbbd9e4bSmacallan/* The manual seems to imply this is needed, but it's really clumsy 59dbbd9e4bSmacallan * so we can test if it really is a requirement with this. 60dbbd9e4bSmacallan */ 61dbbd9e4bSmacallan#define MDATA_NEEDS_BLANK 62dbbd9e4bSmacallan 63dbbd9e4bSmacallan/* DDC1/DDC2 support */ 64dbbd9e4bSmacallanstatic unsigned int 65dbbd9e4bSmacallanFFBDacDdc1Read(ScrnInfoPtr pScrn) 66dbbd9e4bSmacallan{ 67dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 68dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 69dbbd9e4bSmacallan unsigned int val; 70dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 71dbbd9e4bSmacallan unsigned int uctrl; 72dbbd9e4bSmacallan#endif 73dbbd9e4bSmacallan 74dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 75dbbd9e4bSmacallan /* Force a blank of the screen. */ 76dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 77dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 78dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 79dbbd9e4bSmacallan#endif 80dbbd9e4bSmacallan 81dbbd9e4bSmacallan /* Tristate SCL pin. */ 82dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 83dbbd9e4bSmacallan FFBDAC_CFG_MPDATA_SCL); 84dbbd9e4bSmacallan 85dbbd9e4bSmacallan /* Pause until VSYNC is hit. */ 86dbbd9e4bSmacallan WaitForVSYNC(dac); 87dbbd9e4bSmacallan 88dbbd9e4bSmacallan /* Read the sense line to see what the monitor is driving 89dbbd9e4bSmacallan * it at. 90dbbd9e4bSmacallan */ 91dbbd9e4bSmacallan val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE); 92dbbd9e4bSmacallan val = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0; 93dbbd9e4bSmacallan 94dbbd9e4bSmacallan /* Stop tristating the SCL pin. */ 95dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0); 96dbbd9e4bSmacallan 97dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 98dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 99dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 100dbbd9e4bSmacallan#endif 101dbbd9e4bSmacallan 102dbbd9e4bSmacallan /* Return the result and we're done. */ 103dbbd9e4bSmacallan return val; 104dbbd9e4bSmacallan} 105dbbd9e4bSmacallan 106dbbd9e4bSmacallanstatic void 107dbbd9e4bSmacallanFFBI2CGetBits(I2CBusPtr b, int *clock, int *data) 108dbbd9e4bSmacallan{ 109dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]); 110dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 111dbbd9e4bSmacallan unsigned int val; 112dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 113dbbd9e4bSmacallan unsigned int uctrl; 114dbbd9e4bSmacallan#endif 115dbbd9e4bSmacallan 116dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 117dbbd9e4bSmacallan /* Force a blank of the screen. */ 118dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 119dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 120dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 121dbbd9e4bSmacallan#endif 122dbbd9e4bSmacallan 123dbbd9e4bSmacallan /* Tristate SCL+SDA pins. */ 124dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 125dbbd9e4bSmacallan (FFBDAC_CFG_MPDATA_SCL | FFBDAC_CFG_MPDATA_SDA)); 126dbbd9e4bSmacallan 127dbbd9e4bSmacallan /* Read the sense line to see what the monitor is driving 128dbbd9e4bSmacallan * them at. 129dbbd9e4bSmacallan */ 130dbbd9e4bSmacallan val = DACCFG_READ(dac, FFBDAC_CFG_MPSENSE); 131dbbd9e4bSmacallan *clock = (val & FFBDAC_CFG_MPSENSE_SCL) ? 1 : 0; 132dbbd9e4bSmacallan *data = (val & FFBDAC_CFG_MPSENSE_SDA) ? 1 : 0; 133dbbd9e4bSmacallan 134dbbd9e4bSmacallan /* Stop tristating the SCL pin. */ 135dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, 0); 136dbbd9e4bSmacallan 137dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 138dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 139dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 140dbbd9e4bSmacallan#endif 141dbbd9e4bSmacallan} 142dbbd9e4bSmacallan 143dbbd9e4bSmacallanstatic void 144dbbd9e4bSmacallanFFBI2CPutBits(I2CBusPtr b, int clock, int data) 145dbbd9e4bSmacallan{ 146dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(xf86Screens[b->scrnIndex]); 147dbbd9e4bSmacallan ffb_dacPtr dac = pFfb->dac; 148dbbd9e4bSmacallan unsigned int val; 149dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 150dbbd9e4bSmacallan unsigned int uctrl; 151dbbd9e4bSmacallan#endif 152dbbd9e4bSmacallan 153dbbd9e4bSmacallan val = 0; 154dbbd9e4bSmacallan if (clock) 155dbbd9e4bSmacallan val |= FFBDAC_CFG_MPDATA_SCL; 156dbbd9e4bSmacallan if (data) 157dbbd9e4bSmacallan val |= FFBDAC_CFG_MPDATA_SDA; 158dbbd9e4bSmacallan 159dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 160dbbd9e4bSmacallan /* Force a blank of the screen. */ 161dbbd9e4bSmacallan uctrl = DACCFG_READ(dac, FFBDAC_CFG_UCTRL); 162dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, 163dbbd9e4bSmacallan (uctrl | FFBDAC_UCTRL_ABLANK)); 164dbbd9e4bSmacallan#endif 165dbbd9e4bSmacallan 166dbbd9e4bSmacallan /* Tristate requested pins. */ 167dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_MPDATA, val); 168dbbd9e4bSmacallan 169dbbd9e4bSmacallan#ifdef MDATA_NEEDS_BLANK 170dbbd9e4bSmacallan /* Restore UCTRL to unblank the screen. */ 171dbbd9e4bSmacallan DACCFG_WRITE(dac, FFBDAC_CFG_UCTRL, uctrl); 172dbbd9e4bSmacallan#endif 173dbbd9e4bSmacallan} 174dbbd9e4bSmacallan 175dbbd9e4bSmacallanBool 176dbbd9e4bSmacallanFFBi2cInit(ScrnInfoPtr pScrn) 177dbbd9e4bSmacallan{ 178dbbd9e4bSmacallan FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); 179dbbd9e4bSmacallan I2CBusPtr I2CPtr; 180dbbd9e4bSmacallan 181dbbd9e4bSmacallan I2CPtr = xf86CreateI2CBusRec(); 182dbbd9e4bSmacallan if (!I2CPtr) 183dbbd9e4bSmacallan return FALSE; 184dbbd9e4bSmacallan 185dbbd9e4bSmacallan pFfb->I2C = I2CPtr; 186dbbd9e4bSmacallan 187dbbd9e4bSmacallan I2CPtr->BusName = "DDC"; 188dbbd9e4bSmacallan I2CPtr->scrnIndex = pScrn->scrnIndex; 189dbbd9e4bSmacallan I2CPtr->I2CPutBits = FFBI2CPutBits; 190dbbd9e4bSmacallan I2CPtr->I2CGetBits = FFBI2CGetBits; 191dbbd9e4bSmacallan I2CPtr->AcknTimeout = 5; 192dbbd9e4bSmacallan 193dbbd9e4bSmacallan if (!xf86I2CBusInit(I2CPtr)) 194dbbd9e4bSmacallan return FALSE; 195dbbd9e4bSmacallan 196dbbd9e4bSmacallan return TRUE; 197dbbd9e4bSmacallan} 198