1209ff23fSmrg#ifdef HAVE_CONFIG_H
2209ff23fSmrg#include "config.h"
3209ff23fSmrg#endif
4209ff23fSmrg
5209ff23fSmrg#include <math.h>
6209ff23fSmrg
7209ff23fSmrg#include "radeon.h"
8209ff23fSmrg#include "radeon_reg.h"
9209ff23fSmrg#include "radeon_macros.h"
10209ff23fSmrg#include "radeon_probe.h"
11209ff23fSmrg#include <X11/extensions/Xv.h>
12209ff23fSmrg#include "radeon_video.h"
13209ff23fSmrg#include "atipciids.h"
14209ff23fSmrg
15209ff23fSmrg#include "xf86.h"
16209ff23fSmrg
17209ff23fSmrg/* i2c stuff */
18209ff23fSmrg#include "xf86i2c.h"
19209ff23fSmrg#include "fi1236.h"
20209ff23fSmrg#include "msp3430.h"
21209ff23fSmrg#include "tda9885.h"
22209ff23fSmrg#include "uda1380.h"
23209ff23fSmrg#include "i2c_def.h"
24209ff23fSmrg
25209ff23fSmrg
26209ff23fSmrgstatic void RADEON_TDA9885_Init(RADEONPortPrivPtr pPriv);
27209ff23fSmrg
28209ff23fSmrg/* Wait for 10ms at the most for the I2C_GO register to drop. */
29209ff23fSmrg#define I2C_WAIT_FOR_GO() { \
30209ff23fSmrg	int i2ctries = 0; \
31209ff23fSmrg	RADEONWaitForIdleMMIO(pScrn); \
32209ff23fSmrg	write_mem_barrier(); \
33209ff23fSmrg	while (i2ctries < 10) { \
34209ff23fSmrg		reg = INREG8(RADEON_I2C_CNTL_0+1); \
35209ff23fSmrg		if (!(reg & (RADEON_I2C_GO >> 8))) \
36209ff23fSmrg			break; \
37209ff23fSmrg		if (reg & (RADEON_I2C_ABORT >> 8)) \
38209ff23fSmrg			break; \
39209ff23fSmrg		usleep(1000); \
40209ff23fSmrg		i2ctries++; \
41209ff23fSmrg	} \
42209ff23fSmrg}
43209ff23fSmrg
44209ff23fSmrg/* Wait, and dump the status in the 'status' register.  If we time out or
45209ff23fSmrg * receive an abort signal, halt/restart the I2C bus and leave _ABORT in the
46209ff23fSmrg * status register. */
47209ff23fSmrg#define I2C_WAIT_WITH_STATUS() { \
48209ff23fSmrg	I2C_WAIT_FOR_GO() \
49209ff23fSmrg	if (reg & ((RADEON_I2C_ABORT >> 8) | (RADEON_I2C_GO >> 8))) { \
50209ff23fSmrg		RADEON_I2C_Halt(pScrn); \
51209ff23fSmrg		status = RADEON_I2C_ABORT; \
52209ff23fSmrg	} \
53209ff23fSmrg	else \
54209ff23fSmrg		status = RADEON_I2C_WaitForAck(pScrn, pPriv); \
55209ff23fSmrg}
56209ff23fSmrg
57209ff23fSmrg/****************************************************************************
58209ff23fSmrg *  I2C_WaitForAck (void)                                                   *
59209ff23fSmrg *                                                                          *
60209ff23fSmrg *  Function: polls the I2C status bits, waiting for an acknowledge or      *
61209ff23fSmrg *            an error condition.                                           *
62209ff23fSmrg *    Inputs: NONE                                                          *
63209ff23fSmrg *   Outputs: I2C_DONE - the I2C transfer was completed                     *
64209ff23fSmrg *            I2C_NACK - an NACK was received from the slave                *
65209ff23fSmrg *            I2C_HALT - a timeout condition has occured                    *
66209ff23fSmrg ****************************************************************************/
67209ff23fSmrgstatic uint8_t RADEON_I2C_WaitForAck (ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
68209ff23fSmrg{
69209ff23fSmrg    uint8_t retval = 0;
70209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
71209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
72209ff23fSmrg    long counter = 0;
73209ff23fSmrg
74209ff23fSmrg    usleep(1000);
75209ff23fSmrg    while(1)
76209ff23fSmrg    {
77209ff23fSmrg        RADEONWaitForIdleMMIO(pScrn);
78209ff23fSmrg        retval = INREG8(RADEON_I2C_CNTL_0);
79209ff23fSmrg        if (retval & RADEON_I2C_HALT)
80209ff23fSmrg        {
81209ff23fSmrg            return (RADEON_I2C_HALT);
82209ff23fSmrg        }
83209ff23fSmrg        if (retval & RADEON_I2C_NACK)
84209ff23fSmrg        {
85209ff23fSmrg            return (RADEON_I2C_NACK);
86209ff23fSmrg        }
87209ff23fSmrg        if(retval & RADEON_I2C_DONE)
88209ff23fSmrg        {
89209ff23fSmrg            return RADEON_I2C_DONE;
90209ff23fSmrg        }
91209ff23fSmrg        counter++;
92209ff23fSmrg	/* 50ms ought to be long enough. */
93209ff23fSmrg        if(counter > 50)
94209ff23fSmrg        {
95209ff23fSmrg             xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Timeout condition on Radeon i2c bus\n");
96209ff23fSmrg             return RADEON_I2C_HALT;
97209ff23fSmrg        }
98209ff23fSmrg	usleep(1000);
99209ff23fSmrg    }
100209ff23fSmrg}
101209ff23fSmrg
102209ff23fSmrgstatic void RADEON_I2C_Halt (ScrnInfoPtr pScrn)
103209ff23fSmrg{
104209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
105209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
106209ff23fSmrg    uint8_t    reg;
107209ff23fSmrg
108209ff23fSmrg    /* reset status flags */
109209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
110209ff23fSmrg    reg = INREG8 (RADEON_I2C_CNTL_0 + 0) & ~(RADEON_I2C_DONE|RADEON_I2C_NACK|RADEON_I2C_HALT);
111209ff23fSmrg    OUTREG8 (RADEON_I2C_CNTL_0 + 0, reg);
112209ff23fSmrg
113209ff23fSmrg    /* issue ABORT call */
114209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
115209ff23fSmrg    reg = INREG8 (RADEON_I2C_CNTL_0 + 1) & 0xE7;
116209ff23fSmrg    OUTREG8 (RADEON_I2C_CNTL_0 + 1, (reg |((RADEON_I2C_GO|RADEON_I2C_ABORT) >> 8)));
117209ff23fSmrg
118209ff23fSmrg    /* wait for GO bit to go low */
119209ff23fSmrg    I2C_WAIT_FOR_GO();
120209ff23fSmrg}
121209ff23fSmrg
122209ff23fSmrg
123209ff23fSmrgstatic Bool RADEONI2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite,
124209ff23fSmrg                            I2CByte *ReadBuffer, int nRead)
125209ff23fSmrg{
126209ff23fSmrg    int loop, status;
127209ff23fSmrg    uint32_t i2c_cntl_0, i2c_cntl_1;
128209ff23fSmrg    uint8_t reg;
129209ff23fSmrg    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)(d->pI2CBus->DriverPrivate.ptr);
130209ff23fSmrg    ScrnInfoPtr pScrn = xf86Screens[d->pI2CBus->scrnIndex];
131209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
132209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
133209ff23fSmrg
134209ff23fSmrg    status=RADEON_I2C_DONE;
135209ff23fSmrg
136209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
137209ff23fSmrg    if(nWrite>0){
138209ff23fSmrg/*       RADEONWaitForFifo(pScrn, 4+nWrite); */
139209ff23fSmrg
140209ff23fSmrg       /* Clear the status bits of the I2C Controller */
141209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST);
142209ff23fSmrg
143209ff23fSmrg       /* Write the address into the buffer first */
144209ff23fSmrg       OUTREG(RADEON_I2C_DATA, (uint32_t) (d->SlaveAddr) & ~(1));
145209ff23fSmrg
146209ff23fSmrg       /* Write Value into the buffer */
147209ff23fSmrg       for (loop = 0; loop < nWrite; loop++)
148209ff23fSmrg       {
149209ff23fSmrg          OUTREG8(RADEON_I2C_DATA, WriteBuffer[loop]);
150209ff23fSmrg       }
151209ff23fSmrg
152209ff23fSmrg       i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | RADEON_I2C_EN | RADEON_I2C_SEL |
153209ff23fSmrg                        nWrite | 0x100;
154209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1);
155209ff23fSmrg
156209ff23fSmrg       i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) |
157209ff23fSmrg                        RADEON_I2C_GO | RADEON_I2C_START | ((nRead >0)?0:RADEON_I2C_STOP) | RADEON_I2C_DRIVE_EN;
158209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0);
159209ff23fSmrg
160209ff23fSmrg       I2C_WAIT_WITH_STATUS();
161209ff23fSmrg
162209ff23fSmrg       if(status!=RADEON_I2C_DONE){
163209ff23fSmrg          RADEON_I2C_Halt(pScrn);
164209ff23fSmrg          return FALSE;
165209ff23fSmrg          }
166209ff23fSmrg    }
167209ff23fSmrg
168209ff23fSmrg
169209ff23fSmrg    if(nRead > 0) {
170209ff23fSmrg       RADEONWaitForFifo(pScrn, 4+nRead);
171209ff23fSmrg
172209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST);
173209ff23fSmrg
174209ff23fSmrg       /* Write the address into the buffer first */
175209ff23fSmrg       OUTREG(RADEON_I2C_DATA, (uint32_t) (d->SlaveAddr) | (1));
176209ff23fSmrg
177209ff23fSmrg       i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | RADEON_I2C_EN | RADEON_I2C_SEL |
178209ff23fSmrg                        nRead | 0x100;
179209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1);
180209ff23fSmrg
181209ff23fSmrg       i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) |
182209ff23fSmrg                        RADEON_I2C_GO | RADEON_I2C_START | RADEON_I2C_STOP | RADEON_I2C_DRIVE_EN | RADEON_I2C_RECEIVE;
183209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0);
184209ff23fSmrg
185209ff23fSmrg       I2C_WAIT_WITH_STATUS();
186209ff23fSmrg
187209ff23fSmrg       /* Write Value into the buffer */
188209ff23fSmrg       for (loop = 0; loop < nRead; loop++)
189209ff23fSmrg       {
190209ff23fSmrg          RADEONWaitForFifo(pScrn, 1);
191209ff23fSmrg          if((status == RADEON_I2C_HALT) || (status == RADEON_I2C_NACK))
192209ff23fSmrg          {
193209ff23fSmrg          ReadBuffer[loop]=0xff;
194209ff23fSmrg          } else {
195209ff23fSmrg          RADEONWaitForIdleMMIO(pScrn);
196209ff23fSmrg          ReadBuffer[loop]=INREG8(RADEON_I2C_DATA) & 0xff;
197209ff23fSmrg          }
198209ff23fSmrg       }
199209ff23fSmrg    }
200209ff23fSmrg
201209ff23fSmrg    if(status!=RADEON_I2C_DONE){
202209ff23fSmrg       RADEON_I2C_Halt(pScrn);
203209ff23fSmrg       return FALSE;
204209ff23fSmrg       }
205209ff23fSmrg    return TRUE;
206209ff23fSmrg}
207209ff23fSmrg
208209ff23fSmrgstatic Bool R200_I2CWriteRead(I2CDevPtr d, I2CByte *WriteBuffer, int nWrite,
209209ff23fSmrg                            I2CByte *ReadBuffer, int nRead)
210209ff23fSmrg{
211209ff23fSmrg    int loop, status;
212209ff23fSmrg    uint32_t i2c_cntl_0, i2c_cntl_1;
213209ff23fSmrg    uint8_t reg;
214209ff23fSmrg    RADEONPortPrivPtr pPriv = (RADEONPortPrivPtr)(d->pI2CBus->DriverPrivate.ptr);
215209ff23fSmrg    ScrnInfoPtr pScrn = xf86Screens[d->pI2CBus->scrnIndex];
216209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
217209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
218209ff23fSmrg
219209ff23fSmrg    status=RADEON_I2C_DONE;
220209ff23fSmrg
221209ff23fSmrg    RADEONWaitForIdleMMIO(pScrn);
222209ff23fSmrg    if(nWrite>0){
223209ff23fSmrg/*       RADEONWaitForFifo(pScrn, 4+nWrite); */
224209ff23fSmrg
225209ff23fSmrg       /* Clear the status bits of the I2C Controller */
226209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST);
227209ff23fSmrg
228209ff23fSmrg       /* Write the address into the buffer first */
229209ff23fSmrg       OUTREG(RADEON_I2C_DATA, (uint32_t) (d->SlaveAddr) & ~(1));
230209ff23fSmrg
231209ff23fSmrg       /* Write Value into the buffer */
232209ff23fSmrg       for (loop = 0; loop < nWrite; loop++)
233209ff23fSmrg       {
234209ff23fSmrg          OUTREG8(RADEON_I2C_DATA, WriteBuffer[loop]);
235209ff23fSmrg       }
236209ff23fSmrg
237209ff23fSmrg       i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | RADEON_I2C_EN | RADEON_I2C_SEL |
238209ff23fSmrg                        nWrite | 0x010;
239209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1);
240209ff23fSmrg
241209ff23fSmrg       i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) |
242209ff23fSmrg                        RADEON_I2C_GO | RADEON_I2C_START | ((nRead >0)?0:RADEON_I2C_STOP) | RADEON_I2C_DRIVE_EN;
243209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0);
244209ff23fSmrg
245209ff23fSmrg       I2C_WAIT_WITH_STATUS();
246209ff23fSmrg
247209ff23fSmrg       if(status!=RADEON_I2C_DONE){
248209ff23fSmrg          RADEON_I2C_Halt(pScrn);
249209ff23fSmrg          return FALSE;
250209ff23fSmrg          }
251209ff23fSmrg    }
252209ff23fSmrg
253209ff23fSmrg
254209ff23fSmrg    if(nRead > 0) {
255209ff23fSmrg       RADEONWaitForFifo(pScrn, 4+nRead);
256209ff23fSmrg
257209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST);
258209ff23fSmrg
259209ff23fSmrg       /* Write the address into the buffer first */
260209ff23fSmrg       OUTREG(RADEON_I2C_DATA, (uint32_t) (d->SlaveAddr) | (1));
261209ff23fSmrg
262209ff23fSmrg       i2c_cntl_1 = (pPriv->radeon_i2c_timing << 24) | RADEON_I2C_EN | RADEON_I2C_SEL |
263209ff23fSmrg                        nRead | 0x010;
264209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_1, i2c_cntl_1);
265209ff23fSmrg
266209ff23fSmrg       i2c_cntl_0 = (pPriv->radeon_N << 24) | (pPriv->radeon_M << 16) |
267209ff23fSmrg                        RADEON_I2C_GO | RADEON_I2C_START | RADEON_I2C_STOP | RADEON_I2C_DRIVE_EN | RADEON_I2C_RECEIVE;
268209ff23fSmrg       OUTREG(RADEON_I2C_CNTL_0, i2c_cntl_0);
269209ff23fSmrg
270209ff23fSmrg       I2C_WAIT_WITH_STATUS();
271209ff23fSmrg
272209ff23fSmrg       RADEONWaitForIdleMMIO(pScrn);
273209ff23fSmrg       /* Write Value into the buffer */
274209ff23fSmrg       for (loop = 0; loop < nRead; loop++)
275209ff23fSmrg       {
276209ff23fSmrg          if((status == RADEON_I2C_HALT) || (status == RADEON_I2C_NACK))
277209ff23fSmrg          {
278209ff23fSmrg          ReadBuffer[loop]=0xff;
279209ff23fSmrg          } else {
280209ff23fSmrg          ReadBuffer[loop]=INREG8(RADEON_I2C_DATA) & 0xff;
281209ff23fSmrg          }
282209ff23fSmrg       }
283209ff23fSmrg    }
284209ff23fSmrg
285209ff23fSmrg    if(status!=RADEON_I2C_DONE){
286209ff23fSmrg       RADEON_I2C_Halt(pScrn);
287209ff23fSmrg       return FALSE;
288209ff23fSmrg       }
289209ff23fSmrg    return TRUE;
290209ff23fSmrg}
291209ff23fSmrg
292209ff23fSmrg#if 0
293209ff23fSmrgstatic Bool RADEONProbeAddress(I2CBusPtr b, I2CSlaveAddr addr)
294209ff23fSmrg{
295209ff23fSmrg     I2CByte a;
296209ff23fSmrg     I2CDevRec d;
297209ff23fSmrg
298209ff23fSmrg     d.DevName = "Probing";
299209ff23fSmrg     d.SlaveAddr = addr;
300209ff23fSmrg     d.pI2CBus = b;
301209ff23fSmrg     d.NextDev = NULL;
302209ff23fSmrg
303209ff23fSmrg     return I2C_WriteRead(&d, NULL, 0, &a, 1);
304209ff23fSmrg}
305209ff23fSmrg#endif
306209ff23fSmrg
307209ff23fSmrg#define I2C_CLOCK_FREQ     (60000.0)
308209ff23fSmrg
309209ff23fSmrg
310209ff23fSmrgconst struct
311209ff23fSmrg{
312209ff23fSmrg   char *name;
313209ff23fSmrg   int type;
314209ff23fSmrg} RADEON_tuners[32] =
315209ff23fSmrg    {
316209ff23fSmrg        /* name ,index to tuner_parms table */
317209ff23fSmrg        {"NO TUNER"            , -1},
318209ff23fSmrg        {"Philips FI1236 (or compatible)"               , TUNER_TYPE_FI1236},
319209ff23fSmrg        {"Philips FI1236 (or compatible)"               , TUNER_TYPE_FI1236},
320209ff23fSmrg        {"Philips FI1216 (or compatible)"               , TUNER_TYPE_FI1216},
321209ff23fSmrg        {"Philips FI1246 (or compatible)"               , TUNER_TYPE_FI1246},
322209ff23fSmrg        {"Philips FI1216MF (or compatible)"             , TUNER_TYPE_FI1216},
323209ff23fSmrg        {"Philips FI1236 (or compatible)"               , TUNER_TYPE_FI1236},
324209ff23fSmrg        {"Philips FI1256 (or compatible)"               , TUNER_TYPE_FI1256},
325209ff23fSmrg        {"Philips FI1236 (or compatible)"               , TUNER_TYPE_FI1236},
326209ff23fSmrg        {"Philips FI1216 (or compatible)"               , TUNER_TYPE_FI1216},
327209ff23fSmrg        {"Philips FI1246 (or compatible)"               , TUNER_TYPE_FI1246},
328209ff23fSmrg        {"Philips FI1216MF (or compatible)"             , TUNER_TYPE_FI1216},
329209ff23fSmrg        {"Philips FI1236 (or compatible)"               , TUNER_TYPE_FI1236},
330209ff23fSmrg        {"TEMIC-FN5AL"          , TUNER_TYPE_TEMIC_FN5AL},
331209ff23fSmrg        {"FQ1216ME/P"           , TUNER_TYPE_FI1216},
332209ff23fSmrg        {"FI1236W"              , TUNER_TYPE_FI1236W},
333209ff23fSmrg	{"Philips FI1216ME (or compatible)"             , TUNER_TYPE_FM1216ME},
334209ff23fSmrg        /*{"Alps TSCxx"           , -1},*/
335209ff23fSmrg	{"Philips FM1236/F"     , TUNER_TYPE_FI1236W},
336209ff23fSmrg	{"Philips FI1216ME (or compatible)"             , TUNER_TYPE_FM1216ME},
337209ff23fSmrg        {"UNKNOWN-19"           , -1},
338209ff23fSmrg        {"UNKNOWN-20"           , -1},
339209ff23fSmrg        {"UNKNOWN-21"           , -1},
340209ff23fSmrg        {"UNKNOWN-22"           , -1},
341209ff23fSmrg        {"UNKNOWN-23"           , -1},
342209ff23fSmrg        {"UNKNOWN-24"           , -1},
343209ff23fSmrg        {"UNKNOWN-25"           , -1},
344209ff23fSmrg        {"UNKNOWN-26"           , -1},
345209ff23fSmrg        {"UNKNOWN-27"           , -1},
346209ff23fSmrg        {"UNKNOWN-28"           , -1},
347209ff23fSmrg        {"Microtuner MT2032"            , TUNER_TYPE_MT2032},
348209ff23fSmrg        {"Microtuner MT2032"            , TUNER_TYPE_MT2032},
349209ff23fSmrg        {"UNKNOWN-31"           , -1}
350209ff23fSmrg    };
351209ff23fSmrg
352209ff23fSmrg
353209ff23fSmrgvoid RADEONResetI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
354209ff23fSmrg{
355209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
356209ff23fSmrg    unsigned char *RADEONMMIO = info->MMIO;
357209ff23fSmrg
358209ff23fSmrg    RADEONWaitForFifo(pScrn, 2);
359209ff23fSmrg    OUTREG8(RADEON_I2C_CNTL_1+2, ((RADEON_I2C_SEL | RADEON_I2C_EN)>>16));
360209ff23fSmrg    OUTREG8(RADEON_I2C_CNTL_0+0, (RADEON_I2C_DONE | RADEON_I2C_NACK | RADEON_I2C_HALT | RADEON_I2C_SOFT_RST | RADEON_I2C_DRIVE_EN | RADEON_I2C_DRIVE_SEL));
361209ff23fSmrg}
362209ff23fSmrg
363209ff23fSmrgvoid RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv)
364209ff23fSmrg{
365209ff23fSmrg    double nm;
366209ff23fSmrg    RADEONInfoPtr info = RADEONPTR(pScrn);
367209ff23fSmrg    RADEONPLLPtr  pll = &(info->pll);
368209ff23fSmrg
369209ff23fSmrg    pPriv->i2c = NULL;
370209ff23fSmrg    pPriv->fi1236 = NULL;
371209ff23fSmrg    pPriv->msp3430 = NULL;
372209ff23fSmrg    pPriv->tda9885 = NULL;
373209ff23fSmrg	 pPriv->uda1380 = NULL;
374209ff23fSmrg    #if 0 /* put back on when saa7114 support is present */
375209ff23fSmrg    pPriv->saa7114 = NULL;
376209ff23fSmrg    #endif
377209ff23fSmrg
378209ff23fSmrg    /* Blacklist chipsets that lockup - these are usually older mobility chips */
379209ff23fSmrg
380209ff23fSmrg    switch(info->Chipset){
381209ff23fSmrg    	case PCI_CHIP_RADEON_LY:
382209ff23fSmrg	case PCI_CHIP_RADEON_LZ:
383209ff23fSmrg	     xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M6, disabling multimedia i2c\n");
384209ff23fSmrg	     return;
385209ff23fSmrg	case PCI_CHIP_RADEON_LW:
386209ff23fSmrg	     xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility M7, disabling multimedia i2c\n");
387209ff23fSmrg 	     return;
388209ff23fSmrg	/*case PCI_CHIP_RV250_If:
389209ff23fSmrg	     xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon 9000 - skipping multimedia i2c initialization code.\n");
390209ff23fSmrg	     return;*/
391209ff23fSmrg	case PCI_CHIP_RV370_5460:
392209ff23fSmrg	     xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Detected Radeon Mobility X300, disabling multimedia i2c\n");
393209ff23fSmrg	     return;
394209ff23fSmrg	}
395209ff23fSmrg
396209ff23fSmrg    /* no multimedia capabilities detected and no information was provided to substitute for it */
397209ff23fSmrg    if(!info->MM_TABLE_valid  &&
398209ff23fSmrg       !(info->tunerType>=0))
399209ff23fSmrg    {
400209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No video input capabilities detected and no information is provided - disabling multimedia i2c\n");
401209ff23fSmrg       return;
402209ff23fSmrg    }
403209ff23fSmrg
404209ff23fSmrg
405209ff23fSmrg    if(pPriv->i2c!=NULL) return;  /* for some reason we are asked to init it again.. Stop ! */
406209ff23fSmrg
407209ff23fSmrg    if(!xf86LoadSubModule(pScrn,"i2c"))
408209ff23fSmrg    {
409209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Unable to initialize i2c bus\n");
410209ff23fSmrg        pPriv->i2c = NULL;
411209ff23fSmrg        return;
412209ff23fSmrg    }
413209ff23fSmrg    pPriv->i2c=CreateI2CBusRec();
414209ff23fSmrg    pPriv->i2c->scrnIndex=pScrn->scrnIndex;
415209ff23fSmrg    pPriv->i2c->BusName="Radeon multimedia bus";
416209ff23fSmrg    pPriv->i2c->DriverPrivate.ptr=(pointer)pPriv;
417209ff23fSmrg    switch(info->ChipFamily){
418209ff23fSmrg    	case CHIP_FAMILY_RV350:
419209ff23fSmrg    	case CHIP_FAMILY_R350:
420209ff23fSmrg    	case CHIP_FAMILY_R300:
421209ff23fSmrg	case CHIP_FAMILY_RV250:
422209ff23fSmrg    	case CHIP_FAMILY_R200:
423209ff23fSmrg		case CHIP_FAMILY_RV200:
424209ff23fSmrg            	pPriv->i2c->I2CWriteRead=R200_I2CWriteRead;
425209ff23fSmrg            	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Using R200 i2c bus access method\n");
426209ff23fSmrg		break;
427209ff23fSmrg	default:
428209ff23fSmrg            	pPriv->i2c->I2CWriteRead=RADEONI2CWriteRead;
429209ff23fSmrg            	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Using Radeon bus access method\n");
430209ff23fSmrg        }
431209ff23fSmrg    if(!I2CBusInit(pPriv->i2c))
432209ff23fSmrg    {
433209ff23fSmrg        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Failed to register i2c bus\n");
434209ff23fSmrg    }
435209ff23fSmrg
436209ff23fSmrg#if 1
437209ff23fSmrg    switch(info->ChipFamily){
438209ff23fSmrg	case CHIP_FAMILY_RV200:
439209ff23fSmrg            nm=(pll->reference_freq * 40000.0)/(1.0*I2C_CLOCK_FREQ);
440209ff23fSmrg	    break;
441209ff23fSmrg    	case CHIP_FAMILY_R300:
442209ff23fSmrg    	case CHIP_FAMILY_R200:
443209ff23fSmrg    	    if(info->MM_TABLE_valid && (RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_MT2032)){
444209ff23fSmrg                nm=(pll->reference_freq * 40000.0)/(4.0*I2C_CLOCK_FREQ);
445209ff23fSmrg	        break;
446209ff23fSmrg                }
447209ff23fSmrg	default:
448209ff23fSmrg            nm=(pll->reference_freq * 10000.0)/(4.0*I2C_CLOCK_FREQ);
449209ff23fSmrg        }
450209ff23fSmrg#else
451209ff23fSmrg    nm=(pll->xclk * 40000.0)/(1.0*I2C_CLOCK_FREQ);
452209ff23fSmrg#endif
453209ff23fSmrg    for(pPriv->radeon_N=1; pPriv->radeon_N<255; pPriv->radeon_N++)
454209ff23fSmrg          if((pPriv->radeon_N * (pPriv->radeon_N-1)) > nm)break;
455209ff23fSmrg    pPriv->radeon_M=pPriv->radeon_N-1;
456209ff23fSmrg    pPriv->radeon_i2c_timing=2*pPriv->radeon_N;
457209ff23fSmrg
458209ff23fSmrg
459209ff23fSmrg#if 0
460209ff23fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ref=%d M=0x%02x N=0x%02x timing=0x%02x\n", pll->reference_freq, pPriv->radeon_M, pPriv->radeon_N, pPriv->radeon_i2c_timing);
461209ff23fSmrg    pPriv->radeon_M=0x32;
462209ff23fSmrg    pPriv->radeon_N=0x33;
463209ff23fSmrg    pPriv->radeon_i2c_timing=2*pPriv->radeon_N;
464209ff23fSmrg#endif
465209ff23fSmrg    RADEONResetI2C(pScrn, pPriv);
466209ff23fSmrg
467209ff23fSmrg#if 0 /* I don't know whether standalone boards are supported with Radeons */
468209ff23fSmrg      /* looks like none of them have AMC connectors anyway */
469209ff23fSmrg    if(!info->MM_TABLE_valid)RADEON_read_eeprom(pPriv);
470209ff23fSmrg#endif
471209ff23fSmrg
472209ff23fSmrg    if(!xf86LoadSubModule(pScrn,"fi1236"))
473209ff23fSmrg    {
474209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize fi1236 driver\n");
475209ff23fSmrg    }
476209ff23fSmrg    else
477209ff23fSmrg    {
478209ff23fSmrg    if(pPriv->fi1236 == NULL)
479209ff23fSmrg    {
480209ff23fSmrg        pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_1);
481209ff23fSmrg    }
482209ff23fSmrg    if(pPriv->fi1236 == NULL)
483209ff23fSmrg    {
484209ff23fSmrg        pPriv->fi1236 = xf86_Detect_FI1236(pPriv->i2c, FI1236_ADDR_2);
485209ff23fSmrg    }
486209ff23fSmrg    }
487209ff23fSmrg    if(pPriv->fi1236 != NULL)
488209ff23fSmrg    {
489209ff23fSmrg         xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected %s device at 0x%02x\n",
490209ff23fSmrg               RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].name,
491209ff23fSmrg               FI1236_ADDR(pPriv->fi1236));
492209ff23fSmrg         if(info->MM_TABLE_valid)xf86_FI1236_set_tuner_type(pPriv->fi1236, RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type);
493209ff23fSmrg                else {
494209ff23fSmrg                   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MM_TABLE not found (standalone board ?), forcing tuner type to NTSC\n");
495209ff23fSmrg                    xf86_FI1236_set_tuner_type(pPriv->fi1236, TUNER_TYPE_FI1236);
496209ff23fSmrg                }
497209ff23fSmrg    }
498209ff23fSmrg
499209ff23fSmrg    if(info->MM_TABLE_valid && (RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_MT2032)){
500209ff23fSmrg    if(!xf86LoadSubModule(pScrn,"tda9885"))
501209ff23fSmrg    {
502209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize tda9885 driver\n");
503209ff23fSmrg    }
504209ff23fSmrg    else
505209ff23fSmrg    {
506209ff23fSmrg    if(pPriv->tda9885 == NULL)
507209ff23fSmrg    {
508209ff23fSmrg        pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_1);
509209ff23fSmrg    }
510209ff23fSmrg    if(pPriv->tda9885 == NULL)
511209ff23fSmrg    {
512209ff23fSmrg        pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_2);
513209ff23fSmrg    }
514209ff23fSmrg    if(pPriv->tda9885 != NULL)
515209ff23fSmrg    {
516209ff23fSmrg        RADEON_TDA9885_Init(pPriv);
517209ff23fSmrg    }
518209ff23fSmrg    }
519209ff23fSmrg    }
520209ff23fSmrg
521209ff23fSmrg	if(info->MM_TABLE_valid && ((RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_FM1216ME)
522209ff23fSmrg							|| (RADEON_tuners[info->MM_TABLE.tuner_type & 0x1f].type==TUNER_TYPE_FI1236W)))
523209ff23fSmrg	{
524209ff23fSmrg		if(!xf86LoadSubModule(pScrn,"tda9885"))
525209ff23fSmrg		{
526209ff23fSmrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize tda9885 driver\n");
527209ff23fSmrg		}
528209ff23fSmrg		else
529209ff23fSmrg		{
530209ff23fSmrg			if(pPriv->tda9885 == NULL)
531209ff23fSmrg			{
532209ff23fSmrg				pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_1);
533209ff23fSmrg			}
534209ff23fSmrg			if(pPriv->tda9885 == NULL)
535209ff23fSmrg			{
536209ff23fSmrg				pPriv->tda9885 = xf86_Detect_tda9885(pPriv->i2c, TDA9885_ADDR_2);
537209ff23fSmrg			}
538209ff23fSmrg			if(pPriv->tda9885 != NULL)
539209ff23fSmrg			{
540209ff23fSmrg				RADEON_TDA9885_Init(pPriv);
541209ff23fSmrg				pPriv->fi1236->afc_source = (void*)pPriv->tda9885;
542209ff23fSmrg			}
543209ff23fSmrg		}
544209ff23fSmrg	}
545209ff23fSmrg
546209ff23fSmrg	if(!xf86LoadSubModule(pScrn,"uda1380"))
547209ff23fSmrg	{
548209ff23fSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize uda1380 driver\n");
549209ff23fSmrg	}
550209ff23fSmrg	else
551209ff23fSmrg	{
552209ff23fSmrg		if(pPriv->uda1380 == NULL)
553209ff23fSmrg		{
554209ff23fSmrg			pPriv->uda1380 = xf86_Detect_uda1380(pPriv->i2c, UDA1380_ADDR_1);
555209ff23fSmrg		}
556209ff23fSmrg		if(pPriv->uda1380 == NULL)
557209ff23fSmrg		{
558209ff23fSmrg			pPriv->uda1380 = xf86_Detect_uda1380(pPriv->i2c, UDA1380_ADDR_2);
559209ff23fSmrg		}
560209ff23fSmrg		if(pPriv->uda1380 != NULL)
561209ff23fSmrg		{
562209ff23fSmrg			xf86_uda1380_init(pPriv->uda1380);
563209ff23fSmrg		}
564209ff23fSmrg	}
565209ff23fSmrg
566209ff23fSmrg
567209ff23fSmrg    if(!xf86LoadSubModule(pScrn,"msp3430"))
568209ff23fSmrg    {
569209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize msp3430 driver\n");
570209ff23fSmrg    }
571209ff23fSmrg    else
572209ff23fSmrg    {
573209ff23fSmrg    if(pPriv->msp3430 == NULL)
574209ff23fSmrg    {
575209ff23fSmrg       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_1);
576209ff23fSmrg    }
577209ff23fSmrg    if(pPriv->msp3430 == NULL)
578209ff23fSmrg    {
579209ff23fSmrg       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_2);
580209ff23fSmrg    }
581209ff23fSmrg#if 0 /* this would confuse bt829 with msp3430 */
582209ff23fSmrg    if(pPriv->msp3430 == NULL)
583209ff23fSmrg    {
584209ff23fSmrg       pPriv->msp3430 = xf86_DetectMSP3430(pPriv->i2c, MSP3430_ADDR_3);
585209ff23fSmrg    }
586209ff23fSmrg#endif
587209ff23fSmrg    }
588209ff23fSmrg    if(pPriv->msp3430 != NULL)
589209ff23fSmrg    {
590209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected MSP3430 at 0x%02x\n",
591209ff23fSmrg                 MSP3430_ADDR(pPriv->msp3430));
592209ff23fSmrg       pPriv->msp3430->standard = MSP3430_NTSC;
593209ff23fSmrg       pPriv->msp3430->connector = MSP3430_CONNECTOR_1;
594209ff23fSmrg       xf86_ResetMSP3430(pPriv->msp3430);
595209ff23fSmrg       xf86_InitMSP3430(pPriv->msp3430);
596209ff23fSmrg       xf86_MSP3430SetVolume(pPriv->msp3430, pPriv->mute ? MSP3430_FAST_MUTE : MSP3430_VOLUME(pPriv->volume));
597209ff23fSmrg    }
598209ff23fSmrg
599209ff23fSmrg#if 0 /* put this back when saa7114 driver is ready */
600209ff23fSmrg    if(!xf86LoadSubModule(pScrn,"saa7114"))
601209ff23fSmrg    {
602209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to initialize saa7114 driver\n");
603209ff23fSmrg    }
604209ff23fSmrg    else
605209ff23fSmrg    {
606209ff23fSmrg    if(pPriv->saa7114 == NULL)
607209ff23fSmrg    {
608209ff23fSmrg       pPriv->saa7114 = xf86_DetectSAA7114(pPriv->i2c, SAA7114_ADDR_1);
609209ff23fSmrg    }
610209ff23fSmrg    if(pPriv->saa7114 == NULL)
611209ff23fSmrg    {
612209ff23fSmrg       pPriv->saa7114 = xf86_DetectSAA7114(pPriv->i2c, SAA7114_ADDR_2);
613209ff23fSmrg    }
614209ff23fSmrg    }
615209ff23fSmrg    if(pPriv->saa7114 != NULL)
616209ff23fSmrg    {
617209ff23fSmrg       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected SAA7114 at 0x%02x\n",
618209ff23fSmrg                 pPriv->saa7114->d.SlaveAddr);
619209ff23fSmrg       xf86_InitSAA7114(pPriv->saa7114);
620209ff23fSmrg    }
621209ff23fSmrg#endif
622209ff23fSmrg
623209ff23fSmrg}
624209ff23fSmrg
625209ff23fSmrgstatic void RADEON_TDA9885_Init(RADEONPortPrivPtr pPriv)
626209ff23fSmrg{
627209ff23fSmrgTDA9885Ptr t=pPriv->tda9885;
628209ff23fSmrgt->sound_trap=0;
629209ff23fSmrgt->auto_mute_fm=1; /* ? */
630209ff23fSmrgt->carrier_mode=0; /* ??? */
631209ff23fSmrgt->modulation=2; /* negative FM */
632209ff23fSmrgt->forced_mute_audio=0;
633209ff23fSmrgt->port1=1;
634209ff23fSmrgt->port2=1;
635209ff23fSmrgt->top_adjustment=0x10;
636209ff23fSmrgt->deemphasis=1;
637209ff23fSmrgt->audio_gain=0;
638209ff23fSmrgt->minimum_gain=0;
639209ff23fSmrgt->gating=0;
640209ff23fSmrgt->vif_agc=1; /* set to 1 ? - depends on design */
641209ff23fSmrgt->gating=0;
642209ff23fSmrg}
643