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