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