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  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
 
30
#ifdef ATOM_BIOS
31
# include "xf86.h"
32
#include "rhd.h"
33
 
34
# include "edid.h"
35
 
36
# include "xf86DDC.h"
37
 
38
# if HAVE_XF86_ANSIC_H
39
#  include "xf86_ansic.h"
40
# else
41
#  include 
42
#  include 
43
#  include 
44
# endif
45
 
46
 
47
 
48
# include "rhd_atombios.h"
49
 
50
# include "rhd_connector.h"
51
# include "rhd_output.h"
52
# include "rhd_biosscratch.h"
53
# include "rhd_crtc.h"
54
# include "rhd_card.h"
55
 
56
# ifdef ATOM_BIOS_PARSER
57
#  define INT8 INT8
58
#  define INT16 INT16
59
#  define INT32 INT32
60
#  include "CD_Common_Types.h"
61
# else
62
#  ifndef ULONG
63
typedef unsigned int ULONG;
64
#   define ULONG ULONG
65
#  endif
66
#  ifndef UCHAR
67
typedef unsigned char UCHAR;
68
#   define UCHAR UCHAR
69
#  endif
70
#  ifndef USHORT
71
typedef unsigned short USHORT;
72
#   define USHORT USHORT
73
#  endif
74
# endif
75
 
76
# include "atombios.h"
77
 
78
struct rhdOutputDevices {
79
    enum atomDevice DeviceId;
80
    enum rhdConnectorType ConnectorType;
81
};
82
 
83
#if defined (ATOM_BIOS_PARSER)
84
/*
85
 *
86
 */
87
static enum rhdSensedOutput
88
rhdAtomBIOSScratchDACSenseResults(struct rhdOutput *Output, enum atomDAC DAC, enum atomDevice Device)
89
{
90
    RHDPtr rhdPtr = RHDPTRI(Output);
91
    CARD32 BIOS_0;
92
    Bool TV = FALSE;
93
 
94
    RHDFUNC(Output);
95
 
96
    if (rhdPtr->ChipSet < RHD_R600)
97
	BIOS_0 = RHDRegRead(Output, 0x10);
98
    else
99
	BIOS_0 = RHDRegRead(Output, 0x1724);
100
 
101
    switch (Device) {
102
    	case atomNone:
103
	case atomCRT2:
104
    	case atomCRT1:
105
	case atomLCD1:
106
	case atomLCD2:
107
	case atomDFP1:
108
	case atomDFP2:
109
	case atomDFP3:
110
	case atomDFP4:
111
	case atomDFP5:
112
	    TV = FALSE;
113
	    break;
114
	case atomTV1:
115
	case atomTV2:
116
	case atomCV:
117
	    TV = TRUE;
118
	    break;
119
    }
120
 
121
    RHDDebug(Output->scrnIndex, "BIOSScratch_0: 0x%4.4x\n",BIOS_0);
122
 
123
    switch (DAC) {
124
	case atomDACA:
125
	    break;
126
	case atomDACB:
127
	    BIOS_0 >>= 8;
128
	    break;
129
	case atomDACExt:
130
	    return RHD_SENSED_NONE;
131
    }
132
 
133
    if (!TV) {
134
	if (BIOS_0 & ATOM_S0_CRT1_MASK) {
135
	    RHDDebug(Output->scrnIndex, "%s sensed RHD_SENSED_VGA\n",__func__);
136
	    return RHD_SENSED_VGA;
137
	}
138
    } else {
139
	if (BIOS_0 & ATOM_S0_TV1_COMPOSITE_A) {
140
	    RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPOSITE\n",__func__);
141
	    return RHD_SENSED_TV_COMPOSITE;
142
	} else if (BIOS_0 & ATOM_S0_TV1_SVIDEO_A) {
143
	    RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_SVIDE\n",__func__);
144
	    return RHD_SENSED_TV_SVIDEO;
145
	} else if (BIOS_0 & ATOM_S0_CV_MASK_A) {
146
	    RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_TV_COMPONENT\n",__func__);
147
	    return RHD_SENSED_TV_COMPONENT;
148
	}
149
    }
150
 
151
    RHDDebug(Output->scrnIndex, "%s: RHD_SENSED_NONE\n",__func__);
152
    return RHD_SENSED_NONE;
153
}
154
 
155
/*
156
 *
157
 */
158
enum rhdSensedOutput
159
RHDBIOSScratchDACSense(struct rhdOutput *Output, struct rhdConnector *Connector)
160
{
161
    RHDPtr rhdPtr = RHDPTRI(Output);
162
    enum atomDAC DAC;
163
    Bool ret;
164
    Bool TV;
165
    enum atomDevice Device;
166
    enum rhdSensedOutput retVal;
167
    int i = 0;
168
 
169
    RHDFUNC(Output);
170
 
171
    if (!Output->OutputDriverPrivate)
172
	return RHD_SENSED_NONE;
173
 
174
    switch (Output->Id) {
175
	case RHD_OUTPUT_DACA:
176
	    RHDDebug(Output->scrnIndex, "Sensing DACA on Output %s\n",Output->Name);
177
	    DAC = atomDACA;
178
	    break;
179
	case RHD_OUTPUT_DACB:
180
	    RHDDebug(Output->scrnIndex, "Sensing DACB on Output %s\n",Output->Name);
181
	    DAC = atomDACB;
182
	    break;
183
	default:
184
	    return FALSE;
185
    }
186
 
187
    switch (Connector->Type) {
188
	case RHD_CONNECTOR_DVI:
189
	case RHD_CONNECTOR_DVI_SINGLE:
190
	case RHD_CONNECTOR_VGA:
191
	    TV = FALSE;
192
	    break;
193
	default:
194
	    TV = TRUE;
195
    }
196
 
197
    while ((Device = Output->OutputDriverPrivate->OutputDevices[i++].DeviceId) != atomNone) {
198
	switch (Device) {
199
	    case atomCRT1:
200
	    case atomCRT2:
201
		if (TV)
202
		    continue;
203
		break;
204
	    case atomTV1:
205
	    case atomTV2:
206
	    case atomCV:
207
		if (!TV)
208
		    continue;
209
		break;
210
	    default: /* should not get here */
211
		return RHD_SENSED_NONE;
212
	}
213
 
214
	ret = AtomDACLoadDetection(rhdPtr->atomBIOS, Device, DAC);
215
 
216
	if (!ret)
217
	    continue;
218
 
219
	if ((retVal =  rhdAtomBIOSScratchDACSenseResults(Output, DAC, Device)) != RHD_SENSED_NONE)
220
	    return retVal;
221
    }
222
    return RHD_SENSED_NONE;
223
}
224
# endif /* ATOM_BIOS_PARSER */
225
/*
226
 *
227
 */
228
static void
229
rhdAtomBIOSScratchUpdateAttachedState(RHDPtr rhdPtr, enum atomDevice dev, Bool attached)
230
{
231
    CARD32 BIOS_0;
232
    CARD32 Addr;
233
    CARD32 Mask;
234
 
235
    RHDFUNC(rhdPtr);
236
 
237
    if (rhdPtr->ChipSet < RHD_R600)
238
	Addr = 0x10;
239
    else
240
	Addr = 0x1724;
241
 
242
    BIOS_0 = RHDRegRead(rhdPtr, Addr);
243
 
244
    switch (dev) {
245
	case atomDFP1:
246
	    Mask = ATOM_S0_DFP1;
247
	    break;
248
	case atomDFP2:
249
	    Mask = ATOM_S0_DFP2;
250
	    break;
251
	case atomLCD1:
252
	    Mask = ATOM_S0_LCD1;
253
	    break;
254
	case atomLCD2:
255
	    Mask = ATOM_S0_LCD2;
256
	    break;
257
	case atomTV2:
258
	    Mask = ATOM_S0_TV2;
259
	    break;
260
	case atomDFP3:
261
	    Mask = ATOM_S0_DFP3;
262
	    break;
263
	case atomDFP4:
264
	    Mask = ATOM_S0_DFP4;
265
	    break;
266
	case atomDFP5:
267
	    Mask = ATOM_S0_DFP5;
268
	    break;
269
	default:
270
	    return;
271
    }
272
    if (attached)
273
	BIOS_0 |= Mask;
274
    else
275
	BIOS_0 &= ~Mask;
276
 
277
    RHDRegWrite(rhdPtr, Addr, BIOS_0);
278
}
279
 
280
/*
281
 *
282
 */
283
static void
284
rhdAtomBIOSScratchUpdateOnState(RHDPtr rhdPtr, enum atomDevice dev, Bool on)
285
{
286
    CARD32 BIOS_3;
287
    CARD32 Addr;
288
    CARD32 Mask = 0;
289
 
290
    RHDFUNC(rhdPtr);
291
 
292
    if (rhdPtr->ChipSet < RHD_R600)
293
	Addr = 0x1C;
294
    else
295
	Addr = 0x1730;
296
 
297
    BIOS_3 = RHDRegRead(rhdPtr, Addr);
298
 
299
    switch (dev) {
300
	case atomCRT1:
301
	    Mask = ATOM_S3_CRT1_ACTIVE;
302
	    break;
303
	case atomLCD1:
304
	    Mask = ATOM_S3_LCD1_ACTIVE;
305
	    break;
306
	case atomTV1:
307
	    Mask = ATOM_S3_TV1_ACTIVE;
308
	    break;
309
	case atomDFP1:
310
	    Mask =  ATOM_S3_DFP1_ACTIVE;
311
	    break;
312
	case atomCRT2:
313
	    Mask = ATOM_S3_CRT2_ACTIVE;
314
	    break;
315
	case atomLCD2:
316
	    Mask = ATOM_S3_LCD2_ACTIVE;
317
	    break;
318
	case atomTV2:
319
	    Mask = ATOM_S3_TV2_ACTIVE;
320
	    break;
321
	case atomDFP2:
322
	    Mask = ATOM_S3_DFP2_ACTIVE;
323
	    break;
324
	case  atomCV:
325
	    Mask = ATOM_S3_CV_ACTIVE;
326
	    break;
327
	case atomDFP3:
328
	    Mask = ATOM_S3_DFP3_ACTIVE;
329
	    break;
330
	case atomDFP4:
331
	    Mask = ATOM_S3_DFP4_ACTIVE;
332
	    break;
333
	case atomDFP5:
334
	    Mask = ATOM_S3_DFP5_ACTIVE;
335
	    break;
336
	case atomNone:
337
	    return;
338
    }
339
    if (on)
340
	BIOS_3 |= Mask;
341
    else
342
	BIOS_3 &= ~Mask;
343
 
344
    RHDRegWrite(rhdPtr, Addr, BIOS_3);
345
}
346
 
347
/*
348
 *
349
 */
350
void
351
RHDAtomBIOSScratchSetAccelratorMode(RHDPtr rhdPtr, Bool on)
352
{
353
    CARD32 Addr;
354
    CARD32 Mask = ATOM_S6_ACC_MODE | ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH;
355
 
356
    if (rhdPtr->ChipSet < RHD_R600)
357
	Addr = 0x10 + (6 << 2);
358
    else
359
	Addr = 0x1724 + (6 << 2);
360
 
361
    RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask);
362
}
363
 
364
/*
365
 *
366
 */
367
static void
368
rhdAtomBIOSScratchSetAcceleratorModeForDevice(RHDPtr rhdPtr,
369
					      enum atomDevice Device, Bool on)
370
{
371
    CARD32 Addr;
372
    CARD32 Mask = 0;
373
 
374
    if (rhdPtr->ChipSet < RHD_R600)
375
	Addr = 0x10 + (6 << 2);
376
    else
377
	Addr = 0x1724 + (6 << 2);
378
 
379
    switch (Device) {
380
	case atomCRT1:
381
	    Mask = ATOM_S6_ACC_REQ_CRT1;
382
	    break;
383
	case atomLCD1:
384
	    Mask = ATOM_S6_ACC_REQ_LCD1;
385
	    break;
386
	case atomTV1:
387
	    Mask = ATOM_S6_ACC_REQ_TV1;
388
	    break;
389
	case atomDFP1:
390
	    Mask = ATOM_S6_ACC_REQ_DFP1;
391
	    break;
392
	case atomCRT2:
393
	    Mask = ATOM_S6_ACC_REQ_CRT2;
394
	    break;
395
	case atomLCD2:
396
	    Mask = ATOM_S6_ACC_REQ_LCD2;
397
	    break;
398
	case atomTV2:
399
	    Mask = ATOM_S6_ACC_REQ_TV2;
400
	    break;
401
	case atomDFP2:
402
	    Mask = ATOM_S6_ACC_REQ_DFP2;
403
	    break;
404
	case  atomCV:
405
	    Mask = ATOM_S6_ACC_REQ_CV;
406
	    break;
407
	case atomDFP3:
408
	    Mask = ATOM_S6_ACC_REQ_DFP3;
409
	    break;
410
	case atomDFP4:
411
	    Mask = ATOM_S6_ACC_REQ_DFP4;
412
	    break;
413
	case atomDFP5:
414
	    Mask = ATOM_S6_ACC_REQ_DFP5;
415
	    break;
416
	case atomNone:
417
	    return;
418
    }
419
    RHDRegMask(rhdPtr, Addr, on ? Mask : 0, Mask);
420
}
421
 
422
/*
423
 *
424
 */
425
static void
426
rhdAtomBIOSScratchSetCrtcState(RHDPtr rhdPtr, enum atomDevice dev, enum atomCrtc Crtc)
427
{
428
    CARD32 BIOS_3;
429
    CARD32 Addr;
430
    CARD32 Mask = 0;
431
 
432
    RHDFUNC(rhdPtr);
433
 
434
    if (rhdPtr->ChipSet < RHD_R600)
435
	Addr = 0x1C;
436
    else
437
	Addr = 0x1730;
438
 
439
    BIOS_3 = RHDRegRead(rhdPtr, Addr);
440
 
441
    switch (dev) {
442
	case atomCRT1:
443
	    Mask = ATOM_S3_CRT1_CRTC_ACTIVE;
444
	    break;
445
	case atomLCD1:
446
	    Mask = ATOM_S3_LCD1_CRTC_ACTIVE;
447
	    break;
448
	case atomTV1:
449
	    Mask = ATOM_S3_TV1_CRTC_ACTIVE;
450
	    break;
451
	case atomDFP1:
452
	    Mask =  ATOM_S3_DFP1_CRTC_ACTIVE;
453
	    break;
454
	case atomCRT2:
455
	    Mask = ATOM_S3_CRT2_CRTC_ACTIVE;
456
	    break;
457
	case atomLCD2:
458
	    Mask = ATOM_S3_LCD2_CRTC_ACTIVE;
459
	    break;
460
	case atomTV2:
461
	    Mask = ATOM_S3_TV2_CRTC_ACTIVE;
462
	    break;
463
	case atomDFP2:
464
	    Mask = ATOM_S3_DFP2_CRTC_ACTIVE;
465
	    break;
466
	case  atomCV:
467
	    Mask = ATOM_S3_CV_CRTC_ACTIVE;
468
	    break;
469
	case atomDFP3:
470
	    Mask = ATOM_S3_DFP3_CRTC_ACTIVE;
471
	    break;
472
	case atomDFP4:
473
	    Mask = ATOM_S3_DFP4_CRTC_ACTIVE;
474
	    break;
475
	case atomDFP5:
476
	    Mask = ATOM_S3_DFP5_CRTC_ACTIVE;
477
	    break;
478
	case atomNone:
479
	    return;
480
    }
481
    if (Crtc == atomCrtc2)
482
	BIOS_3 |= Mask;
483
    else
484
	BIOS_3 &= ~Mask;
485
 
486
    RHDRegWrite(rhdPtr, Addr, BIOS_3);
487
}
488
 
489
/*
490
 *
491
 */
492
void
493
RHDAtomBIOSScratchPMState(RHDPtr rhdPtr, struct rhdOutput *Output, int PowerManagementMode)
494
{
495
    CARD32 Addr;
496
    CARD32 Mask = 0, Mask1;
497
    enum atomDevice Device = Output->OutputDriverPrivate->Device;
498
 
499
    if (rhdPtr->ChipSet < RHD_R600)
500
	Addr = 0x10 + (2 << 2);
501
    else
502
	Addr = 0x1724 + (2 << 2);
503
 
504
    switch (Device) {
505
	case atomCRT1:
506
	    Mask = ATOM_S2_CRT1_DPMS_STATE;
507
	    break;
508
	case atomLCD1:
509
	    Mask = ATOM_S2_LCD1_DPMS_STATE;
510
	    break;
511
	case atomTV1:
512
	    Mask = ATOM_S2_TV1_DPMS_STATE;
513
	    break;
514
	case atomDFP1:
515
	    Mask = ATOM_S2_DFP1_DPMS_STATE;
516
	    break;
517
	case atomCRT2:
518
	    Mask = ATOM_S2_CRT2_DPMS_STATE;
519
	    break;
520
	case atomLCD2:
521
	    Mask = ATOM_S2_LCD2_DPMS_STATE;
522
	    break;
523
	case atomTV2:
524
	    Mask = ATOM_S2_TV2_DPMS_STATE;
525
	    break;
526
	case atomDFP2:
527
	    Mask = ATOM_S2_DFP2_DPMS_STATE;
528
	    break;
529
	case  atomCV:
530
	    Mask = ATOM_S2_CV_DPMS_STATE;
531
	    break;
532
	case atomDFP3:
533
	    Mask = ATOM_S2_DFP3_DPMS_STATE;
534
	    break;
535
	case atomDFP4:
536
	    Mask = ATOM_S2_DFP4_DPMS_STATE;
537
	    break;
538
	case atomDFP5:
539
	    Mask = ATOM_S2_DFP5_DPMS_STATE;
540
	    break;
541
	case atomNone:
542
	    return;
543
    }
544
    switch (PowerManagementMode) {
545
	case DPMSModeOn:
546
	    Mask1 = 0;
547
	    break;
548
	case DPMSModeStandby:
549
	case DPMSModeSuspend:
550
	case DPMSModeOff:
551
	default:
552
	    Mask1 = Mask;
553
	    break;
554
    }
555
 
556
    RHDRegMask(rhdPtr, Addr, Mask1, Mask);
557
}
558
 
559
/*
560
 *
561
 */
562
void
563
RHDAtomBIOSScratchBlLevel(RHDPtr rhdPtr, enum rhdBIOSScratchBlAction action, int *val)
564
{
565
    CARD32 Addr;
566
 
567
    RHDFUNC(rhdPtr);
568
 
569
    if (rhdPtr->ChipSet < RHD_R600)
570
	Addr = 0x18;
571
    else
572
	Addr = 0x172C;
573
 
574
    switch (action) {
575
	case rhdBIOSScratchBlGet:
576
	    *val = (RHDRegRead(rhdPtr, Addr) >> 8) & 0xFF;
577
	    RHDDebug(rhdPtr->scrnIndex, "Get BL level: 0x%x\n",*val);
578
	    break;
579
	case rhdBIOSScratchBlSet:
580
	    RHDDebug(rhdPtr->scrnIndex, "Set BL level: 0x%x\n",*val);
581
	    RHDRegMask(rhdPtr, Addr, (*val) << 8, 0xFF00);
582
	    break;
583
    }
584
}
585
 
586
/*
587
 * This function finds the AtomBIOS device ID of the device that we currently
588
 * want to drive with a specific output. It contains a logic to deal with CRTC vs. TV
589
 * on DACs.
590
 * This function preferrably gets called from within the function that also updates
591
 * the BIOS scratch registers.
592
 */
593
static enum atomDevice
594
rhdBIOSScratchSetDeviceForOutput(struct rhdOutput *Output)
595
{
596
    int i = 0;
597
 
598
    RHDFUNC(Output);
599
 
600
    if (!Output->Connector) {
601
	RHDDebug(Output->scrnIndex,"%s: No connector assigned to output %s\n",__func__,Output->Name);
602
	return atomNone;
603
    }
604
 
605
    if (!Output->OutputDriverPrivate) {
606
	RHDDebug(Output->scrnIndex,"%s: Output %s has no DriverPrivate\n",__func__,Output->Name);
607
	return atomNone;
608
    }
609
 
610
    while (Output->OutputDriverPrivate->OutputDevices[i].DeviceId != atomNone) {
611
	if (Output->OutputDriverPrivate->OutputDevices[i].ConnectorType == Output->Connector->Type){
612
 
613
	    switch (Output->OutputDriverPrivate->OutputDevices[i].DeviceId) {
614
		case atomCrtc1:
615
		case atomCrtc2:
616
		    if (Output->SensedType == RHD_SENSED_VGA
617
			|| Output->SensedType == RHD_SENSED_NONE) /* if nothing was sensed default to VGA */
618
			break;
619
		    i++;
620
		    continue;
621
		case atomTV1:
622
		case atomTV2:
623
		    if (Output->SensedType == RHD_SENSED_TV_SVIDEO
624
			|| Output->SensedType == RHD_SENSED_TV_COMPOSITE)
625
			break;
626
		    i++;
627
		    continue;
628
		case atomCV:
629
		    if (Output->SensedType == RHD_SENSED_TV_COMPONENT)
630
			break;
631
		    i++;
632
		    continue;
633
		default:
634
		    break;
635
	    }
636
	    Output->OutputDriverPrivate->Device = Output->OutputDriverPrivate->OutputDevices[i].DeviceId;
637
 
638
	    return Output->OutputDriverPrivate->Device;
639
	}
640
	i++;
641
    }
642
    RHDDebugVerb(Output->scrnIndex,1,"%s: No device found: ConnectorType: %2.2x SensedType: %2.2x\n",
643
	     __func__, Output->Connector->Type, Output->SensedType);
644
    return atomNone;
645
}
646
 
647
/*
648
 * This function is public as it is used from within other outputs, too.
649
 */
650
static enum atomDevice
651
rhdBIOSScratchUpdateBIOSScratchForOutput(struct rhdOutput *Output)
652
{
653
    RHDPtr rhdPtr = RHDPTRI(Output);
654
    struct rhdOutputDevices *devList;
655
    enum atomDevice Device;
656
    int i = 0;
657
 
658
    RHDFUNC(Output);
659
 
660
    if (!Output->OutputDriverPrivate) {
661
	RHDDebug(Output->scrnIndex,"%s: no output driver private present\n",__func__);
662
	return atomNone;
663
    }
664
    devList = Output->OutputDriverPrivate->OutputDevices;
665
 
666
    if (Output->Connector) {
667
	/* connected - enable */
668
	Device = rhdBIOSScratchSetDeviceForOutput(Output);
669
 
670
    if (Device == atomNone && rhdPtr->Card->ConnectorInfo[0].Type != RHD_CONNECTOR_NONE) {
671
        xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: AtomBIOS DeviceID unknown\n",__func__);
672
        return Device;
673
    }
674
 
675
	ASSERT(Device != atomNone);
676
 
677
	if (Output->Crtc)
678
	    rhdAtomBIOSScratchSetCrtcState(rhdPtr, Device,
679
					   Output->Crtc->Id == 1 ? atomCrtc2 : atomCrtc1);
680
	rhdAtomBIOSScratchUpdateOnState(rhdPtr, Device, Output->Active);
681
	rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr, Device, Output->Active);
682
	rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, Device, TRUE);
683
 
684
	while (devList[i].DeviceId != atomNone) {
685
	    if (devList[i].DeviceId != Device)
686
		rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE);
687
	        i++;
688
	}
689
 
690
    } else {
691
	/* not connected - just disable everything */
692
	Device = atomNone;
693
	Output->OutputDriverPrivate->Device = Device;
694
 
695
	while (devList[i].DeviceId != atomNone) {
696
	    rhdAtomBIOSScratchUpdateOnState(rhdPtr, devList[i].DeviceId, FALSE);
697
	    rhdAtomBIOSScratchSetAcceleratorModeForDevice(rhdPtr,
698
							  devList[i].DeviceId, FALSE);
699
	    rhdAtomBIOSScratchUpdateAttachedState(rhdPtr, devList[i].DeviceId, FALSE);
700
	    i++;
701
	}
702
    }
703
 
704
    return Device;
705
}
706
 
707
/*
708
 *
709
 */
710
static void
711
rhdBIOSScratchPower(struct rhdOutput *Output, int Power)
712
{
713
    rhdBIOSScratchUpdateBIOSScratchForOutput(Output);
714
    Output->OutputDriverPrivate->Power(Output, Power);
715
}
716
 
717
/*
718
 *
719
 */
720
static void
721
rhdBIOSScratchMode(struct rhdOutput *Output, DisplayModePtr Mode)
722
{
723
    rhdBIOSScratchUpdateBIOSScratchForOutput(Output);
724
    Output->OutputDriverPrivate->Mode(Output, Mode);
725
}
726
 
727
/*
728
 * This destroys the privates again. It is implemented as an output destroy wrapper.
729
 */
730
static void
731
rhdBIOSScratchDestroyOutputDriverPrivate(struct rhdOutput *Output)
732
{
733
    RHDFUNC(Output);
734
 
735
    if (Output->OutputDriverPrivate) {
736
	void (*Destroy) (struct rhdOutput *Output) = Output->OutputDriverPrivate->Destroy;
737
 
738
	xfree(Output->OutputDriverPrivate->OutputDevices);
739
	xfree(Output->OutputDriverPrivate);
740
	Output->OutputDriverPrivate = NULL;
741
	if (Destroy)
742
	    Destroy(Output);
743
    }
744
}
745
 
746
/*
747
 * This sets up the AtomBIOS driver output private.
748
 * It allocates the data structure and sets up the list of devices
749
 * including the connector they are associated with.
750
 */
751
Bool
752
RHDAtomSetupOutputDriverPrivate(struct rhdAtomOutputDeviceList *Devices, struct rhdOutput *Output)
753
{
754
    struct rhdOutputDevices *od = NULL;
755
    struct BIOSScratchOutputPrivate *OutputDriverPrivate;
756
    int i = 0, cnt = 0;
757
 
758
    RHDFUNC(Output);
759
 
760
    if (!Devices) {
761
	RHDDebug(Output->scrnIndex, "%s: Device list doesn't exist.\n");
762
	return FALSE;
763
    }
764
 
765
    RHDDebugVerb(Output->scrnIndex, 1, " Output: %s[0x%2.2x] - adding devices:\n", Output->Name, Output->Id);
766
 
767
    while (Devices[i].DeviceId != atomNone) {
768
	RHDDebugVerb(Output->scrnIndex,1," Looking at DeviceID: 0x%2.2x OutputType: 0x%2.2x ConnectorType: 0x%2.2x\n",
769
		     Devices[i].DeviceId,Devices[i].OutputType,Devices[i].ConnectorType);
770
	if (Devices[i].OutputType == Output->Id) {
771
	    if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1))))
772
		return FALSE;
773
	    RHDDebugVerb(Output->scrnIndex,1,"  >> 0x%2.2x\n", Devices[i].DeviceId);
774
	    od[cnt].DeviceId = Devices[i].DeviceId;
775
	    od[cnt].ConnectorType = Devices[i].ConnectorType;
776
	    cnt++;
777
	}
778
	i++;
779
    }
780
    if (!(od = (struct rhdOutputDevices *)xrealloc(od, sizeof(struct rhdOutputDevices) * (cnt + 1))))
781
	return FALSE;
782
    od[cnt].DeviceId = atomNone;
783
 
784
    if (!(OutputDriverPrivate = (struct BIOSScratchOutputPrivate *)xalloc(sizeof(struct BIOSScratchOutputPrivate)))) {
785
	xfree(od);
786
	return FALSE;
787
    }
788
    OutputDriverPrivate->OutputDevices = od;
789
    OutputDriverPrivate->Destroy = Output->Destroy;
790
    Output->Destroy = rhdBIOSScratchDestroyOutputDriverPrivate;
791
    OutputDriverPrivate->Power = Output->Power;
792
    Output->Power = rhdBIOSScratchPower;
793
    OutputDriverPrivate->Mode = Output->Mode;
794
    Output->Mode = rhdBIOSScratchMode;
795
    Output->OutputDriverPrivate = OutputDriverPrivate;
796
 
797
    return TRUE;
798
}
799
 
800
/*
801
 * Find the connector and output type for a specific atom device.
802
 * This information is kept in the output lists.
803
 */
804
Bool
805
RHDFindConnectorAndOutputTypesForDevice(RHDPtr rhdPtr, enum atomDevice Device, enum rhdOutputType *ot, enum rhdConnectorType *ct)
806
{
807
    struct rhdOutput *Output;
808
 
809
    *ot = RHD_OUTPUT_NONE;
810
    *ct = RHD_CONNECTOR_NONE;
811
 
812
    for (Output = rhdPtr->Outputs; Output; Output = Output->Next) {
813
	struct rhdOutputDevices *DeviceList;
814
	int i = 0;
815
 
816
	if (!Output->OutputDriverPrivate)
817
	    continue;
818
 
819
	DeviceList = Output->OutputDriverPrivate->OutputDevices;
820
	while (DeviceList[i].DeviceId != atomNone) {
821
	    if (DeviceList[i].DeviceId == Device) {
822
		*ot = Output->Id;
823
		*ct = DeviceList[i].ConnectorType;
824
		return TRUE;
825
	    }
826
	    i++;
827
	}
828
    }
829
 
830
    return FALSE;
831
}
832
 
833
/*
834
 *
835
 */
836
enum atomDevice
837
RHDGetDeviceOnCrtc(RHDPtr rhdPtr, enum atomCrtc Crtc)
838
{
839
    CARD32 BIOS_3;
840
    CARD32 Addr;
841
    CARD32 Mask = 0;
842
 
843
    RHDFUNC(rhdPtr);
844
 
845
    if (rhdPtr->ChipSet < RHD_R600)
846
	Addr = 0x1C;
847
    else
848
	Addr = 0x1730;
849
 
850
    if (Crtc == atomCrtc1)
851
	Mask = ~Mask;
852
 
853
    BIOS_3 = RHDRegRead(rhdPtr, Addr);
854
    RHDDebug(rhdPtr->scrnIndex, "%s: BIOS_3 = 0x%x\n",__func__,BIOS_3);
855
 
856
    if (BIOS_3 & ATOM_S3_CRT1_ACTIVE
857
	&& ((BIOS_3 ^ Mask) & ATOM_S3_CRT1_CRTC_ACTIVE))
858
	return atomCRT1;
859
    else if (BIOS_3 & ATOM_S3_LCD1_ACTIVE
860
	     && ((BIOS_3 ^ Mask) & ATOM_S3_LCD1_CRTC_ACTIVE))
861
	return atomLCD1;
862
    else if (BIOS_3 & ATOM_S3_DFP1_ACTIVE
863
	     && ((BIOS_3 ^ Mask) & ATOM_S3_DFP1_CRTC_ACTIVE))
864
	return atomDFP1;
865
    else if (BIOS_3 & ATOM_S3_CRT2_ACTIVE
866
	     && ((BIOS_3 ^ Mask) & ATOM_S3_CRT2_CRTC_ACTIVE))
867
	return atomCRT2;
868
    else if (BIOS_3 & ATOM_S3_LCD2_ACTIVE
869
	     && ((BIOS_3 ^ Mask) & ATOM_S3_LCD2_CRTC_ACTIVE))
870
	return atomLCD2;
871
    else if (BIOS_3 & ATOM_S3_TV2_ACTIVE
872
	     && ((BIOS_3 ^ Mask) & ATOM_S3_TV2_CRTC_ACTIVE))
873
	return atomTV2;
874
    else if (BIOS_3 & ATOM_S3_DFP2_ACTIVE
875
	     && ((BIOS_3 ^ Mask) & ATOM_S3_DFP2_CRTC_ACTIVE))
876
	return atomDFP2;
877
    else if (BIOS_3 & ATOM_S3_CV_ACTIVE
878
	     && ((BIOS_3 ^ Mask) & ATOM_S3_CV_CRTC_ACTIVE))
879
	return atomCV;
880
    else if (BIOS_3 & ATOM_S3_DFP3_ACTIVE
881
	     && ((BIOS_3 ^ Mask) & ATOM_S3_DFP3_CRTC_ACTIVE))
882
	return atomDFP3;
883
    else if (BIOS_3 & ATOM_S3_DFP4_ACTIVE
884
	     && ((BIOS_3 ^ Mask) & ATOM_S3_DFP4_CRTC_ACTIVE))
885
	return atomDFP4;
886
    else if (BIOS_3 & ATOM_S3_DFP5_ACTIVE
887
	     && ((BIOS_3 ^ Mask) & ATOM_S3_DFP5_CRTC_ACTIVE))
888
	return atomDFP5;
889
    else
890
	return atomNone;
891
}
892
 
893
struct rhdBiosScratchRegisters {
894
    CARD32 Scratch0;
895
    CARD32 Scratch2;
896
    CARD32 Scratch3;
897
    CARD32 Scratch6;
898
};
899
 
900
struct rhdBiosScratchRegisters *
901
RHDSaveBiosScratchRegisters(RHDPtr rhdPtr)
902
{
903
    struct rhdBiosScratchRegisters *regs;
904
    CARD32 S0Addr, S2Addr, S3Addr, S6Addr;
905
 
906
    RHDFUNC(rhdPtr);
907
 
908
    if (!(regs = (struct rhdBiosScratchRegisters *)xalloc(sizeof(struct rhdBiosScratchRegisters))))
909
	return NULL;
910
 
911
    if (rhdPtr->ChipSet < RHD_R600) {
912
	S0Addr = 0x10;
913
	S2Addr = 0x18;
914
	S3Addr = 0x1C;
915
	S6Addr = 0x10 + (6 << 2);
916
    } else {
917
	S0Addr = 0x1724;
918
	S2Addr = 0x172C;
919
	S3Addr = 0x1730;
920
	S6Addr = 0x1724 + (6 << 2);
921
    }
922
    regs->Scratch0 = RHDRegRead(rhdPtr, S0Addr);
923
    regs->Scratch2 = RHDRegRead(rhdPtr, S2Addr);
924
    regs->Scratch3 = RHDRegRead(rhdPtr, S3Addr);
925
    regs->Scratch6 = RHDRegRead(rhdPtr, S6Addr);
926
 
927
    return regs;
928
}
929
 
930
void
931
RHDRestoreBiosScratchRegisters(RHDPtr rhdPtr, struct rhdBiosScratchRegisters *regs)
932
{
933
    CARD32 S0Addr, S2Addr, S3Addr, S6Addr;
934
 
935
    RHDFUNC(rhdPtr);
936
 
937
    if (!regs)
938
	return;
939
 
940
    if (rhdPtr->ChipSet < RHD_R600) {
941
	S0Addr = 0x10;
942
	S2Addr = 0x18;
943
	S3Addr = 0x1C;
944
	S6Addr = 0x10 + (6 << 2);
945
    } else {
946
	S0Addr = 0x1724;
947
	S2Addr = 0x172C;
948
	S3Addr = 0x1730;
949
	S6Addr = 0x1724 + (6 << 2);
950
    }
951
    RHDRegWrite(rhdPtr, S0Addr, regs->Scratch0);
952
    RHDRegWrite(rhdPtr, S2Addr, regs->Scratch2);
953
    RHDRegWrite(rhdPtr, S3Addr, regs->Scratch3);
954
    RHDRegWrite(rhdPtr, S6Addr, regs->Scratch6);
955
 
956
    xfree(regs);
957
}
958
 
959
#endif /* ATOM_BIOS */
960