Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
/*
2
 * Copyright 2007, 2008  Egbert Eich   
3
 * Copyright 2007, 2008  Luc Verhaegen 
4
 * Copyright 2007, 2008  Matthias Hopf 
5
 * Copyright 2007, 2008  Advanced Micro Devices, Inc.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a
8
 * copy of this software and associated documentation files (the "Software"),
9
 * to deal in the Software without restriction, including without limitation
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
 * and/or sell copies of the Software, and to permit persons to whom the
12
 * Software is furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 * OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
#include "xf86.h"
30
#if HAVE_XF86_ANSIC_H
31
# include "xf86_ansic.h"
32
#else
33
# include 
34
# include 
35
#endif
36
 
37
#include "rhd.h"
38
#include "edid.h"
39
#include "rhd_i2c.h"
40
#include "xf86DDC.h"
41
 
42
#include "rhd_regs.h"
43
 
44
#ifdef ATOM_BIOS
45
#include "rhd_atombios.h"
46
#endif
47
 
48
#define MAX_I2C_LINES 6
49
 
50
#define RHD_I2C_STATUS_LOOPS 5000
51
 
52
enum rhdDDClines {
53
    rhdDdc1data = 0,
54
    rhdDdc2data = 2,
55
    rhdDdc3data = 4,
56
    rhdDdc4data = 6, /* arbirarily choosen */
57
    rhdVIP_DOUT_scl = 0x41,
58
    rhdDvoData12 = 0x28,
59
    rhdDdc5data = 0x48,
60
    rhdDdc6data = 0x4a,
61
    rhdDdc1clk = 1,
62
    rhdDdc2clk = 3,
63
    rhdDdc3clk = 5,
64
    rhdDdc4clk = 7, /* arbirarily choosen */
65
    rhdVIP_DOUTvipclk = 0x42,
66
    rhdDvoData13 = 0x29,
67
    rhdDdc5clk  = 0x49,
68
    rhdDdc6clk  = 0x4b,
69
    rhdDdcUnknown
70
};
71
 
72
typedef struct _rhdI2CRec
73
{
74
    CARD16 prescale;
75
    union {
76
	CARD8 line;
77
	struct i2cGpio {
78
	    enum rhdDDClines Sda;
79
	    enum rhdDDClines Scl;
80
	    CARD32 SdaReg;
81
	    CARD32 SclReg;
82
	} Gpio;
83
    } u;
84
    int scrnIndex;
85
} rhdI2CRec;
86
 
87
enum _rhdR6xxI2CBits {
88
    /* R6_DC_I2C_TRANSACTION0 */
89
    R6_DC_I2C_RW0   = (0x1 << 0),
90
    R6_DC_I2C_STOP_ON_NACK0         = (0x1 << 8),
91
    R6_DC_I2C_ACK_ON_READ0  = (0x1 << 9),
92
    R6_DC_I2C_START0        = (0x1 << 12),
93
    R6_DC_I2C_STOP0         = (0x1 << 13),
94
    R6_DC_I2C_COUNT0        = (0xff << 16),
95
    /* R6_DC_I2C_TRANSACTION1 */
96
    R6_DC_I2C_RW1   = (0x1 << 0),
97
    R6_DC_I2C_STOP_ON_NACK1         = (0x1 << 8),
98
    R6_DC_I2C_ACK_ON_READ1  = (0x1 << 9),
99
    R6_DC_I2C_START1        = (0x1 << 12),
100
    R6_DC_I2C_STOP1         = (0x1 << 13),
101
    R6_DC_I2C_COUNT1        = (0xff << 16),
102
    /* R6_DC_I2C_DATA */
103
    R6_DC_I2C_DATA_RW       = (0x1 << 0),
104
    R6_DC_I2C_DATA_BIT      = (0xff << 8),
105
    R6_DC_I2C_INDEX         = (0xff << 16),
106
    R6_DC_I2C_INDEX_WRITE   = (0x1 << 31),
107
    /* R6_DC_I2C_CONTROL */
108
    R6_DC_I2C_GO    = (0x1 << 0),
109
    R6_DC_I2C_SOFT_RESET    = (0x1 << 1),
110
    R6_DC_I2C_SEND_RESET    = (0x1 << 2),
111
    R6_DC_I2C_SW_STATUS_RESET       = (0x1 << 3),
112
    R6_DC_I2C_SDVO_EN       = (0x1 << 4),
113
    R6_DC_I2C_SDVO_ADDR_SEL         = (0x1 << 6),
114
    R6_DC_I2C_DDC_SELECT    = (0x7 << 8),
115
    R6_DC_I2C_TRANSACTION_COUNT     = (0x3 << 20),
116
    R6_DC_I2C_SW_DONE_INT   = (0x1 << 0),
117
    R6_DC_I2C_SW_DONE_ACK   = (0x1 << 1),
118
    R6_DC_I2C_SW_DONE_MASK  = (0x1 << 2),
119
    R6_DC_I2C_DDC1_HW_DONE_INT      = (0x1 << 4),
120
    R6_DC_I2C_DDC1_HW_DONE_ACK      = (0x1 << 5),
121
    R6_DC_I2C_DDC1_HW_DONE_MASK     = (0x1 << 6),
122
    R6_DC_I2C_DDC2_HW_DONE_INT      = (0x1 << 8),
123
    R6_DC_I2C_DDC2_HW_DONE_ACK      = (0x1 << 9),
124
    R6_DC_I2C_DDC2_HW_DONE_MASK     = (0x1 << 10),
125
    R6_DC_I2C_DDC3_HW_DONE_INT      = (0x1 << 12),
126
    R6_DC_I2C_DDC3_HW_DONE_ACK      = (0x1 << 13),
127
    R6_DC_I2C_DDC3_HW_DONE_MASK     = (0x1 << 14),
128
    R6_DC_I2C_DDC4_HW_DONE_INT      = (0x1 << 16),
129
    R6_DC_I2C_DDC4_HW_DONE_ACK      = (0x1 << 17),
130
    R6_DC_I2C_DDC4_HW_DONE_MASK     = (0x1 << 18),
131
    /* R6_DC_I2C_SW_STATUS */
132
    R6_DC_I2C_SW_STATUS_BIT         = (0x3 << 0),
133
    R6_DC_I2C_SW_DONE       = (0x1 << 2),
134
    R6_DC_I2C_SW_ABORTED    = (0x1 << 4),
135
    R6_DC_I2C_SW_TIMEOUT    = (0x1 << 5),
136
    R6_DC_I2C_SW_INTERRUPTED        = (0x1 << 6),
137
    R6_DC_I2C_SW_BUFFER_OVERFLOW    = (0x1 << 7),
138
    R6_DC_I2C_SW_STOPPED_ON_NACK    = (0x1 << 8),
139
    R6_DC_I2C_SW_SDVO_NACK  = (0x1 << 10),
140
    R6_DC_I2C_SW_NACK0      = (0x1 << 12),
141
    R6_DC_I2C_SW_NACK1      = (0x1 << 13),
142
    R6_DC_I2C_SW_NACK2      = (0x1 << 14),
143
    R6_DC_I2C_SW_NACK3      = (0x1 << 15),
144
    R6_DC_I2C_SW_REQ        = (0x1 << 18)
145
};
146
 
147
enum _rhdR5xxI2CBits {
148
 /* R5_DC_I2C_STATUS1 */
149
    R5_DC_I2C_DONE	 = (0x1 << 0),
150
    R5_DC_I2C_NACK	 = (0x1 << 1),
151
    R5_DC_I2C_HALT	 = (0x1 << 2),
152
    R5_DC_I2C_GO	 = (0x1 << 3),
153
 /* R5_DC_I2C_RESET */
154
    R5_DC_I2C_SOFT_RESET	 = (0x1 << 0),
155
    R5_DC_I2C_ABORT	 = (0x1 << 8),
156
 /* R5_DC_I2C_CONTROL1 */
157
    R5_DC_I2C_START	 = (0x1 << 0),
158
    R5_DC_I2C_STOP	 = (0x1 << 1),
159
    R5_DC_I2C_RECEIVE	 = (0x1 << 2),
160
    R5_DC_I2C_EN	 = (0x1 << 8),
161
    R5_DC_I2C_PIN_SELECT	 = (0x3 << 16),
162
 /* R5_DC_I2C_CONTROL2 */
163
    R5_DC_I2C_ADDR_COUNT	 = (0x7 << 0),
164
    R5_DC_I2C_DATA_COUNT	 = (0xf << 8),
165
    R5_DC_I2C_PRESCALE_LOWER	 = (0xff << 16),
166
    R5_DC_I2C_PRESCALE_UPPER	 = (0xff << 24),
167
 /* R5_DC_I2C_CONTROL3 */
168
    R5_DC_I2C_DATA_DRIVE_EN	 = (0x1 << 0),
169
    R5_DC_I2C_DATA_DRIVE_SEL	 = (0x1 << 1),
170
    R5_DC_I2C_CLK_DRIVE_EN	 = (0x1 << 7),
171
    R5_DC_I2C_RD_INTRA_BYTE_DELAY	 = (0xff << 8),
172
    R5_DC_I2C_WR_INTRA_BYTE_DELAY	 = (0xff << 16),
173
    R5_DC_I2C_TIME_LIMIT	 = (0xff << 24),
174
 /* R5_DC_I2C_DATA */
175
    R5_DC_I2C_DATA_BIT	 = (0xff << 0),
176
 /* R5_DC_I2C_INTERRUPT_CONTROL */
177
    R5_DC_I2C_INTERRUPT_STATUS	 = (0x1 << 0),
178
    R5_DC_I2C_INTERRUPT_AK	 = (0x1 << 8),
179
    R5_DC_I2C_INTERRUPT_ENABLE	 = (0x1 << 16),
180
 /* R5_DC_I2C_ARBITRATION */
181
    R5_DC_I2C_SW_WANTS_TO_USE_I2C	 = (0x1 << 0),
182
    R5_DC_I2C_SW_CAN_USE_I2C	 = (0x1 << 1),
183
    R5_DC_I2C_SW_DONE_USING_I2C	 = (0x1 << 8),
184
    R5_DC_I2C_HW_NEEDS_I2C	 = (0x1 << 9),
185
    R5_DC_I2C_ABORT_HDCP_I2C	 = (0x1 << 16),
186
    R5_DC_I2C_HW_USING_I2C	 = (0x1 << 17)
187
};
188
 
189
enum _rhdRS69I2CBits {
190
    /* RS69_DC_I2C_TRANSACTION0 */
191
    RS69_DC_I2C_RW0   = (0x1 << 0),
192
    RS69_DC_I2C_STOP_ON_NACK0         = (0x1 << 8),
193
    RS69_DC_I2C_START0        = (0x1 << 12),
194
    RS69_DC_I2C_STOP0         = (0x1 << 13),
195
    /* RS69_DC_I2C_TRANSACTION1 */
196
    RS69_DC_I2C_RW1   = (0x1 << 0),
197
    RS69_DC_I2C_START1        = (0x1 << 12),
198
    RS69_DC_I2C_STOP1         = (0x1 << 13),
199
    /* RS69_DC_I2C_DATA */
200
    RS69_DC_I2C_DATA_RW       = (0x1 << 0),
201
    RS69_DC_I2C_INDEX_WRITE   = (0x1 << 31),
202
    /* RS69_DC_I2C_CONTROL */
203
    RS69_DC_I2C_GO    = (0x1 << 0),
204
    RS69_DC_I2C_TRANSACTION_COUNT     = (0x3 << 20),
205
    RS69_DC_I2C_SW_DONE_ACK   = (0x1 << 1),
206
    /* RS69_DC_I2C_SW_STATUS */
207
    RS69_DC_I2C_SW_DONE       = (0x1 << 2),
208
    RS69_DC_I2C_SW_ABORTED    = (0x1 << 4),
209
    RS69_DC_I2C_SW_TIMEOUT    = (0x1 << 5),
210
    RS69_DC_I2C_SW_INTERRUPTED= (0x1 << 6),
211
    RS69_DC_I2C_SW_BUFFER_OVERFLOW= (0x1 << 7),
212
    RS69_DC_I2C_SW_STOPPED_ON_NACK    = (0x1 << 8),
213
    RS69_DC_I2C_SW_NACK0      = (0x1 << 12),
214
    RS69_DC_I2C_SW_NACK1      = (0x1 << 13)
215
};
216
 
217
/* RV620 */
218
enum rv620I2CBits {
219
    /* GENERIC_I2C_CONTROL */
220
    RV62_DC_I2C_GO    = (0x1 << 0),
221
    RV62_GENERIC_I2C_GO       = (0x1 << 0),
222
    RV62_GENERIC_I2C_SOFT_RESET       = (0x1 << 1),
223
    RV62_GENERIC_I2C_SEND_RESET       = (0x1 << 2),
224
    /* GENERIC_I2C_INTERRUPT_CONTROL */
225
    RV62_GENERIC_I2C_DONE_INT         = (0x1 << 0),
226
    RV62_GENERIC_I2C_DONE_ACK         = (0x1 << 1),
227
    RV62_GENERIC_I2C_DONE_MASK        = (0x1 << 2),
228
    /* GENERIC_I2C_STATUS */
229
    RV62_GENERIC_I2C_STATUS_BIT       = (0xf << 0),
230
    RV62_GENERIC_I2C_DONE     = (0x1 << 4),
231
    RV62_GENERIC_I2C_ABORTED  = (0x1 << 5),
232
    RV62_GENERIC_I2C_TIMEOUT  = (0x1 << 6),
233
    RV62_GENERIC_I2C_STOPPED_ON_NACK  = (0x1 << 9),
234
    RV62_GENERIC_I2C_NACK     = (0x1 << 10),
235
    /* GENERIC_I2C_SPEED */
236
    RV62_GENERIC_I2C_THRESHOLD        = (0x3 << 0),
237
    RV62_GENERIC_I2C_DISABLE_FILTER_DURING_STALL      = (0x1 << 4),
238
    RV62_GENERIC_I2C_PRESCALE         = (0xffff << 16),
239
    /* GENERIC_I2C_SETUP */
240
    RV62_GENERIC_I2C_DATA_DRIVE_EN    = (0x1 << 0),
241
    RV62_GENERIC_I2C_DATA_DRIVE_SEL   = (0x1 << 1),
242
    RV62_GENERIC_I2C_CLK_DRIVE_EN     = (0x1 << 7),
243
    RV62_GENERIC_I2C_INTRA_BYTE_DELAY         = (0xff << 8),
244
    RV62_GENERIC_I2C_TIME_LIMIT       = (0xff << 24),
245
    /* GENERIC_I2C_TRANSACTION */
246
    RV62_GENERIC_I2C_RW       = (0x1 << 0),
247
    RV62_GENERIC_I2C_STOP_ON_NACK     = (0x1 << 8),
248
    RV62_GENERIC_I2C_ACK_ON_READ      = (0x1 << 9),
249
    RV62_GENERIC_I2C_START    = (0x1 << 12),
250
    RV62_GENERIC_I2C_STOP     = (0x1 << 13),
251
    RV62_GENERIC_I2C_COUNT    = (0xf << 16),
252
    /* GENERIC_I2C_DATA */
253
    RV62_GENERIC_I2C_DATA_RW  = (0x1 << 0),
254
    RV62_GENERIC_I2C_DATA_BIT         = (0xff << 8),
255
    RV62_GENERIC_I2C_INDEX    = (0xf << 16),
256
    RV62_GENERIC_I2C_INDEX_WRITE      = (0x1 << 31),
257
    /* GENERIC_I2C_PIN_SELECTION */
258
    RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT = 0,
259
    RV62_GENERIC_I2C_SCL_PIN_SEL      = (0x7f << RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT),
260
    RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT = 8,
261
    RV62_GENERIC_I2C_SDA_PIN_SEL      = (0x7f << RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT)
262
};
263
 
264
/*
265
 *
266
 */
267
static enum rhdDDClines
268
getDDCLineFromGPIO(int scrnIndex, CARD32 gpio, int shift)
269
{
270
    switch (gpio) {
271
    case 0x1f90:
272
	switch (shift) {
273
	    case 0:
274
		return rhdDdc1clk; /* ddc1 clk */
275
	    case 8:
276
		return rhdDdc1data; /* ddc1 data */
277
	}
278
	break;
279
    case 0x1f94: /* ddc2 */
280
	switch (shift) {
281
	    case 0:
282
		return rhdDdc2clk; /* ddc2 clk */
283
	    case 8:
284
		return rhdDdc2data; /* ddc2 data */
285
	}
286
	break;
287
    case 0x1f98: /* ddc3 */
288
	switch (shift) {
289
	    case 0:
290
		return rhdDdc3clk; /* ddc3 clk */
291
	    case 8:
292
		return rhdDdc3data; /* ddc3 data */
293
	}
294
    case 0x1f80: /* ddc4 - on r6xx */
295
	switch (shift) {
296
	    case 0:
297
		return rhdDdc4clk; /* ddc4 clk */
298
	    case 8:
299
		return rhdDdc4data; /* ddc4 data */
300
	}
301
	break;
302
    case 0x1f88: /* ddc5 */
303
	switch (shift) {
304
	    case 0:
305
		return rhdVIP_DOUTvipclk; /* ddc5 clk */
306
	    case 8:
307
		return rhdVIP_DOUT_scl; /* ddc5 data */
308
	}
309
	break;
310
    case 0x1fda: /* ddc6 */
311
	switch (shift) {
312
	    case 0:
313
		return rhdDvoData13; /* ddc6 clk */
314
	    case 1:
315
		return rhdDvoData12; /* ddc6 data */
316
	}
317
	break;
318
    case 0x1fc4:
319
	switch (shift) {
320
	    case 0:
321
		return rhdDdc5clk;
322
	    case 8:
323
		return rhdDdc5data;
324
	}
325
	break;
326
    case 0x1fe8: /* ddc6 */
327
	switch (shift) {
328
	    case 0:
329
		return rhdDdc6clk; /* ddc6 clk */
330
	    case 8:
331
		return rhdDdc6data; /* ddc6 data */
332
	}
333
	break;
334
    }
335
 
336
    xf86DrvMsg(scrnIndex, X_WARNING,
337
	       "%s: Failed to match GPIO 0x%04X.%d with a known DDC line\n",
338
	       __func__, (unsigned int) gpio, shift);
339
    return rhdDdcUnknown;
340
}
341
 
342
/*
343
 *
344
 */
345
static Bool
346
rhdI2CGetDataClkLines(RHDPtr rhdPtr, int line,
347
		      enum rhdDDClines *scl, enum rhdDDClines *sda,
348
		      CARD32 *sda_reg, CARD32 *scl_reg)
349
{
350
#ifdef ATOM_BIOS
351
    AtomBiosResult result;
352
    AtomBiosArgRec data;
353
 
354
    /* scl register */
355
    data.val = line & 0x0f;
356
    result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
357
			     ATOM_GPIO_I2C_CLK_MASK, &data);
358
    if (result != ATOM_SUCCESS)
359
	return FALSE;
360
    *scl_reg = data.val;
361
 
362
    /* scl DDC line */
363
	data.val = line & 0x0f;
364
    result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
365
			     ATOM_GPIO_I2C_CLK_MASK_SHIFT, &data);
366
    if (result != ATOM_SUCCESS)
367
	return FALSE;
368
    *scl = getDDCLineFromGPIO(rhdPtr->scrnIndex, *scl_reg, data.val);
369
 
370
    /* sda register */
371
	    data.val = line & 0x0f;
372
    result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
373
			     ATOM_GPIO_I2C_DATA_MASK, &data);
374
    if (result != ATOM_SUCCESS)
375
	return FALSE;
376
    *sda_reg = data.val;
377
 
378
    /* sda DDC line */
379
		data.val = line & 0x0f;
380
    result = RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
381
			     ATOM_GPIO_I2C_DATA_MASK_SHIFT, &data);
382
    if (result != ATOM_SUCCESS)
383
	return FALSE;
384
    *sda = getDDCLineFromGPIO(rhdPtr->scrnIndex, *sda_reg, data.val);
385
 
386
    if ((*scl == rhdDdcUnknown) || (*sda == rhdDdcUnknown)) {
387
	xf86DrvMsg(rhdPtr->scrnIndex, X_WARNING,
388
		   "%s: failed to map gpio lines for DDC line %d\n",
389
		   __func__, line);
390
	return FALSE;
391
    }
392
 
393
		    return TRUE;
394
#else /* ATOM_BIOS */
395
    return FALSE;
396
#endif
397
}
398
 
399
/* R5xx */
400
static Bool
401
rhd5xxI2CSetupStatus(I2CBusPtr I2CPtr, int line)
402
{
403
    RHDFUNC(I2CPtr);
404
 
405
    line &= 0xf;
406
 
407
 
408
    switch (line) {
409
	case 0:
410
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC1_MASK, 0x0, 0xffff);
411
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC1_A, 0x0, 0xffff);
412
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_EN, 0x0, 0xffff);
413
	    break;
414
	case 1:
415
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC2_MASK, 0x0, 0xffff);
416
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC2_A, 0x0, 0xffff);
417
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_EN, 0x0, 0xffff);
418
	    break;
419
	case 2:
420
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_MASK, 0x0, 0xffff);
421
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_A, 0x0, 0xffff);
422
	    RHDRegMask(I2CPtr, R5_DC_GPIO_DDC3_EN, 0x0, 0xffff);
423
	    break;
424
	default:
425
	    xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
426
		       "%s: Trying to initialize non-existent I2C line: %i\n",
427
		       __func__,line);
428
	    return FALSE;
429
    }
430
    return TRUE;
431
}
432
 
433
static Bool
434
rhd5xxI2CStatus(I2CBusPtr I2CPtr)
435
{
436
    int count = RHD_I2C_STATUS_LOOPS;
437
    CARD32 res;
438
 
439
    RHDFUNC(I2CPtr);
440
 
441
    while (count-- != 0) {
442
	usleep (10);
443
	if (((RHDRegRead(I2CPtr, R5_DC_I2C_STATUS1)) & R5_DC_I2C_GO) != 0)
444
	    continue;
445
	res = RHDRegRead(I2CPtr, R5_DC_I2C_STATUS1);
446
	RHDDebugVerb(I2CPtr->scrnIndex,1,"SW_STATUS: 0x%x %i\n",
447
		     (unsigned int)res,count);
448
	if (res & R5_DC_I2C_DONE)
449
	    return TRUE;
450
	else
451
	    return FALSE;
452
    }
453
    RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_ABORT, 0xff00);
454
    return FALSE;
455
}
456
 
457
Bool
458
rhd5xxWriteReadChunk(I2CDevPtr i2cDevPtr, int line, I2CByte *WriteBuffer,
459
		int nWrite, I2CByte *ReadBuffer, int nRead)
460
{
461
    I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
462
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
463
    rhdI2CPtr I2C = (rhdI2CPtr)(I2CPtr->DriverPrivate.ptr);
464
    int prescale = I2C->prescale;
465
    CARD32 save_I2C_CONTROL1, save_494;
466
    CARD32  tmp32;
467
    Bool ret = TRUE;
468
 
469
    RHDFUNC(i2cDevPtr->pI2CBus);
470
 
471
    RHDRegMask(I2CPtr, 0x28, 0x200, 0x200);
472
    save_I2C_CONTROL1 = RHDRegRead(I2CPtr, R5_DC_I2C_CONTROL1);
473
    save_494 = RHDRegRead(I2CPtr, 0x494);
474
    RHDRegMask(I2CPtr, 0x494, 1, 1);
475
    RHDRegMask(I2CPtr, R5_DC_I2C_ARBITRATION,
476
	       R5_DC_I2C_SW_WANTS_TO_USE_I2C,
477
	       R5_DC_I2C_SW_WANTS_TO_USE_I2C);
478
 
479
    if (!RHDRegRead(I2CPtr, R5_DC_I2C_ARBITRATION) & R5_DC_I2C_SW_CAN_USE_I2C) {
480
	RHDDebug(I2CPtr->scrnIndex, "%s SW cannot use I2C line %i\n",__func__,line);
481
	ret = FALSE;
482
    } else {
483
 
484
	RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE
485
		   | R5_DC_I2C_NACK
486
		   | R5_DC_I2C_HALT, 0xff);
487
	RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xffff);
488
	RHDRegWrite(I2CPtr, R5_DC_I2C_RESET, 0);
489
 
490
	RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
491
		   (line  & 0x0f) << 16 | R5_DC_I2C_EN,
492
		   R5_DC_I2C_PIN_SELECT | R5_DC_I2C_EN);
493
    }
494
 
495
    if (ret && (nWrite || !nRead)) { /* special case for bus probing */
496
	/*
497
	 * chip can't just write the slave address without data.
498
	 * Add a dummy byte.
499
	 */
500
	RHDRegWrite(I2CPtr, R5_DC_I2C_CONTROL2,
501
		    prescale << 16 |
502
		    (nWrite ? nWrite : 1) << 8 | 0x01); /* addr_cnt: 1 */
503
	RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL3,
504
		   0x30 << 24, 0xff << 24); /* time limit 30 */
505
 
506
	RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, slave);
507
 
508
	/* Add dummy byte */
509
	if (!nWrite)
510
	    RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, 0);
511
	else
512
	    while (nWrite--)
513
		RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, *WriteBuffer++);
514
 
515
	RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
516
		   R5_DC_I2C_START | R5_DC_I2C_STOP, 0xff);
517
	RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
518
 
519
	if ((ret = rhd5xxI2CStatus(I2CPtr)))
520
	    RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1,R5_DC_I2C_DONE, 0xff);
521
	else
522
	    ret = FALSE;
523
    }
524
 
525
    if (ret && nRead) {
526
 
527
	RHDRegWrite(I2CPtr, R5_DC_I2C_DATA, slave | 1); /*slave*/
528
	RHDRegWrite(I2CPtr, R5_DC_I2C_CONTROL2,
529
		    prescale << 16 | nRead << 8 | 0x01); /* addr_cnt: 1 */
530
 
531
	RHDRegMask(I2CPtr, R5_DC_I2C_CONTROL1,
532
		   R5_DC_I2C_START | R5_DC_I2C_STOP | R5_DC_I2C_RECEIVE, 0xff);
533
	RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_GO, 0xff);
534
	if ((ret = rhd5xxI2CStatus(I2CPtr))) {
535
	    RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1, R5_DC_I2C_DONE, 0xff);
536
	    while (nRead--) {
537
		*(ReadBuffer++) = (CARD8)RHDRegRead(I2CPtr, R5_DC_I2C_DATA);
538
	    }
539
	} else
540
	    ret = FALSE;
541
    }
542
 
543
    RHDRegMask(I2CPtr, R5_DC_I2C_STATUS1,
544
	       R5_DC_I2C_DONE | R5_DC_I2C_NACK | R5_DC_I2C_HALT, 0xff);
545
    RHDRegMask(I2CPtr, R5_DC_I2C_RESET, R5_DC_I2C_SOFT_RESET, 0xff);
546
    RHDRegWrite(I2CPtr,R5_DC_I2C_RESET, 0);
547
 
548
    RHDRegMask(I2CPtr,R5_DC_I2C_ARBITRATION,
549
	       R5_DC_I2C_SW_DONE_USING_I2C, 0xff00);
550
 
551
    RHDRegWrite(I2CPtr,R5_DC_I2C_CONTROL1, save_I2C_CONTROL1);
552
    RHDRegWrite(I2CPtr,0x494, save_494);
553
    tmp32 = RHDRegRead(I2CPtr,0x28);
554
    RHDRegWrite(I2CPtr,0x28, tmp32 & 0xfffffdff);
555
 
556
    return ret;
557
}
558
 
559
static Bool
560
rhd5xxWriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
561
{
562
    /*
563
     * Since the transaction buffer can only hold
564
     * 15 bytes (+ the slave address) we bail out
565
     * on every transaction that is bigger unless
566
     * it's a read transaction following a write
567
     * transaction sending just one byte.
568
     * In this case we assume, that this byte is
569
     * an offset address. Thus we will restart
570
     * the transaction after 15 bytes sending
571
     * a new offset.
572
     */
573
 
574
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
575
    int  ddc_line;
576
 
577
    RHDFUNC(I2CPtr);
578
 
579
    if (nWrite > 15 || (nRead > 15 && nWrite != 1)) {
580
	xf86DrvMsg(i2cDevPtr->pI2CBus->scrnIndex,X_ERROR,
581
		   "%s: Currently only I2C transfers with "
582
		   "maximally 15bytes are supported\n",
583
		   __func__);
584
	return FALSE;
585
    }
586
 
587
    ddc_line = ((rhdI2CPtr)(I2CPtr->DriverPrivate.ptr))->u.line;
588
 
589
    rhd5xxI2CSetupStatus(I2CPtr, ddc_line);
590
 
591
    if (nRead > 15) {
592
	I2CByte offset = *WriteBuffer;
593
	while (nRead) {
594
	    int n = nRead > 15 ? 15 : nRead;
595
	    if (!rhd5xxWriteReadChunk(i2cDevPtr, ddc_line, &offset, 1, ReadBuffer, n))
596
		return FALSE;
597
	    ReadBuffer += n;
598
	    nRead -= n;
599
	    offset += n;
600
	}
601
	return TRUE;
602
    } else
603
	return rhd5xxWriteReadChunk(i2cDevPtr, ddc_line, WriteBuffer, nWrite,
604
	    ReadBuffer, nRead);
605
}
606
 
607
/* RS690 */
608
static Bool
609
rhdRS69I2CStatus(I2CBusPtr I2CPtr)
610
{
611
    volatile CARD32 val;
612
    int i;
613
 
614
    RHDFUNC(I2CPtr);
615
 
616
    for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
617
	usleep(10);
618
 
619
	val = RHDRegRead(I2CPtr, RS69_DC_I2C_SW_STATUS);
620
 
621
	RHDDebugVerb(I2CPtr->scrnIndex, 1, "SW_STATUS: 0x%x %i\n",
622
		     (unsigned int) val, i);
623
 
624
	if (val & RS69_DC_I2C_SW_DONE)
625
	    break;
626
    }
627
 
628
    RHDRegMask(I2CPtr, RS69_DC_I2C_INTERRUPT_CONTROL, RS69_DC_I2C_SW_DONE_ACK,
629
	       RS69_DC_I2C_SW_DONE_ACK);
630
 
631
    if ((i == RHD_I2C_STATUS_LOOPS) ||
632
	(val & (RS69_DC_I2C_SW_ABORTED | RS69_DC_I2C_SW_TIMEOUT |
633
		RS69_DC_I2C_SW_INTERRUPTED | RS69_DC_I2C_SW_BUFFER_OVERFLOW |
634
		RS69_DC_I2C_SW_STOPPED_ON_NACK |
635
		RS69_DC_I2C_SW_NACK0 | RS69_DC_I2C_SW_NACK1 | 0x3)))
636
	return FALSE; /* 2 */
637
 
638
    return TRUE; /* 1 */
639
}
640
 
641
static Bool
642
rhdRS69I2CSetupStatus(I2CBusPtr I2CPtr, enum rhdDDClines sda, enum rhdDDClines scl, int prescale)
643
{
644
    CARD32 clk_pin, data_pin;
645
 
646
    RHDFUNC(I2CPtr);
647
 
648
    switch (sda) {
649
	case rhdDdc1data:
650
	    data_pin = 0;
651
	    break;
652
	case rhdDdc2data:
653
	    data_pin = 1;
654
	    break;
655
	case rhdDdc3data:
656
	    data_pin = 2;
657
	    break;
658
	default:
659
	    return FALSE;
660
    }
661
    switch (scl) {
662
	case rhdDdc1data:
663
	    clk_pin = 4;
664
	    break;
665
	case rhdDdc2data:
666
	    clk_pin = 5;
667
	    break;
668
	case rhdDdc3data:
669
	    clk_pin = 6;
670
	    break;
671
	case rhdDdc1clk:
672
	    clk_pin = 0;
673
	    break;
674
	case rhdDdc2clk:
675
	    clk_pin = 1;
676
	    break;
677
	case rhdDdc3clk:
678
	    clk_pin = 2;
679
	    break;
680
	default:
681
	    return FALSE;
682
    }
683
 
684
    RHDRegMask(I2CPtr, 0x28, 0x200, 0x200);
685
    RHDRegMask(I2CPtr, RS69_DC_I2C_UNKNOWN_1, prescale << 16 | 0x2, 0xffff00ff);
686
    RHDRegWrite(I2CPtr, RS69_DC_I2C_DDC_SETUP_Q, 0x30000000);
687
    RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, ((data_pin & 0x3) << 16) | (clk_pin << 8), 0xffff00);
688
    RHDRegMask(I2CPtr, RS69_DC_I2C_INTERRUPT_CONTROL, 0x2, 0x2);
689
    RHDRegMask(I2CPtr, RS69_DC_I2C_UNKNOWN_2, 0x2, 0xff);
690
 
691
    return TRUE;
692
}
693
 
694
static Bool
695
rhdRS69WriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer,
696
		 int nWrite, I2CByte *ReadBuffer, int nRead)
697
{
698
    Bool ret = FALSE;
699
    CARD32 data = 0;
700
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
701
    I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
702
    rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
703
    int prescale = I2C->prescale;
704
    int idx = 1;
705
 
706
    enum {
707
	TRANS_WRITE_READ,
708
	TRANS_WRITE,
709
	TRANS_READ
710
    } trans;
711
 
712
    RHDFUNC(i2cDevPtr->pI2CBus);
713
 
714
    if (nWrite > 0 && nRead > 0) {
715
	trans = TRANS_WRITE_READ;
716
    } else if (nWrite > 0) {
717
	trans = TRANS_WRITE;
718
    } else if (nRead > 0) {
719
	trans = TRANS_READ;
720
    } else {
721
	/* for bus probing */
722
	trans = TRANS_WRITE;
723
    }
724
    if (slave & 0xff00) {
725
	xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
726
		   "%s: 10 bit I2C slave addresses not supported\n",__func__);
727
	return FALSE;
728
    }
729
 
730
    if (!rhdRS69I2CSetupStatus(I2CPtr, I2C->u.Gpio.Sda, I2C->u.Gpio.Scl,  prescale))
731
	return FALSE;
732
 
733
    RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
734
	       ? (1 << 20) : 0, RS69_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
735
    RHDRegMask(I2CPtr, RS69_DC_I2C_TRANSACTION0,
736
	       RS69_DC_I2C_STOP_ON_NACK0
737
	       | (trans == TRANS_READ ? RS69_DC_I2C_RW0 : 0)
738
	       | RS69_DC_I2C_START0
739
	       | (trans == TRANS_WRITE_READ ? 0 : RS69_DC_I2C_STOP0 )
740
	       | ((trans == TRANS_READ ? nRead : nWrite)  << 16),
741
	       0xffffff);
742
    if (trans == TRANS_WRITE_READ)
743
	RHDRegMask(I2CPtr, RS69_DC_I2C_TRANSACTION1,
744
		   nRead << 16
745
		   | RS69_DC_I2C_RW1
746
		   | RS69_DC_I2C_START1
747
		   | RS69_DC_I2C_STOP1,
748
		   0xffffff); /*  read */
749
 
750
    data = RS69_DC_I2C_INDEX_WRITE
751
	| (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
752
	| (0 << 16);
753
    RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
754
    if (trans != TRANS_READ) { /* we have bytes to write */
755
	while (nWrite--) {
756
	    data = RS69_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
757
		| (idx++ << 16);
758
	    RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
759
	}
760
    }
761
    if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
762
	data = RS69_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
763
	RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, data);
764
    }
765
    /* Go! */
766
    RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, RS69_DC_I2C_GO, RS69_DC_I2C_GO);
767
    if (rhdRS69I2CStatus(I2CPtr)) {
768
	/* Hopefully this doesn't write data to index */
769
	RHDRegWrite(I2CPtr, RS69_DC_I2C_DATA, RS69_DC_I2C_INDEX_WRITE
770
		    | RS69_DC_I2C_DATA_RW  | /* idx++ */3 << 16);
771
	while (nRead--) {
772
	    data = RHDRegRead(I2CPtr, RS69_DC_I2C_DATA);
773
	    *(ReadBuffer++) = (data >> 8) & 0xff;
774
	}
775
	ret = TRUE;
776
    }
777
 
778
    RHDRegMask(I2CPtr, RS69_DC_I2C_CONTROL, 0x2, 0xff);
779
    usleep(10);
780
    RHDRegWrite(I2CPtr, RS69_DC_I2C_CONTROL, 0);
781
 
782
    return ret;
783
}
784
 
785
 
786
/* R6xx */
787
static Bool
788
rhdR6xxI2CStatus(I2CBusPtr I2CPtr)
789
{
790
    volatile CARD32 val;
791
    int i;
792
 
793
    RHDFUNC(I2CPtr);
794
 
795
    for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
796
	usleep(10);
797
 
798
	val = RHDRegRead(I2CPtr, R6_DC_I2C_SW_STATUS);
799
 
800
	RHDDebugVerb(I2CPtr->scrnIndex, 1, "SW_STATUS: 0x%x %i\n",
801
		     (unsigned int) val, i);
802
 
803
	if (val & R6_DC_I2C_SW_DONE)
804
	    break;
805
    }
806
 
807
    RHDRegMask(I2CPtr, R6_DC_I2C_INTERRUPT_CONTROL, R6_DC_I2C_SW_DONE_ACK,
808
	       R6_DC_I2C_SW_DONE_ACK);
809
 
810
    if ((i == RHD_I2C_STATUS_LOOPS) ||
811
	(val & (R6_DC_I2C_SW_ABORTED | R6_DC_I2C_SW_TIMEOUT |
812
		R6_DC_I2C_SW_INTERRUPTED | R6_DC_I2C_SW_BUFFER_OVERFLOW |
813
		R6_DC_I2C_SW_STOPPED_ON_NACK |
814
		R6_DC_I2C_SW_NACK0 | R6_DC_I2C_SW_NACK1 | 0x3)))
815
	return FALSE; /* 2 */
816
 
817
    return TRUE; /* 1 */
818
}
819
 
820
static Bool
821
rhd6xxI2CSetupStatus(I2CBusPtr I2CPtr, int line, int prescale)
822
{
823
    line &= 0xf;
824
 
825
    RHDFUNC(I2CPtr);
826
 
827
    switch (line) {
828
	case 0:
829
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_MASK, 0x0, 0xffff);
830
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_A, 0x0, 0xffff);
831
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC1_EN, 0x0, 0xffff);
832
	    RHDRegMask(I2CPtr, R6_DC_I2C_DDC1_SPEED, (prescale << 16) | 2,
833
		       0xffff00ff);
834
	    RHDRegWrite(I2CPtr, R6_DC_I2C_DDC1_SETUP, 0x30000000);
835
	    break;
836
	case 1:
837
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_MASK, 0x0, 0xffff);
838
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_A, 0x0, 0xffff);
839
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC2_EN, 0x0, 0xffff);
840
	    RHDRegMask(I2CPtr, R6_DC_I2C_DDC2_SPEED, (prescale << 16) | 2,
841
		       0xffff00ff);
842
	    RHDRegWrite(I2CPtr, R6_DC_I2C_DDC2_SETUP, 0x30000000);
843
	    break;
844
	case 2:
845
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_MASK, 0x0, 0xffff);
846
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_A, 0x0, 0xffff);
847
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC3_EN, 0x0, 0xffff);
848
	    RHDRegMask(I2CPtr, R6_DC_I2C_DDC3_SPEED, (prescale << 16) | 2,
849
		       0xffff00ff);
850
	    RHDRegWrite(I2CPtr, R6_DC_I2C_DDC3_SETUP, 0x30000000);
851
	    break;
852
	case 3:
853
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_MASK, 0x0, 0xffff);
854
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_A, 0x0, 0xffff);
855
	    RHDRegMask(I2CPtr, R6_DC_GPIO_DDC4_EN, 0x0, 0xffff);
856
	    RHDRegMask(I2CPtr, R6_DC_I2C_DDC4_SPEED, (prescale << 16) | 2,
857
		       0xffff00ff);
858
	    RHDRegWrite(I2CPtr, R6_DC_I2C_DDC4_SETUP, 0x30000000);
859
	    break;
860
	default:
861
	    xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
862
		       "%s: Trying to initialize non-existent I2C line: %i\n",
863
		       __func__,line);
864
	    return FALSE;
865
    }
866
    RHDRegWrite(I2CPtr, R6_DC_I2C_CONTROL, line << 8);
867
    RHDRegMask(I2CPtr, R6_DC_I2C_INTERRUPT_CONTROL, 0x2, 0x2);
868
    RHDRegMask(I2CPtr, R6_DC_I2C_ARBITRATION, 0, 0xff);
869
    return TRUE;
870
}
871
 
872
static Bool
873
rhd6xxWriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
874
{
875
    Bool ret = FALSE;
876
    CARD32 data = 0;
877
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
878
    I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
879
    rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
880
    CARD32 ddc_line = I2C->u.line;
881
    int prescale = I2C->prescale;
882
    int idx = 1;
883
    enum {
884
	TRANS_WRITE_READ,
885
	TRANS_WRITE,
886
	TRANS_READ
887
    } trans;
888
 
889
    RHDFUNC(i2cDevPtr->pI2CBus);
890
 
891
    if (nWrite > 0 && nRead > 0) {
892
	trans = TRANS_WRITE_READ;
893
    } else if (nWrite > 0) {
894
	trans = TRANS_WRITE;
895
    } else if (nRead > 0) {
896
	trans = TRANS_READ;
897
    } else {
898
	/* for bus probing */
899
	trans = TRANS_WRITE;
900
    }
901
    if (slave & 0xff00) {
902
	xf86DrvMsg(I2CPtr->scrnIndex,X_ERROR,
903
		   "%s: 10 bit I2C slave addresses not supported\n",__func__);
904
	return FALSE;
905
    }
906
 
907
    if (!rhd6xxI2CSetupStatus(I2CPtr, ddc_line,  prescale))
908
	return FALSE;
909
 
910
    RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, (trans == TRANS_WRITE_READ)
911
	       ? (1 << 20) : 0, R6_DC_I2C_TRANSACTION_COUNT); /* 2 or 1 Transaction */
912
    RHDRegMask(I2CPtr, R6_DC_I2C_TRANSACTION0,
913
	       R6_DC_I2C_STOP_ON_NACK0
914
	       | (trans == TRANS_READ ? R6_DC_I2C_RW0 : 0)
915
	       | R6_DC_I2C_START0
916
	       | (trans == TRANS_WRITE_READ ? 0 : R6_DC_I2C_STOP0 )
917
	       | ((trans == TRANS_READ ? nRead : nWrite)  << 16),
918
	       0xffffff);
919
    if (trans == TRANS_WRITE_READ)
920
	RHDRegMask(I2CPtr, R6_DC_I2C_TRANSACTION1,
921
		   nRead << 16
922
		   | R6_DC_I2C_RW1
923
		   | R6_DC_I2C_START1
924
		   | R6_DC_I2C_STOP1,
925
		   0xffffff); /*  read */
926
 
927
    data = R6_DC_I2C_INDEX_WRITE
928
	| (((slave & 0xfe) | (trans == TRANS_READ ? 1 : 0)) << 8 )
929
	| (0 << 16);
930
    RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
931
    if (trans != TRANS_READ) { /* we have bytes to write */
932
	while (nWrite--) {
933
	    data = R6_DC_I2C_INDEX_WRITE | ( *(WriteBuffer++) << 8 )
934
		| (idx++ << 16);
935
	    RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
936
	}
937
    }
938
    if (trans == TRANS_WRITE_READ) { /* we have bytes to read after write */
939
	data = R6_DC_I2C_INDEX_WRITE | ((slave | 0x1) << 8) | (idx++ << 16);
940
	RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, data);
941
    }
942
    /* Go! */
943
    RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, R6_DC_I2C_GO, R6_DC_I2C_GO);
944
    if (rhdR6xxI2CStatus(I2CPtr)) {
945
	/* Hopefully this doesn't write data to index */
946
	RHDRegWrite(I2CPtr, R6_DC_I2C_DATA, R6_DC_I2C_INDEX_WRITE
947
		    | R6_DC_I2C_DATA_RW  | /* idx++ */3 << 16);
948
	while (nRead--) {
949
	    data = RHDRegRead(I2CPtr, R6_DC_I2C_DATA);
950
	    *(ReadBuffer++) = (data >> 8) & 0xff;
951
	}
952
	ret = TRUE;
953
    }
954
 
955
    RHDRegMask(I2CPtr, R6_DC_I2C_CONTROL, 0x2, 0xff);
956
    usleep(10);
957
    RHDRegWrite(I2CPtr, R6_DC_I2C_CONTROL, 0);
958
 
959
    return ret;
960
}
961
 
962
/* RV620 */
963
static Bool
964
rhdRV620I2CStatus(I2CBusPtr I2CPtr)
965
{
966
    volatile CARD32 val;
967
    int i;
968
 
969
    RHDFUNC(I2CPtr);
970
 
971
    for (i = 0; i < RHD_I2C_STATUS_LOOPS; i++) {
972
	usleep(10);
973
 
974
	val = RHDRegRead(I2CPtr, RV62_GENERIC_I2C_STATUS);
975
 
976
	RHDDebugVerb(I2CPtr->scrnIndex, 1,
977
		     "SW_STATUS: 0x%x %i\n", (unsigned int) val, i);
978
	if (val & RV62_GENERIC_I2C_DONE)
979
	    break;
980
    }
981
 
982
    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_INTERRUPT_CONTROL, 0x2, 0xff);
983
 
984
    if ((i == RHD_I2C_STATUS_LOOPS) ||
985
	(val & (RV62_GENERIC_I2C_STOPPED_ON_NACK | RV62_GENERIC_I2C_NACK |
986
		RV62_GENERIC_I2C_ABORTED | RV62_GENERIC_I2C_TIMEOUT)))
987
	return FALSE; /* 2 */
988
 
989
    return TRUE; /* 1 */
990
}
991
 
992
/*
993
 *
994
 */
995
static  Bool
996
rhdRV620I2CSetupStatus(I2CBusPtr I2CPtr, struct i2cGpio *Gpio, int prescale)
997
{
998
    CARD32 reg_7d9c = 0; /* 0 is invalid */
999
    CARD32 scl_reg;
1000
 
1001
    RHDFUNC(I2CPtr);
1002
 
1003
    scl_reg = Gpio->SclReg;
1004
    reg_7d9c = (Gpio->Scl << RV62_GENERIC_I2C_SCL_PIN_SEL_SHIFT)
1005
	| (Gpio->Sda << RV62_GENERIC_I2C_SDA_PIN_SEL_SHIFT);
1006
 
1007
    scl_reg = Gpio->SclReg;
1008
    /* Don't understand this yet */
1009
    if (scl_reg == 0x1fda)
1010
	scl_reg = 0x1f90;
1011
 
1012
    RHDRegWrite(I2CPtr, scl_reg << 2, 0);
1013
 
1014
    RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_PIN_SELECTION, reg_7d9c);
1015
    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_SPEED,
1016
	    (prescale & 0xffff) << 16 | 0x02, 0xffff00ff);
1017
    RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_SETUP, 0x30000000);
1018
    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_INTERRUPT_CONTROL,
1019
	    RV62_GENERIC_I2C_DONE_ACK, RV62_GENERIC_I2C_DONE_ACK);
1020
 
1021
    return TRUE;
1022
}
1023
 
1024
static Bool
1025
rhdRV620Transaction(I2CDevPtr i2cDevPtr, Bool Write, I2CByte *Buffer, int count)
1026
{
1027
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
1028
    I2CSlaveAddr slave = i2cDevPtr->SlaveAddr;
1029
    Bool Start = TRUE;
1030
 
1031
    RHDFUNC(I2CPtr);
1032
 
1033
#define MAX 8
1034
 
1035
    while (count > 0 || (Write && Start)) {
1036
	int num;
1037
	int idx = 0;
1038
	CARD32 data = 0;
1039
 
1040
	if (count > MAX) {
1041
	    num = MAX;
1042
	    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_TRANSACTION,
1043
		    (MAX - (((Start) ? 0 : 1))) << 16
1044
		    | RV62_GENERIC_I2C_STOP_ON_NACK
1045
		    | RV62_GENERIC_I2C_ACK_ON_READ
1046
		    | (Start ? RV62_GENERIC_I2C_START : 0)
1047
		    | (!Write ? RV62_GENERIC_I2C_RW : 0 ),
1048
		    0xFFFFFF);
1049
	} else {
1050
	    num = count;
1051
	    data = ( count - (((Start) ? 0 : 1)) ) << 16
1052
		| RV62_GENERIC_I2C_STOP_ON_NACK
1053
		|  RV62_GENERIC_I2C_STOP
1054
		| (Start ? RV62_GENERIC_I2C_START : 0)
1055
		| (!Write ? RV62_GENERIC_I2C_RW : 0);
1056
	    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_TRANSACTION,
1057
		    data,
1058
		    0xFFFFFF);
1059
	}
1060
 
1061
	if (Start) {
1062
	    data = RV62_GENERIC_I2C_INDEX_WRITE
1063
		| (((slave & 0xfe) | ( Write ? 0 : 1)) << 8)
1064
		| (idx++ << 16);
1065
	    RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA, data);
1066
	}
1067
 
1068
	if (Write) {
1069
	    while (num--) {
1070
		data = RV62_GENERIC_I2C_INDEX_WRITE
1071
		    | (idx++ << 16)
1072
		    | *(Buffer++) << 8;
1073
		RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA, data);
1074
	    }
1075
 
1076
	    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_CONTROL,
1077
		    RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
1078
	    if (!rhdRV620I2CStatus(I2CPtr))
1079
		return FALSE;
1080
	} else {
1081
 
1082
	    RHDRegMask(I2CPtr, RV62_GENERIC_I2C_CONTROL,
1083
		    RV62_GENERIC_I2C_GO, RV62_GENERIC_I2C_GO);
1084
	    if (!rhdRV620I2CStatus(I2CPtr))
1085
		return FALSE;
1086
 
1087
	    RHDRegWrite(I2CPtr, RV62_GENERIC_I2C_DATA,
1088
		     RV62_GENERIC_I2C_INDEX_WRITE
1089
		     | (idx++ << 16)
1090
		     | RV62_GENERIC_I2C_RW);
1091
 
1092
	    while (num--) {
1093
		data = RHDRegRead(I2CPtr, RV62_GENERIC_I2C_DATA);
1094
		*(Buffer++) = (CARD8)((data >> 8) & 0xff);
1095
	    }
1096
	}
1097
	Start = FALSE;
1098
	count -= MAX;
1099
    }
1100
 
1101
    return TRUE;
1102
}
1103
 
1104
static Bool
1105
rhdRV620WriteRead(I2CDevPtr i2cDevPtr, I2CByte *WriteBuffer, int nWrite, I2CByte *ReadBuffer, int nRead)
1106
{
1107
    I2CBusPtr I2CPtr = i2cDevPtr->pI2CBus;
1108
    rhdI2CPtr I2C = (rhdI2CPtr)I2CPtr->DriverPrivate.ptr;
1109
    int prescale = I2C->prescale;
1110
 
1111
    RHDFUNC(I2C);
1112
 
1113
    rhdRV620I2CSetupStatus(I2CPtr, &I2C->u.Gpio, prescale);
1114
 
1115
    if (nWrite || !nRead)
1116
	if (!rhdRV620Transaction(i2cDevPtr, TRUE, WriteBuffer, nWrite))
1117
	    return FALSE;
1118
    if (nRead)
1119
	if (!rhdRV620Transaction(i2cDevPtr, FALSE, ReadBuffer, nRead))
1120
	    return FALSE;
1121
 
1122
    return TRUE;
1123
}
1124
 
1125
static void
1126
rhdTearDownI2C(I2CBusPtr *I2C)
1127
{
1128
    int i;
1129
 
1130
    /*
1131
     * xf86I2CGetScreenBuses() is
1132
     * broken in older server versions.
1133
     * So we cannot use it. How bad!
1134
     */
1135
    for (i = 0; i < MAX_I2C_LINES; i++) {
1136
	char *name;
1137
	if (!I2C[i])
1138
	    break;
1139
	name = I2C[i]->BusName;
1140
	xfree(I2C[i]->DriverPrivate.ptr);
1141
	xf86DestroyI2CBusRec(I2C[i], TRUE, TRUE);
1142
	xfree(name);
1143
    }
1144
    xfree(I2C);
1145
}
1146
 
1147
#define TARGET_HW_I2C_CLOCK 25 /*  kHz */
1148
#define DEFAULT_ENGINE_CLOCK 453000 /* kHz (guessed) */
1149
#define DEFAULT_REF_CLOCK 27000
1150
 
1151
static CARD32
1152
rhdGetI2CPrescale(RHDPtr rhdPtr)
1153
{
1154
#ifdef ATOM_BIOS
1155
    AtomBiosArgRec atomBiosArg;
1156
    RHDFUNC(rhdPtr);
1157
 
1158
    if (rhdPtr->ChipSet < RHD_R600) {
1159
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1160
			    GET_DEFAULT_ENGINE_CLOCK, &atomBiosArg)
1161
	    == ATOM_SUCCESS)
1162
	    return (0x7f << 8)
1163
		+ (atomBiosArg.val / (4 * 0x7f * TARGET_HW_I2C_CLOCK));
1164
	else
1165
	    return (0x7f << 8)
1166
		+ (DEFAULT_ENGINE_CLOCK / (4 * 0x7f * TARGET_HW_I2C_CLOCK));
1167
    } else if (rhdPtr->ChipSet < RHD_RV620) {
1168
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1169
			    GET_REF_CLOCK, &atomBiosArg) == ATOM_SUCCESS)
1170
	    return (atomBiosArg.val / TARGET_HW_I2C_CLOCK);
1171
	else
1172
	    return (DEFAULT_REF_CLOCK / TARGET_HW_I2C_CLOCK);
1173
    } else {
1174
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1175
			    GET_REF_CLOCK, &atomBiosArg) == ATOM_SUCCESS)
1176
	    return (atomBiosArg.val / (4 * TARGET_HW_I2C_CLOCK));
1177
	else
1178
	    return (DEFAULT_REF_CLOCK / (4 * TARGET_HW_I2C_CLOCK));
1179
    }
1180
#else
1181
    RHDFUNC(rhdPtr);
1182
 
1183
    if (rhdPtr->ChipSet < RHD_R600) {
1184
	return (0x7f << 8)
1185
	    + (DEFAULT_ENGINE_CLOCK) / (4 * 0x7f * TARGET_HW_I2C_CLOCK);
1186
    } else if (rhdPtr->ChipSet < RHD_RV620) {
1187
	return (DEFAULT_REF_CLOCK / TARGET_HW_I2C_CLOCK);
1188
    } else
1189
	  return (DEFAULT_REF_CLOCK / (4 * TARGET_HW_I2C_CLOCK));
1190
#endif
1191
}
1192
 
1193
static Bool
1194
rhdI2CAddress(I2CDevPtr d, I2CSlaveAddr addr)
1195
{
1196
    d->SlaveAddr = addr;
1197
    return xf86I2CWriteRead(d, NULL, 0, NULL, 0);
1198
}
1199
 
1200
/*
1201
 * This stub is needed to keep xf86I2CProbeAddress() happy.
1202
 */
1203
static void
1204
rhdI2CStop(I2CDevPtr d)
1205
{
1206
}
1207
 
1208
static I2CBusPtr *
1209
rhdInitI2C(int scrnIndex)
1210
{
1211
    int i;
1212
    rhdI2CPtr I2C;
1213
    I2CBusPtr I2CPtr = NULL;
1214
    RHDPtr rhdPtr = (RHDPtr)scrnIndex;
1215
    I2CBusPtr *I2CList;
1216
    int numLines;
1217
    CARD16 prescale = rhdGetI2CPrescale(rhdPtr);
1218
    enum rhdDDClines sda = 0, scl = 0;
1219
    CARD32 scl_reg = 0, sda_reg = 0;
1220
    Bool valid;
1221
 
1222
    RHDFUNCI(scrnIndex);
1223
 
1224
    if (rhdPtr->ChipSet < RHD_RS600)
1225
	numLines = 3;
1226
    else if (rhdPtr->ChipSet < RHD_R600)
1227
	numLines = 4;
1228
    else if (rhdPtr->ChipSet < RHD_RV730)
1229
	numLines = 4;
1230
    else
1231
	numLines = MAX_I2C_LINES;
1232
 
1233
    if (!(I2CList = xcalloc(MAX_I2C_LINES, sizeof(I2CBusPtr)))) {
1234
	xf86DrvMsg(scrnIndex, X_ERROR,
1235
		   "%s: Out of memory.\n",__func__);
1236
    }
1237
    /* We have 4 I2C lines */
1238
    for (i = 0; i < numLines; i++) {
1239
	if (!(I2C = xcalloc(sizeof(rhdI2CRec),1))) {
1240
	    xf86DrvMsg(scrnIndex, X_ERROR,
1241
		       "%s: Out of memory.\n",__func__);
1242
	    goto error;
1243
	}
1244
	I2C->scrnIndex = scrnIndex;
1245
 
1246
	valid = rhdI2CGetDataClkLines(rhdPtr, i, &scl, &sda, &sda_reg, &scl_reg);
1247
	if (rhdPtr->ChipSet < RHD_RS600
1248
	    || (rhdPtr->ChipSet > RHD_RS740 && rhdPtr->ChipSet < RHD_RV620)) {
1249
 
1250
	    if (valid) {
1251
		if (sda == rhdDdc1data && scl == rhdDdc1clk)
1252
		    I2C->u.line = 0;
1253
		else if (sda == rhdDdc2data && scl == rhdDdc2clk)
1254
		    I2C->u.line = 1;
1255
		else if (sda == rhdDdc3data && scl == rhdDdc3clk)
1256
		    I2C->u.line = 2;
1257
		else if (rhdPtr->ChipSet > RHD_RS740 && sda == rhdDdc4data && scl == rhdDdc4clk)
1258
		    I2C->u.line = 3; /* R6XX only */
1259
		else {
1260
		    xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "No DDC line found for index %i: scl=0x%2.2x sda=0x%2.2x\n",
1261
			       i, scl, sda);
1262
		    xfree(I2C);
1263
		    continue;
1264
		}
1265
 
1266
	    } else
1267
		I2C->u.line = i;
1268
 
1269
	} else if (rhdPtr->ChipSet <= RHD_RS740) {
1270
 
1271
	    if (valid) {
1272
		if (sda != rhdDdc1data && sda != rhdDdc2data && sda != rhdDdc3data) {
1273
		    xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid DDC CLK pin found: %i\n",
1274
			       sda);
1275
		    xfree(I2C);
1276
		    continue;
1277
		}
1278
		if (scl != rhdDdc1data && scl != rhdDdc2data && scl != rhdDdc3data
1279
		    && scl != rhdDdc1clk && scl != rhdDdc2clk && scl != rhdDdc3clk) {
1280
		    xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid DDC CLK pin found: %i\n",
1281
			       scl);
1282
		    xfree(I2C);
1283
		    continue;
1284
		}
1285
		I2C->u.Gpio.Sda = sda;
1286
		I2C->u.Gpio.Scl = scl;
1287
		I2C->u.Gpio.SdaReg = sda_reg;
1288
		I2C->u.Gpio.SclReg = scl_reg;
1289
 
1290
	    } else {
1291
		xf86DrvMsg(I2CPtr->scrnIndex, X_ERROR, "Invalid ClkLine for DDC. "
1292
			   "AtomBIOS reported wrong or AtomBIOS unavailable\n");
1293
		xfree(I2C);
1294
		goto error;
1295
	    }
1296
 
1297
	} else {
1298
 
1299
	    if (valid) {
1300
		I2C->u.Gpio.Sda = sda;
1301
		I2C->u.Gpio.Scl = scl;
1302
		I2C->u.Gpio.SdaReg = sda_reg;
1303
		I2C->u.Gpio.SclReg = scl_reg;
1304
	    } else {
1305
		CARD32 gpioReg[] = { 0x1f90, 0x1f94, 0x1f98 };
1306
		enum rhdDDClines sdaList[] = { rhdDdc1data, rhdDdc2data, rhdDdc3data };
1307
		enum rhdDDClines sclList[] = { rhdDdc1clk, rhdDdc2clk, rhdDdc3clk };
1308
		if (i > 2) {
1309
		    xfree(I2C);
1310
		    continue;
1311
		}
1312
		I2C->u.Gpio.Sda = sdaList[i];
1313
		I2C->u.Gpio.Scl = sclList[i];
1314
		I2C->u.Gpio.SclReg = I2C->u.Gpio.SdaReg = gpioReg[i];
1315
	    }
1316
 
1317
	}
1318
 
1319
        /*
1320
	 * This is a value that has been found to work on many cards.
1321
	 * It nees to be replaced by the proper calculation formula
1322
	 * once this is available.
1323
	 */
1324
	I2C->prescale = prescale;
1325
	xf86DrvMsgVerb(scrnIndex, X_INFO, 5, "I2C clock prescale value: %x\n",I2C->prescale);
1326
 
1327
	if (!(I2CPtr = xf86CreateI2CBusRec())) {
1328
	    xf86DrvMsg(scrnIndex, X_ERROR,
1329
		       "Cannot allocate I2C BusRec.\n");
1330
	    xfree(I2C);
1331
	    goto error;
1332
	}
1333
	I2CPtr->DriverPrivate.ptr = I2C;
1334
	if (!(I2CPtr->BusName = xalloc(18))) {
1335
	    xf86DrvMsg(scrnIndex, X_ERROR,
1336
		       "%s: Cannot allocate memory.\n",__func__);
1337
	    xfree(I2C);
1338
	    xf86DestroyI2CBusRec(I2CPtr, TRUE, FALSE);
1339
	    goto error;
1340
	}
1341
	snprintf(I2CPtr->BusName,17,"RHD I2C line %1.1i",i);
1342
	I2CPtr->scrnIndex = scrnIndex;
1343
	if (rhdPtr->ChipSet < RHD_RS600)
1344
	    I2CPtr->I2CWriteRead = rhd5xxWriteRead;
1345
	else if (rhdPtr->ChipSet >= RHD_RS600 && rhdPtr->ChipSet <= RHD_RS740)
1346
	    I2CPtr->I2CWriteRead = rhdRS69WriteRead;
1347
	else if (rhdPtr->ChipSet < RHD_RV620)
1348
	    I2CPtr->I2CWriteRead = rhd6xxWriteRead;
1349
	else
1350
	    I2CPtr->I2CWriteRead = rhdRV620WriteRead;
1351
	I2CPtr->I2CAddress = rhdI2CAddress;
1352
	I2CPtr->I2CStop = rhdI2CStop;
1353
 
1354
	if (!(xf86I2CBusInit(I2CPtr))) {
1355
	    xf86DrvMsg(scrnIndex, X_ERROR,
1356
		       "I2C BusInit failed for bus %i\n",i);
1357
	    xfree(I2CPtr->BusName);
1358
	    xfree(I2C);
1359
	    xf86DestroyI2CBusRec(I2CPtr, TRUE, FALSE);
1360
	    goto error;
1361
	}
1362
	I2CList[i] = I2CPtr;
1363
    }
1364
    return I2CList;
1365
 error:
1366
    rhdTearDownI2C(I2CList);
1367
    return NULL;
1368
}
1369
 
1370
RHDI2CResult
1371
rhdI2CProbeAddress(int scrnIndex, I2CBusPtr I2CBusPtr, CARD8 slave)
1372
{
1373
    I2CDevPtr dev;
1374
    char *name = "I2CProbe";
1375
 
1376
    if ((dev = xf86CreateI2CDevRec())) {
1377
	dev->DevName = name;
1378
	dev->pI2CBus = I2CBusPtr;
1379
 
1380
	if (xf86I2CDevInit(dev)) {
1381
	    Bool ret;
1382
 
1383
	    dev->SlaveAddr = slave & 0xFE;
1384
 
1385
	    ret = xf86I2CWriteRead(dev, NULL, 0, NULL, 0);
1386
 
1387
	    if (ret) {
1388
		unsigned char offset = 0;
1389
		unsigned char buf[2];
1390
 
1391
		/*
1392
		  ASUS M2A-VM (R690) motherboards ACK all I2C slaves on the
1393
		  HDMI line when the HDMI riser card is not installed.
1394
		  We therefore need to read the first two bytes and check
1395
		  if they are part of an I2C header.
1396
		*/
1397
		ret = xf86I2CWriteRead(dev, &offset, 1, buf, 2);
1398
		if (ret && (buf[0] != 0 || buf[1] != 0xff))
1399
		    ret = FALSE;
1400
	    }
1401
	    xf86DestroyI2CDevRec(dev, TRUE);
1402
 
1403
	    return ret ? RHD_I2C_SUCCESS : RHD_I2C_FAILED;
1404
	}
1405
    }
1406
 
1407
    return RHD_I2C_FAILED;
1408
}
1409
 
1410
RHDI2CResult
1411
RHDI2CFunc(int scrnIndex, I2CBusPtr *I2CList, RHDi2cFunc func,
1412
	   RHDI2CDataArgPtr datap)
1413
{
1414
    RHDFUNCI(scrnIndex);
1415
 
1416
    if (func == RHD_I2C_INIT) {
1417
	if (!(datap->I2CBusList = rhdInitI2C(scrnIndex)))
1418
	    return RHD_I2C_FAILED;
1419
	else
1420
	    return RHD_I2C_SUCCESS;
1421
    }
1422
    if (func == RHD_I2C_DDC) {
1423
	if (datap->i >= MAX_I2C_LINES || !I2CList[datap->i])
1424
	    return RHD_I2C_NOLINE;
1425
 
1426
	datap->monitor = xf86DoEDID_DDC2(scrnIndex, I2CList[datap->i]);
1427
	return RHD_I2C_SUCCESS;
1428
    }
1429
    if (func == RHD_I2C_PROBE_ADDR_LINE) {
1430
 
1431
	if (datap->target.line >= MAX_I2C_LINES || !I2CList[datap->target.line])
1432
	    return RHD_I2C_NOLINE;
1433
	return rhdI2CProbeAddress(scrnIndex, I2CList[datap->target.line], datap->target.slave);
1434
    }
1435
    if (func == RHD_I2C_PROBE_ADDR) {
1436
	return rhdI2CProbeAddress(scrnIndex, datap->probe.i2cBusPtr, datap->probe.slave);
1437
    }
1438
    if (func == RHD_I2C_GETBUS) {
1439
	if (datap->i >= MAX_I2C_LINES || !I2CList[datap->i])
1440
	    return RHD_I2C_NOLINE;
1441
 
1442
	datap->i2cBusPtr = I2CList[datap->i];
1443
	return RHD_I2C_SUCCESS;
1444
    }
1445
    if (func == RHD_I2C_TEARDOWN) {
1446
	if (I2CList)
1447
	    rhdTearDownI2C(I2CList);
1448
	return RHD_I2C_SUCCESS;
1449
    }
1450
    return RHD_I2C_FAILED;
1451
}
1452