Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1029 serge 1
/*
2
 * Copyright 2007, 2008  Luc Verhaegen 
3
 * Copyright 2007, 2008  Matthias Hopf 
4
 * Copyright 2007, 2008  Egbert Eich   
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
 
30
#include "xf86.h"
31
 
32
/* for usleep */
33
#if HAVE_XF86_ANSIC_H
34
# include "xf86_ansic.h"
35
#else
36
# include 
37
# include 
38
# include 
39
#endif
40
 
41
#include "rhd.h"
42
#include "rhd_connector.h"
43
#include "rhd_output.h"
44
#include "rhd_crtc.h"
45
#include "rhd_regs.h"
46
#ifdef ATOM_BIOS
47
# include "rhd_atombios.h"
48
#endif
49
 
50
#define REG_DACA_OFFSET 0
51
#define RV620_REG_DACA_OFFSET 0
52
#define REG_DACB_OFFSET 0x200
53
#define RV620_REG_DACB_OFFSET 0x100
54
 
55
struct rhdDACPrivate {
56
    Bool Stored;
57
 
58
    CARD32 Store_Powerdown;
59
    CARD32 Store_Force_Output_Control;
60
    CARD32 Store_Force_Data;
61
    CARD32 Store_Source_Select;
62
    CARD32 Store_Sync_Select;
63
    CARD32 Store_Enable;
64
    CARD32 Store_Control1;
65
    CARD32 Store_Control2;
66
    CARD32 Store_Tristate_Control;
67
    CARD32 Store_Auto_Calib_Control;
68
    CARD32 Store_Dac_Bgadj_Src;
69
};
70
 
71
/* ----------------------------------------------------------- */
72
 
73
/*
74
 *
75
 */
76
static unsigned char
77
DACSense(struct rhdOutput *Output, CARD32 offset, Bool TV)
78
{
79
  CARD32 CompEnable, Control1, Control2, DetectControl, Enable;
80
  CARD8 ret;
81
 
82
    CompEnable = RHDRegRead(Output, offset + DACA_COMPARATOR_ENABLE);
83
    Control1 = RHDRegRead(Output, offset + DACA_CONTROL1);
84
    Control2 = RHDRegRead(Output, offset + DACA_CONTROL2);
85
    DetectControl = RHDRegRead(Output, offset + DACA_AUTODETECT_CONTROL);
86
    Enable = RHDRegRead(Output, offset + DACA_ENABLE);
87
 
88
    RHDRegWrite(Output, offset + DACA_ENABLE, 1);
89
    /* ack autodetect */
90
    RHDRegMask(Output, offset + DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01);
91
    RHDRegMask(Output, offset + DACA_AUTODETECT_CONTROL, 0, 0x00000003);
92
    RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00000001);
93
    RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00ff0000);
94
 
95
    if (offset) { /* We can do TV on DACA but only DACB has mux for separate connector */
96
  if (TV)
97
	RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000100, 0x00000100);
98
  else
99
	RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00000100);
100
    }
101
    RHDRegWrite(Output, offset + DACA_FORCE_DATA, 0);
102
    RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000001, 0x0000001);
103
 
104
    RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, 0x00070000, 0x00070101);
105
    RHDRegWrite(Output, offset + DACA_CONTROL1, 0x00050802);
106
    RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x00000001); /* Shut down Bandgap Voltage Reference Power */
107
  usleep(5);
108
 
109
    RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
110
 
111
    RHDRegWrite(Output, offset + DACA_FORCE_DATA, 0x1e6); /* 486 out of 1024 */
112
    usleep(200);
113
 
114
    RHDRegMask(Output, offset + DACA_POWERDOWN, 0x01010100, 0x01010100); /* Enable RGB */
115
    usleep(88);
116
 
117
    RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */
118
 
119
    RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, 0x00000100, 0x00000100);
120
  usleep(100);
121
 
122
  /* Get RGB detect values
123
   * If only G is detected, we could have a monochrome monitor,
124
   * but we don't bother with this at the moment.
125
   */
126
    ret = (RHDRegRead(Output, offset + DACA_COMPARATOR_OUTPUT) & 0x0E) >> 1;
127
 
128
    RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, CompEnable, 0x00FFFFFF);
129
    RHDRegWrite(Output, offset + DACA_CONTROL1, Control1);
130
    RHDRegMask(Output, offset + DACA_CONTROL2, Control2, 0x000001FF);
131
    RHDRegMask(Output, offset + DACA_AUTODETECT_CONTROL, DetectControl, 0x000000FF);
132
    RHDRegMask(Output, offset + DACA_ENABLE, Enable, 0x000000FF);
133
 
134
    RHDDebug(Output->scrnIndex, "%s: DAC: 0x0%1X\n", __func__, ret);
135
 
136
  return ret;
137
}
138
 
139
/*
140
 *
141
 */
142
static enum rhdSensedOutput
143
DACASense(struct rhdOutput *Output, struct rhdConnector *Connector)
144
{
145
    enum rhdConnectorType Type = Connector->Type;
146
  RHDFUNC(Output);
147
 
148
    switch (Type) {
149
    case RHD_CONNECTOR_DVI:
150
    case RHD_CONNECTOR_DVI_SINGLE:
151
    case RHD_CONNECTOR_VGA:
152
	return  (DACSense(Output, REG_DACA_OFFSET, FALSE) == 0x7)
153
	    ? RHD_SENSED_VGA
154
	    : RHD_SENSED_NONE;
155
    default:
156
	xf86DrvMsg(Output->scrnIndex, X_WARNING,
157
		   "%s: connector type %d is not supported on DACA.\n",
158
		   __func__, Type);
159
	return RHD_SENSED_NONE;
160
    }
161
}
162
 
163
/*
164
 *
165
 */
166
static enum rhdSensedOutput
167
DACBSense(struct rhdOutput *Output, struct rhdConnector *Connector)
168
{
169
    enum rhdConnectorType Type = Connector->Type;
170
    RHDFUNC(Output);
171
 
172
    switch (Type) {
173
    case RHD_CONNECTOR_DVI:
174
    case RHD_CONNECTOR_DVI_SINGLE:
175
    case RHD_CONNECTOR_VGA:
176
	return  (DACSense(Output, REG_DACB_OFFSET, FALSE) == 0x7)
177
	    ? RHD_SENSED_VGA
178
	    : RHD_SENSED_NONE;
179
    case RHD_CONNECTOR_TV:
180
	switch (DACSense(Output, REG_DACB_OFFSET, TRUE) & 0x7) {
181
	    case 0x7:
182
		return RHD_SENSED_TV_COMPONENT;
183
	    case 0x6:
184
		return RHD_SENSED_TV_SVIDEO;
185
	    case 0x1:
186
		return RHD_SENSED_TV_COMPOSITE;
187
    default:
188
		return RHD_SENSED_NONE;
189
	}
190
    default:
191
	xf86DrvMsg(Output->scrnIndex, X_WARNING,
192
		   "%s: connector type %d is not supported on DACB.\n",
193
		   __func__, Type);
194
	return RHD_SENSED_NONE;
195
    }
196
}
197
 
198
enum outputType {
199
    TvPAL = 0,
200
    TvNTSC,
201
    VGA,
202
    TvCV,
203
    typeLast = VGA
204
};
205
 
206
/*
207
 *
208
 */
209
static void
210
DACGetElectrical(RHDPtr rhdPtr, enum outputType type, int dac, CARD8 *bandgap, CARD8 *whitefine)
211
{
212
#ifdef ATOM_BIOS
213
    enum _AtomBiosRequestID bg = 0, wf = 0;
214
    AtomBiosArgRec atomBiosArg;
215
#endif
216
    struct
217
    {
218
	CARD16 pciIdMin;
219
	CARD16 pciIdMax;
220
	CARD8 bandgap[2][4];
221
	CARD8 whitefine[2][4];
222
    } list[] = {
223
	{ 0x791E, 0x791F,
224
	  { { 0x07, 0x07, 0x07, 0x07 },
225
	    { 0x07, 0x07, 0x07, 0x07 } },
226
	  { { 0x09, 0x09, 0x04, 0x09 },
227
	    { 0x09, 0x09, 0x04, 0x09 } },
228
	},
229
	{ 0x793F, 0x7942,
230
	  { { 0x09, 0x09, 0x09, 0x09 },
231
	    { 0x09, 0x09, 0x09, 0x09 } },
232
	  { { 0x0a, 0x0a, 0x08, 0x0a },
233
	    { 0x0a, 0x0a, 0x08, 0x0a } },
234
	},
235
	{ 0x9500, 0x9519,
236
	  { { 0x00, 0x00, 0x00, 0x00 },
237
	    { 0x00, 0x00, 0x00, 0x00 } },
238
	  { { 0x00, 0x00, 0x20, 0x00 },
239
	    { 0x25, 0x25, 0x26, 0x26 } },
240
	},
241
	{ 0, 0,
242
	  { { 0, 0, 0, 0 },
243
	    { 0, 0, 0, 0 } },
244
	  { { 0, 0, 0, 0 },
245
	    { 0, 0, 0, 0 } }
246
	}
247
    };
248
 
249
    *bandgap = *whitefine = 0;
250
 
251
#ifdef ATOM_BIOS
252
    switch (type) {
253
	case TvPAL:
254
	    bg = ATOM_DAC2_PAL_BG_ADJ;
255
	    wf = ATOM_DAC2_PAL_DAC_ADJ;
256
	    break;
257
	case TvNTSC:
258
	    bg = ATOM_DAC2_NTSC_BG_ADJ;
259
	    wf = ATOM_DAC2_NTSC_DAC_ADJ;
260
	    break;
261
	case TvCV:
262
	    bg = ATOM_DAC2_CV_BG_ADJ;
263
	    wf = ATOM_DAC2_CV_DAC_ADJ;
264
	    break;
265
	case VGA:
266
	    switch (dac) {
267
		case 0:
268
		    bg = ATOM_DAC1_BG_ADJ;
269
		    wf = ATOM_DAC1_DAC_ADJ;
270
		    break;
271
		default:
272
		    bg = ATOM_DAC2_CRTC2_BG_ADJ;
273
		    wf = ATOM_DAC2_CRTC2_DAC_ADJ;
274
		    break;
275
	    }
276
	    break;
277
    }
278
    if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, bg, &atomBiosArg)
279
	== ATOM_SUCCESS) {
280
	*bandgap = atomBiosArg.val;
281
	RHDDebug(rhdPtr->scrnIndex, "%s: BandGap found in CompassionateData.\n",__func__);
282
    }
283
    if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, wf, &atomBiosArg)
284
	== ATOM_SUCCESS) {
285
	*whitefine = atomBiosArg.val;
286
	RHDDebug(rhdPtr->scrnIndex, "%s: WhiteFine found in CompassionateData.\n",__func__);
287
    }
288
    if (*whitefine == 0) {
289
	CARD8 w_f = 0, b_g = 0;
290
 
291
	if (atomBiosArg.val = 0x18,
292
	    RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS,
293
				   ATOMBIOS_GET_CODE_DATA_TABLE,
294
				   &atomBiosArg) == ATOM_SUCCESS) {
295
	    struct AtomDacCodeTableData *data
296
		= (struct AtomDacCodeTableData *)atomBiosArg.CommandDataTable.loc;
297
	    if (atomBiosArg.CommandDataTable.size
298
		< (sizeof (struct AtomDacCodeTableData) >> (dac ? 0 : 1))) { /* IGPs only have 1 DAC -> table_size / 2 */
299
		xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
300
			   "Code table data size: %i doesn't match expected size: %u\n",
301
			   atomBiosArg.CommandDataTable.size,
302
			   (unsigned int) sizeof (struct AtomDacCodeTableData));
303
		return;
304
	    }
305
	    RHDDebug(rhdPtr->scrnIndex, "%s: WhiteFine found in Code Table.\n",__func__);
306
	    switch (type) {
307
		case TvPAL:
308
		    w_f = dac ? data->DAC2PALWhiteFine : data->DAC1PALWhiteFine;
309
		    b_g = dac ? data->DAC2PALBandGap : data->DAC1PALBandGap;
310
		    break;
311
		case TvNTSC:
312
		    w_f = dac ? data->DAC2NTSCWhiteFine : data->DAC1NTSCWhiteFine;
313
		    b_g = dac ? data->DAC2NTSCBandGap : data->DAC1NTSCBandGap;
314
		    break;
315
		case TvCV:
316
		    w_f = dac ? data->DAC2CVWhiteFine : data->DAC1CVWhiteFine;
317
		    b_g = dac ? data->DAC2CVBandGap : data->DAC1CVBandGap;
318
		    break;
319
		case VGA:
320
		    w_f = dac ? data->DAC2VGAWhiteFine : data->DAC1VGAWhiteFine;
321
		    b_g = dac ? data->DAC2VGABandGap : data->DAC1VGABandGap;
322
		    break;
323
	    }
324
	    *whitefine = w_f;
325
	    if (rhdPtr->ChipSet >= RHD_RV770)  /* Dunno why this is broken on older ASICs */
326
		*bandgap = b_g;
327
	}
328
    }
329
#endif
330
    if (*bandgap == 0 || *whitefine == 0) {
331
	int i = 0;
332
	while (list[i].pciIdMin != 0) {
333
	    if (list[i].pciIdMin <= rhdPtr->PciDeviceID
334
		&& list[i].pciIdMax >= rhdPtr->PciDeviceID) {
335
#if 0
336
		ErrorF(">> %x %x %x -- %x %x\n",list[i].pciIdMin,
337
		       rhdPtr->PciDeviceID,list[i].pciIdMax,
338
		       list[i].bandgap[dac][type],list[i].whitefine[dac][type]);
339
		ErrorF(">> %i %i\n",dac,type);
340
#endif
341
		if (*bandgap == 0) *bandgap = list[i].bandgap[dac][type];
342
		if (*whitefine == 0) *whitefine = list[i].whitefine[dac][type];
343
		break;
344
	    }
345
	    i++;
346
	}
347
	if (list[i].pciIdMin != 0)
348
	    RHDDebug(rhdPtr->scrnIndex, "%s: BandGap and WhiteFine found in Table.\n",__func__);
349
    }
350
    RHDDebug(rhdPtr->scrnIndex, "%s: DAC[%i] BandGap: 0x%2.2x WhiteFine: 0x%2.2x\n",
351
	     __func__, dac, *bandgap, *whitefine);
352
}
353
 
354
/*
355
 *
356
 */
357
static inline void
358
DACSet(struct rhdOutput *Output, CARD16 offset)
359
{
360
    RHDPtr rhdPtr = RHDPTRI(Output);
361
    CARD8 Standard, WhiteFine, Bandgap;
362
    Bool TV;
363
    CARD32 Mask = 0;
364
 
365
    switch (Output->SensedType) {
366
    case RHD_SENSED_TV_SVIDEO:
367
    case RHD_SENSED_TV_COMPOSITE:
368
	/* might want to selectively enable lines based on type */
369
	TV = TRUE;
370
 
371
    switch (rhdPtr->tvMode) {
372
	case RHD_TV_NTSC:
373
	case RHD_TV_NTSCJ:
374
	    DACGetElectrical(rhdPtr, TvNTSC, offset ? 1 : 0, &Bandgap, &WhiteFine);
375
	    Standard = 1; /* NTSC */
376
	    break;
377
	case RHD_TV_PAL:
378
	case RHD_TV_PALN:
379
	case RHD_TV_PALCN:
380
	case RHD_TV_PAL60:
381
	default:
382
	    DACGetElectrical(rhdPtr, TvPAL, offset ? 1 : 0, &Bandgap, &WhiteFine);
383
	    Standard = 0; /* PAL */
384
	    break;
385
    }
386
	break;
387
 
388
	case RHD_SENSED_TV_COMPONENT:
389
	TV = TRUE;
390
	    DACGetElectrical(rhdPtr, TvCV, offset ? 1 : 0, &Bandgap, &WhiteFine);
391
	Standard = 3; /* HDTV */
392
	break;
393
 
394
	case RHD_SENSED_VGA:
395
	default:
396
	TV = FALSE;
397
	    DACGetElectrical(rhdPtr, VGA, offset ? 1 : 0, &Bandgap, &WhiteFine);
398
	Standard = 2; /* VGA */
399
	    break;
400
    }
401
    if (Bandgap) Mask |= 0xFF << 16;
402
    if (WhiteFine) Mask |= 0xFF << 8;
403
 
404
    RHDRegMask(Output, offset + DACA_CONTROL1, Standard, 0x000000FF);
405
    /* white level fine adjust */
406
    RHDRegMask(Output, offset + DACA_CONTROL1, (Bandgap << 16) | (WhiteFine << 8), Mask);
407
 
408
    if (TV) {
409
	/* tv enable */
410
	if (offset) /* TV mux only available on DACB */
411
	    RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000100, 0x0000FF00);
412
	/* select tv encoder */
413
	RHDRegMask(Output, offset + DACA_SOURCE_SELECT, 0x00000002, 0x00000003);
414
    } else {
415
	if (offset) /* TV mux only available on DACB */
416
	    RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x0000FF00);
417
	/* select a crtc */
418
	RHDRegMask(Output, offset + DACA_SOURCE_SELECT, Output->Crtc->Id & 0x01, 0x00000003);
419
    }
420
 
421
    RHDRegMask(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0x00000701, 0x00000701);
422
    RHDRegMask(Output, offset + DACA_FORCE_DATA, 0, 0x0000FFFF);
423
}
424
 
425
/*
426
 *
427
 */
428
static void
429
DACASet(struct rhdOutput *Output, DisplayModePtr unused)
430
{
431
    RHDFUNC(Output);
432
 
433
    DACSet(Output, REG_DACA_OFFSET);
434
}
435
 
436
/*
437
 *
438
 */
439
static void
440
DACBSet(struct rhdOutput *Output, DisplayModePtr unused)
441
{
442
    RHDFUNC(Output);
443
 
444
    DACSet(Output, REG_DACB_OFFSET);
445
}
446
 
447
/*
448
 *
449
 */
450
static inline void
451
DACPower(struct rhdOutput *Output, CARD16 offset, int Power)
452
{
453
    CARD32 powerdown;
454
 
455
    RHDDebug(Output->scrnIndex, "%s(%s,%s)\n",__func__,Output->Name,
456
	     rhdPowerString[Power]);
457
 
458
    switch (Power) {
459
    case RHD_POWER_ON:
460
	switch (Output->SensedType) {
461
	    case RHD_SENSED_TV_SVIDEO:
462
		powerdown = 0 /* 0x100 */;
463
		break;
464
	    case RHD_SENSED_TV_COMPOSITE:
465
		powerdown = 0 /* 0x1010000 */;
466
		break;
467
	    case RHD_SENSED_TV_COMPONENT:
468
	    powerdown = 0;
469
		break;
470
	    case RHD_SENSED_VGA:
471
	    default:
472
		powerdown = 0;
473
		break;
474
	}
475
 	RHDRegWrite(Output, offset + DACA_ENABLE, 1);
476
      RHDRegWrite(Output, offset + DACA_POWERDOWN, 0);
477
	usleep (14);
478
	RHDRegMask(Output,  offset + DACA_POWERDOWN, powerdown, 0xFFFFFF00);
479
	usleep(2);
480
	RHDRegWrite(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0);
481
	RHDRegMask(Output,  offset + DACA_SYNC_SELECT, 0, 0x00000101);
482
	RHDRegWrite(Output, offset + DACA_SYNC_TRISTATE_CONTROL, 0);
483
      return;
484
    case RHD_POWER_RESET: /* don't bother */
485
      return;
486
    case RHD_POWER_SHUTDOWN:
487
    default:
488
	RHDRegMask(Output, offset + DACA_FORCE_DATA, 0, 0x0000FFFF);
489
	RHDRegMask(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0x0000701, 0x0000701);
490
	RHDRegWrite(Output, offset + DACA_POWERDOWN, 0x01010100);
491
      RHDRegWrite(Output, offset + DACA_POWERDOWN, 0x01010101);
492
      RHDRegWrite(Output, offset + DACA_ENABLE, 0);
493
 	RHDRegWrite(Output, offset + DACA_ENABLE, 0);
494
      return;
495
  }
496
}
497
 
498
/*
499
 *
500
 */
501
static void
502
DACAPower(struct rhdOutput *Output, int Power)
503
{
504
    RHDFUNC(Output);
505
 
506
    DACPower(Output, REG_DACA_OFFSET, Power);
507
}
508
 
509
/*
510
 *
511
 */
512
static void
513
DACBPower(struct rhdOutput *Output, int Power)
514
{
515
    RHDFUNC(Output);
516
 
517
    DACPower(Output, REG_DACB_OFFSET, Power);
518
}
519
 
520
/*
521
 *
522
 */
523
static inline void
524
DACSave(struct rhdOutput *Output, CARD16 offset)
525
{
526
    struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private;
527
 
528
    Private->Store_Powerdown = RHDRegRead(Output, offset + DACA_POWERDOWN);
529
    Private->Store_Force_Output_Control = RHDRegRead(Output, offset + DACA_FORCE_OUTPUT_CNTL);
530
    Private->Store_Force_Data = RHDRegRead(Output, offset + DACA_FORCE_DATA);
531
    Private->Store_Source_Select = RHDRegRead(Output, offset + DACA_SOURCE_SELECT);
532
    Private->Store_Sync_Select = RHDRegRead(Output, offset + DACA_SYNC_SELECT);
533
    Private->Store_Enable = RHDRegRead(Output, offset + DACA_ENABLE);
534
    Private->Store_Control1 = RHDRegRead(Output, offset + DACA_CONTROL1);
535
    Private->Store_Control2 = RHDRegRead(Output, offset + DACA_CONTROL2);
536
    Private->Store_Tristate_Control = RHDRegRead(Output, offset + DACA_SYNC_TRISTATE_CONTROL);
537
 
538
    Private->Stored = TRUE;
539
}
540
 
541
/*
542
 *
543
 */
544
static void
545
DACASave(struct rhdOutput *Output)
546
{
547
    RHDFUNC(Output);
548
 
549
    DACSave(Output, REG_DACA_OFFSET);
550
}
551
 
552
/*
553
 *
554
 */
555
static void
556
DACBSave(struct rhdOutput *Output)
557
{
558
    RHDFUNC(Output);
559
 
560
    DACSave(Output, REG_DACB_OFFSET);
561
}
562
 
563
/*
564
 *
565
 */
566
static inline void
567
DACRestore(struct rhdOutput *Output, CARD16 offset)
568
{
569
    struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private;
570
 
571
    RHDRegWrite(Output, offset + DACA_POWERDOWN, Private->Store_Powerdown);
572
    RHDRegWrite(Output, offset + DACA_FORCE_OUTPUT_CNTL, Private->Store_Force_Output_Control);
573
    RHDRegWrite(Output, offset + DACA_FORCE_DATA, Private->Store_Force_Data);
574
    RHDRegWrite(Output, offset + DACA_SOURCE_SELECT, Private->Store_Source_Select);
575
    RHDRegWrite(Output, offset + DACA_SYNC_SELECT, Private->Store_Sync_Select);
576
    RHDRegWrite(Output, offset + DACA_ENABLE, Private->Store_Enable);
577
    RHDRegWrite(Output, offset + DACA_CONTROL1, Private->Store_Control1);
578
    RHDRegWrite(Output, offset + DACA_CONTROL2, Private->Store_Control2);
579
    RHDRegWrite(Output, offset + DACA_SYNC_TRISTATE_CONTROL, Private->Store_Tristate_Control);
580
}
581
 
582
/*
583
 *
584
 */
585
static void
586
DACARestore(struct rhdOutput *Output)
587
{
588
  RHDFUNC(Output);
589
 
590
    if (!((struct rhdDACPrivate *) Output->Private)->Stored) {
591
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
592
		   "%s: No registers stored.\n", __func__);
593
    return;
594
  }
595
 
596
  DACRestore(Output, REG_DACA_OFFSET);
597
}
598
 
599
/*
600
 *
601
 */
602
static void
603
DACBRestore(struct rhdOutput *Output)
604
{
605
    RHDFUNC(Output);
606
 
607
    if (!((struct rhdDACPrivate *) Output->Private)->Stored) {
608
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
609
		   "%s: No registers stored.\n", __func__);
610
	return;
611
    }
612
 
613
    DACRestore(Output, REG_DACB_OFFSET);
614
}
615
 
616
/* ----------------------------------------------------------- */
617
 
618
/*
619
 *
620
 */
621
static CARD32
622
DACSenseRV620(struct rhdOutput *Output, CARD32 offset, Bool TV)
623
{
624
    CARD32 ret;
625
    CARD32 DetectControl, AutodetectIntCtl, ForceData,
626
	Control1, Control2, CompEnable;
627
 
628
    RHDFUNC(Output);
629
 
630
    Control1 = RHDRegRead(Output, offset + RV620_DACA_MACRO_CNTL); /* 7ef4 */
631
    Control2 = RHDRegRead(Output, offset + RV620_DACA_CONTROL2); /* 7058 */
632
    ForceData = RHDRegRead(Output, offset + RV620_DACA_FORCE_DATA);
633
    AutodetectIntCtl = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL);
634
    DetectControl = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_CONTROL);
635
    CompEnable = RHDRegRead(Output, offset + RV620_DACA_COMPARATOR_ENABLE);
636
 
637
    if (offset) {  /* We can do TV on DACA but only DACB has mux for separate connector */
638
    if (TV)
639
	RHDRegMask(Output, offset + RV620_DACA_CONTROL2, 0x100, 0xff00);
640
    else
641
	RHDRegMask(Output, offset + RV620_DACA_CONTROL2, 0x00, 0xff00);
642
    }
643
    RHDRegMask(Output, offset + RV620_DACA_FORCE_DATA, 0x18, 0xffff);
644
    RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01);
645
    RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_CONTROL, 0x00, 0xff);
646
    RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL,
647
	       (offset > 0) ? 0x2502 :  0x2002, 0xffff);
648
    /* enable comparators for R/G/B, disable DDET and SDET reference */
649
    RHDRegMask(Output, offset + RV620_DACA_COMPARATOR_ENABLE, 0x70000, 0x070101);
650
    RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_CONTROL, 0x01, 0xff);
651
    usleep(32);
652
    ret = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_STATUS);
653
    RHDRegWrite(Output, offset + RV620_DACA_AUTODETECT_CONTROL, DetectControl);
654
    RHDRegWrite(Output, offset + RV620_DACA_MACRO_CNTL, Control1);
655
    RHDRegWrite(Output, offset + RV620_DACA_CONTROL2, Control2);
656
    RHDRegWrite(Output, offset + RV620_DACA_FORCE_DATA, ForceData);
657
    RHDRegWrite(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL, AutodetectIntCtl);
658
#ifdef DEBUG
659
    RHDDebug(Output->scrnIndex, "DAC%i: ret = 0x%x %s\n",offset ? "A" : "B",
660
	     ret,TV ? "TV" : "");
661
#endif
662
    return ret;
663
}
664
 
665
/*
666
 *
667
 */
668
static enum rhdSensedOutput
669
DACASenseRV620(struct rhdOutput *Output, struct rhdConnector *Connector)
670
{
671
    enum rhdConnectorType Type = Connector->Type;
672
    RHDFUNC(Output);
673
 
674
    switch (Type) {
675
    case RHD_CONNECTOR_DVI:
676
    case RHD_CONNECTOR_DVI_SINGLE:
677
    case RHD_CONNECTOR_VGA:
678
	return  (DACSenseRV620(Output, RV620_REG_DACA_OFFSET, FALSE)
679
		  & 0x1010100) ? RHD_SENSED_VGA : RHD_SENSED_NONE;
680
    case RHD_CONNECTOR_TV:
681
	switch (DACSenseRV620(Output, RV620_REG_DACA_OFFSET, TRUE)
682
		& 0x1010100) {
683
	    case 0x1010100:
684
		return RHD_SENSED_NONE; /* on DAC A we cannot distinguish VGA and CV */
685
	    case 0x10100:
686
		return RHD_SENSED_TV_SVIDEO;
687
	    case 0x1000000:
688
		return RHD_SENSED_TV_COMPOSITE;
689
	    default:
690
		return RHD_SENSED_NONE;
691
	}
692
    default:
693
	xf86DrvMsg(Output->scrnIndex, X_WARNING,
694
		   "%s: connector type %d is not supported.\n",
695
		   __func__, Type);
696
	return RHD_SENSED_NONE;
697
    }
698
}
699
 
700
/*
701
 *
702
 */
703
static enum rhdSensedOutput
704
DACBSenseRV620(struct rhdOutput *Output, struct rhdConnector *Connector)
705
{
706
    enum rhdConnectorType Type = Connector->Type;
707
    RHDFUNC(Output);
708
 
709
    switch (Type) {
710
    case RHD_CONNECTOR_DVI:
711
    case RHD_CONNECTOR_DVI_SINGLE:
712
    case RHD_CONNECTOR_VGA:
713
	return  (DACSenseRV620(Output, RV620_REG_DACB_OFFSET, FALSE)
714
		  & 0x1010100) ? RHD_SENSED_VGA : RHD_SENSED_NONE;
715
    case RHD_CONNECTOR_TV:
716
	switch (DACSenseRV620(Output, RV620_REG_DACB_OFFSET, TRUE)
717
		& 0x1010100) {
718
	    case 0x1000000:
719
		return RHD_SENSED_TV_COMPONENT;
720
	    case 0x1010100:
721
		return RHD_SENSED_TV_SVIDEO;
722
	    case 0x10100:
723
		return RHD_SENSED_TV_COMPOSITE;
724
	    default:
725
		return RHD_SENSED_NONE;
726
	}
727
    default:
728
	xf86DrvMsg(Output->scrnIndex, X_WARNING,
729
		   "%s: connector type %d is not supported.\n",
730
		   __func__, Type);
731
	return RHD_SENSED_NONE;
732
    }
733
}
734
 
735
/*
736
 *
737
 */
738
static inline void
739
DACSetRV620(struct rhdOutput *Output, CARD16 offset)
740
{
741
    RHDPtr rhdPtr = RHDPTRI(Output);
742
    CARD32 Source;
743
    CARD32 Mode;
744
    CARD32 TV;
745
    CARD8 WhiteFine, Bandgap;
746
    CARD32 Mask = 0;
747
 
748
    switch (Output->SensedType) {
749
	case RHD_SENSED_TV_SVIDEO:
750
	case RHD_SENSED_TV_COMPOSITE:
751
	    TV = 0x1;
752
	    Source = 0x2; /* tv encoder */
753
    switch (rhdPtr->tvMode) {
754
	case RHD_TV_NTSC:
755
	case RHD_TV_NTSCJ:
756
		    DACGetElectrical(rhdPtr, TvNTSC, offset ? 1 : 0, &Bandgap, &WhiteFine);
757
		    Mode = 1;
758
	    break;
759
	case RHD_TV_PAL:
760
	case RHD_TV_PALN:
761
	case RHD_TV_PALCN:
762
	case RHD_TV_PAL60:
763
	default:
764
		    DACGetElectrical(rhdPtr, TvPAL, offset ? 1 : 0, &Bandgap, &WhiteFine);
765
		    Mode = 0;
766
	    break;
767
    }
768
	    break;
769
	case RHD_SENSED_TV_COMPONENT:
770
	    DACGetElectrical(rhdPtr, TvCV, offset ? 1 : 0, &Bandgap, &WhiteFine);
771
	    Mode = 3; /* HDTV */
772
	    TV = 0x1; /* tv on?? */
773
	    Source = 0x2; /* tv encoder  ?? */
774
	    break;
775
	case RHD_SENSED_VGA:
776
	default:
777
	    DACGetElectrical(rhdPtr, VGA, offset ? 1 : 0, &Bandgap, &WhiteFine);
778
	    Mode = 2;
779
	    TV = 0;
780
	    Source = Output->Crtc->Id;
781
	    break;
782
    }
783
    if (Bandgap) Mask |= 0xFF << 16;
784
    if (WhiteFine) Mask |= 0xFF << 8;
785
 
786
    RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL, Mode, 0xFF); /* no fine control yet */
787
    RHDRegMask(Output,  offset + RV620_DACA_SOURCE_SELECT, Source, 0x00000003);
788
    if (offset) /* TV mux only present on DACB */
789
	RHDRegMask(Output,  offset + RV620_DACA_CONTROL2, TV << 8, 0x0100); /* tv enable/disable */
790
    /* use fine control from white_fine control register */
791
    RHDRegMask(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL, 0x0, 0x4);
792
    RHDRegMask(Output, offset + RV620_DACA_BGADJ_SRC, 0x0, 0x30);
793
    RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL, (Bandgap << 16) | (WhiteFine << 8), Mask);
794
    /* Reset the FMT register on CRTC leading to this output */
795
    Output->Crtc->FMTModeSet(Output->Crtc, NULL);
796
}
797
 
798
/*
799
 *
800
 */
801
static void
802
DACASetRV620(struct rhdOutput *Output, DisplayModePtr unused)
803
{
804
    RHDFUNC(Output);
805
 
806
    DACSetRV620(Output, RV620_REG_DACA_OFFSET);
807
}
808
 
809
/*
810
 *
811
 */
812
static void
813
DACBSetRV620(struct rhdOutput *Output, DisplayModePtr unused)
814
{
815
    RHDFUNC(Output);
816
 
817
    DACSetRV620(Output, RV620_REG_DACB_OFFSET);
818
}
819
 
820
/*
821
 *
822
 */
823
static inline void
824
DACPowerRV620(struct rhdOutput *Output, CARD16 offset, int Power)
825
{
826
    CARD32 powerdown;
827
 
828
    switch (Power) {
829
	case RHD_POWER_ON:
830
	    switch (Output->SensedType) {
831
		case RHD_SENSED_TV_SVIDEO:
832
		    powerdown = 0 /* 0x100 */;
833
		    break;
834
		case RHD_SENSED_TV_COMPOSITE:
835
		    powerdown = 0 /* 0x1010000 */;
836
		    break;
837
		case RHD_SENSED_TV_COMPONENT:
838
		    powerdown = 0;
839
		    break;
840
		case RHD_SENSED_VGA:
841
		default:
842
		    powerdown = 0;
843
		    break;
844
	    }
845
 
846
	    if (!(RHDRegRead(Output, offset + RV620_DACA_ENABLE) & 0x01))
847
		RHDRegMask(Output, offset + RV620_DACA_ENABLE, 0x1, 0xff);
848
	    RHDRegMask(Output,  offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x01, 0x01);
849
	    RHDRegMask(Output,  offset + RV620_DACA_POWERDOWN, 0x0, 0xff);
850
	    usleep (0x14);
851
	    RHDRegMask(Output,  offset + RV620_DACA_POWERDOWN, powerdown, 0xffffff00);
852
	    usleep(2);
853
	    RHDRegMask(Output,  offset + RV620_DACA_FORCE_DATA, 0, 0x0000ffff);
854
	    RHDRegWrite(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x0);
855
	    RHDRegWrite(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL, 0);
856
	    return;
857
	case RHD_POWER_RESET: /* don't bother */
858
	    return;
859
	case RHD_POWER_SHUTDOWN:
860
	default:
861
	    RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, 0x01010100);
862
	    RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, 0x01010101);
863
	    RHDRegWrite(Output, offset + RV620_DACA_ENABLE, 0);
864
	    RHDRegMask(Output, offset + RV620_DACA_FORCE_DATA, 0, 0xffff);
865
	    RHDRegMask(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x701, 0x701);
866
	    return;
867
    }
868
}
869
 
870
/*
871
 *
872
 */
873
static void
874
DACAPowerRV620(struct rhdOutput *Output, int Power)
875
{
876
    RHDFUNC(Output);
877
 
878
    DACPowerRV620(Output, RV620_REG_DACA_OFFSET, Power);
879
}
880
 
881
/*
882
 *
883
 */
884
static void
885
DACBPowerRV620(struct rhdOutput *Output, int Power)
886
{
887
    RHDFUNC(Output);
888
 
889
    DACPowerRV620(Output, RV620_REG_DACB_OFFSET, Power);
890
}
891
 
892
/*
893
 *
894
 */
895
static inline void
896
DACSaveRV620(struct rhdOutput *Output, CARD16 offset)
897
{
898
    struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private;
899
 
900
    Private->Store_Powerdown = RHDRegRead(Output, offset + RV620_DACA_POWERDOWN);
901
    Private->Store_Force_Output_Control = RHDRegRead(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL);
902
    Private->Store_Force_Data = RHDRegRead(Output, offset + RV620_DACA_FORCE_DATA);
903
    Private->Store_Source_Select = RHDRegRead(Output, offset + RV620_DACA_SOURCE_SELECT);
904
    Private->Store_Enable = RHDRegRead(Output, offset + RV620_DACA_ENABLE);
905
    Private->Store_Control1 = RHDRegRead(Output, offset + RV620_DACA_MACRO_CNTL);
906
    Private->Store_Control2 = RHDRegRead(Output, offset + RV620_DACA_CONTROL2);
907
    Private->Store_Tristate_Control = RHDRegRead(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL);
908
    Private->Store_Auto_Calib_Control = RHDRegRead(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL);
909
    Private->Store_Dac_Bgadj_Src = RHDRegRead(Output, offset + RV620_DACA_BGADJ_SRC);
910
 
911
    Private->Stored = TRUE;
912
}
913
 
914
/*
915
 *
916
 */
917
static void
918
DACASaveRV620(struct rhdOutput *Output)
919
{
920
    RHDFUNC(Output);
921
 
922
    DACSaveRV620(Output, RV620_REG_DACA_OFFSET);
923
}
924
 
925
/*
926
 *
927
 */
928
static void
929
DACBSaveRV620(struct rhdOutput *Output)
930
{
931
    RHDFUNC(Output);
932
 
933
    DACSaveRV620(Output, RV620_REG_DACB_OFFSET);
934
}
935
 
936
/*
937
 *
938
 */
939
static inline void
940
DACRestoreRV620(struct rhdOutput *Output, CARD16 offset)
941
{
942
    struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private;
943
 
944
    RHDRegWrite(Output, offset + RV620_DACA_BGADJ_SRC, Private->Store_Dac_Bgadj_Src);
945
    RHDRegWrite(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL, Private->Store_Auto_Calib_Control);
946
    RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, Private->Store_Powerdown);
947
    RHDRegWrite(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, Private->Store_Force_Output_Control);
948
    RHDRegWrite(Output, offset + RV620_DACA_FORCE_DATA, Private->Store_Force_Data);
949
    RHDRegWrite(Output, offset + RV620_DACA_SOURCE_SELECT, Private->Store_Source_Select);
950
    RHDRegWrite(Output, offset + RV620_DACA_ENABLE, Private->Store_Enable);
951
    RHDRegWrite(Output, offset + RV620_DACA_MACRO_CNTL, Private->Store_Control1);
952
    RHDRegWrite(Output, offset + RV620_DACA_CONTROL2, Private->Store_Control2);
953
    RHDRegWrite(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL, Private->Store_Tristate_Control);
954
 
955
}
956
 
957
/*
958
 *
959
 */
960
static void
961
DACARestoreRV620(struct rhdOutput *Output)
962
{
963
    RHDFUNC(Output);
964
 
965
    if (!((struct rhdDACPrivate *) Output->Private)->Stored) {
966
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
967
		   "%s: No registers stored.\n", __func__);
968
	return;
969
    }
970
    DACRestoreRV620(Output, RV620_REG_DACA_OFFSET);
971
}
972
 
973
/*
974
 *
975
 */
976
static void
977
DACBRestoreRV620(struct rhdOutput *Output)
978
{
979
    RHDFUNC(Output);
980
 
981
    if (!((struct rhdDACPrivate *) Output->Private)->Stored) {
982
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
983
		   "%s: No registers stored.\n", __func__);
984
	return;
985
    }
986
 
987
    DACRestoreRV620(Output, RV620_REG_DACB_OFFSET);
988
}
989
 
990
/* ----------------------------------------------------------- */
991
 
992
/*
993
 *
994
 */
995
static ModeStatus
996
DACModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
997
{
998
    RHDFUNC(Output);
999
 
1000
    if (Mode->Clock < 20000)
1001
	return MODE_CLOCK_LOW;
1002
 
1003
    if (Mode->Clock > 400000)
1004
	return MODE_CLOCK_HIGH;
1005
 
1006
    return MODE_OK;
1007
}
1008
 
1009
/*
1010
 *
1011
 */
1012
static void
1013
DACDestroy(struct rhdOutput *Output)
1014
{
1015
    RHDFUNC(Output);
1016
 
1017
    if (!Output->Private)
1018
	return;
1019
 
1020
    xfree(Output->Private);
1021
    Output->Private = NULL;
1022
}
1023
 
1024
/*
1025
 *
1026
 */
1027
struct rhdOutput *
1028
RHDDACAInit(RHDPtr rhdPtr)
1029
{
1030
    struct rhdOutput *Output;
1031
    struct rhdDACPrivate *Private;
1032
 
1033
    RHDFUNC(rhdPtr);
1034
 
1035
    Output = xnfcalloc(sizeof(struct rhdOutput), 1);
1036
 
1037
    Output->scrnIndex = rhdPtr->scrnIndex;
1038
    Output->Name = "DAC A";
1039
    Output->Id = RHD_OUTPUT_DACA;
1040
 
1041
    if (rhdPtr->ChipSet < RHD_RV620) {
1042
	Output->Sense = DACASense;
1043
    Output->Mode = DACASet;
1044
    Output->Power = DACAPower;
1045
    Output->Save = DACASave;
1046
    Output->Restore = DACARestore;
1047
    } else {
1048
	Output->Sense = DACASenseRV620;
1049
	Output->Mode = DACASetRV620;
1050
	Output->Power = DACAPowerRV620;
1051
	Output->Save = DACASaveRV620;
1052
	Output->Restore = DACARestoreRV620;
1053
    }
1054
    Output->ModeValid = DACModeValid;
1055
    Output->Destroy = DACDestroy;
1056
    Private = xnfcalloc(sizeof(struct rhdDACPrivate), 1);
1057
    Output->Private = Private;
1058
 
1059
    return Output;
1060
}
1061
 
1062
/*
1063
 *
1064
 */
1065
struct rhdOutput *
1066
RHDDACBInit(RHDPtr rhdPtr)
1067
{
1068
    struct rhdOutput *Output;
1069
    struct rhdDACPrivate *Private;
1070
 
1071
    RHDFUNC(rhdPtr);
1072
 
1073
    Output = xnfcalloc(sizeof(struct rhdOutput), 1);
1074
 
1075
    Output->scrnIndex = rhdPtr->scrnIndex;
1076
    Output->Name = "DAC B";
1077
    Output->Id = RHD_OUTPUT_DACB;
1078
 
1079
    if (rhdPtr->ChipSet < RHD_RV620) {
1080
	Output->Sense = DACBSense;
1081
    Output->Mode = DACBSet;
1082
    Output->Power = DACBPower;
1083
    Output->Save = DACBSave;
1084
    Output->Restore = DACBRestore;
1085
    } else {
1086
	Output->Sense = DACBSenseRV620;
1087
	Output->Mode = DACBSetRV620;
1088
	Output->Power = DACBPowerRV620;
1089
	Output->Save = DACBSaveRV620;
1090
	Output->Restore = DACBRestoreRV620;
1091
    }
1092
    Output->ModeValid = DACModeValid;
1093
    Output->Destroy = DACDestroy;
1094
 
1095
    Private = xnfcalloc(sizeof(struct rhdDACPrivate), 1);
1096
    Output->Private = Private;
1097
 
1098
    return Output;
1099
}