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
#endif
38
 
39
#include "rhd.h"
40
#include "rhd_crtc.h"
41
#include "rhd_connector.h"
42
#include "rhd_output.h"
43
#include "rhd_regs.h"
44
#include "rhd_hdmi.h"
45
#ifdef ATOM_BIOS
46
#include "rhd_atombios.h"
47
#include "rhd_atomout.h"
48
#endif
49
 
50
#define FMT2_OFFSET 0x800
51
#define DIG1_OFFSET 0x000
52
#define DIG2_OFFSET 0x400
53
 
54
/*
55
 * Transmitter
56
 */
57
struct transmitter {
58
    enum rhdSensedOutput (*Sense) (struct rhdOutput *Output,
59
				   enum rhdConnectorType Type);
60
    ModeStatus (*ModeValid) (struct rhdOutput *Output, DisplayModePtr Mode);
61
    void (*Mode) (struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode);
62
    void (*Power) (struct rhdOutput *Output, int Power);
63
    void (*Save) (struct rhdOutput *Output);
64
    void (*Restore) (struct rhdOutput *Output);
65
    void (*Destroy) (struct rhdOutput *Output);
66
    Bool (*Property) (struct rhdOutput *Output,
67
		      enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val);
68
#ifdef NOT_YET
69
    Bool (*WrappedPropertyCallback) (struct rhdOutput *Output,
70
		      enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val);
71
    void *PropertyPrivate;
72
#endif
73
    void *Private;
74
};
75
 
76
/*
77
 * Encoder
78
 */
79
struct encoder {
80
    ModeStatus (*ModeValid) (struct rhdOutput *Output, DisplayModePtr Mode);
81
    void (*Mode) (struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode);
82
    void (*Power) (struct rhdOutput *Output, int Power);
83
    void (*Save) (struct rhdOutput *Output);
84
    void (*Restore) (struct rhdOutput *Output);
85
    void (*Destroy) (struct rhdOutput *Output);
86
    void *Private;
87
};
88
 
89
/*
90
 *
91
 */
92
enum encoderMode {
93
    DISPLAYPORT = 0,
94
    LVDS = 1,
95
    TMDS_DVI = 2,
96
    TMDS_HDMI = 3,
97
    SDVO = 4
98
};
99
 
100
enum encoderID {
101
    ENCODER_NONE,
102
    ENCODER_DIG1,
103
    ENCODER_DIG2
104
};
105
 
106
struct DIGPrivate
107
{
108
    struct encoder Encoder;
109
    struct transmitter Transmitter;
110
    enum encoderID EncoderID;
111
    enum encoderMode EncoderMode;
112
    Bool Coherent;
113
    Bool RunDualLink;
114
    DisplayModePtr Mode;
115
    struct rhdHdmi *Hdmi;
116
 
117
    /* LVDS */
118
    Bool FPDI;
119
    CARD32 PowerSequenceDe2Bl;
120
    CARD32 PowerSequenceDig2De;
121
    CARD32 OffDelay;
122
    struct rhdFMTDither FMTDither;
123
    int BlLevel;
124
};
125
 
126
/*
127
 * LVTMA Transmitter
128
 */
129
 
130
struct LVTMATransmitterPrivate
131
{
132
    Bool Stored;
133
 
134
    CARD32 StoredTransmitterControl;
135
    CARD32 StoredTransmitterAdjust;
136
    CARD32 StoredPreemphasisControl;
137
    CARD32 StoredMacroControl;
138
    CARD32 StoredLVTMADataSynchronization;
139
    CARD32 StoredTransmiterEnable;
140
    CARD32 StoredPwrSeqCntl;
141
    CARD32 StoredPwrSeqRevDiv;
142
    CARD32 StoredPwrSeqDelay1;
143
    CARD32 StoredPwrSeqDelay2;
144
};
145
 
146
/*
147
 *
148
 */
149
static ModeStatus
150
LVTMATransmitterModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
151
{
152
    RHDFUNC(Output);
153
 
154
    if (Mode->Flags & V_INTERLACE)
155
        return MODE_NO_INTERLACE;
156
 
157
    if (Output->Connector->Type == RHD_CONNECTOR_DVI_SINGLE
158
	&& Mode->SynthClock > 165000)
159
	return MODE_CLOCK_HIGH;
160
 
161
    return MODE_OK;
162
}
163
 
164
static void
165
LVDSSetBacklight(struct rhdOutput *Output, int level)
166
{
167
    struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
168
 
169
    RHDFUNC(Output);
170
 
171
    Private->BlLevel = level;
172
 
173
    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_REF_DIV,
174
	       0x144 << LVTMA_BL_MOD_REF_DI_SHIFT,
175
	       0x7ff << LVTMA_BL_MOD_REF_DI_SHIFT);
176
    RHDRegWrite(Output, RV620_LVTMA_BL_MOD_CNTL,
177
		0xff << LVTMA_BL_MOD_RES_SHIFT
178
		| level << LVTMA_BL_MOD_LEVEL_SHIFT
179
		| LVTMA_BL_MOD_EN);
180
}
181
 
182
/*
183
 *
184
 */
185
static Bool
186
LVDSTransmitterPropertyControl(struct rhdOutput *Output,
187
	     enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
188
{
189
    struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
190
 
191
    RHDFUNC(Output);
192
    switch (Action) {
193
	case rhdPropertyCheck:
194
	    if (Private->BlLevel < 0)
195
		return FALSE;
196
	switch (Property) {
197
	    case RHD_OUTPUT_BACKLIGHT:
198
		    return TRUE;
199
	    default:
200
		return FALSE;
201
	}
202
	case rhdPropertyGet:
203
	    if (Private->BlLevel < 0)
204
		return FALSE;
205
	    switch (Property) {
206
		case RHD_OUTPUT_BACKLIGHT:
207
		    val->integer = Private->BlLevel;
208
		    return TRUE;
209
		default:
210
		    return FALSE;
211
	    }
212
	    break;
213
	case rhdPropertySet:
214
	    if (Private->BlLevel < 0)
215
		return FALSE;
216
	    switch (Property) {
217
		case RHD_OUTPUT_BACKLIGHT:
218
		    LVDSSetBacklight(Output, val->integer);
219
		    return TRUE;
220
		default:
221
		    return FALSE;
222
	    }
223
	    break;
224
    }
225
    return TRUE;
226
}
227
 
228
/*
229
 *
230
 */
231
static Bool
232
TMDSTransmitterPropertyControl(struct rhdOutput *Output,
233
	     enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
234
{
235
    struct DIGPrivate *Private = (struct DIGPrivate *) Output->Private;
236
 
237
    RHDFUNC(Output);
238
    switch (Action) {
239
	case rhdPropertyCheck:
240
	switch (Property) {
241
	    case RHD_OUTPUT_COHERENT:
242
		    return TRUE;
243
	    default:
244
		return FALSE;
245
	}
246
	case rhdPropertyGet:
247
	    switch (Property) {
248
		case RHD_OUTPUT_COHERENT:
249
		    val->Bool =  Private->Coherent;
250
		    return TRUE;
251
		default:
252
		    return FALSE;
253
	    }
254
	    break;
255
	case rhdPropertySet:
256
	    switch (Property) {
257
		case RHD_OUTPUT_COHERENT:
258
		    Private->Coherent = val->Bool;
259
		    Output->Mode(Output, Private->Mode);
260
		    Output->Power(Output, RHD_POWER_ON);
261
		    break;
262
		default:
263
		    return FALSE;
264
	    }
265
	    break;
266
    }
267
    return TRUE;
268
}
269
 
270
/*
271
 *
272
 */
273
static void
274
LVTMATransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
275
{
276
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
277
    CARD32 value = 0;
278
#ifdef ATOM_BIOS
279
    AtomBiosArgRec data;
280
#endif
281
    RHDPtr rhdPtr = RHDPTRI(Output);
282
    Bool doCoherent = Private->Coherent;
283
    RHDFUNC(Output);
284
 
285
    /* set coherent / not coherent mode; whatever that is */
286
    if (Output->Connector->Type != RHD_CONNECTOR_PANEL)
287
	RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
288
		   doCoherent ? 0 : RV62_LVTMA_BYPASS_PLL, RV62_LVTMA_BYPASS_PLL);
289
 
290
    Private->Mode = Mode;
291
#ifdef ATOM_BIOS
292
    RHDDebug(Output->scrnIndex, "%s: SynthClock: %i Hex: %x EncoderMode: %x\n",__func__,
293
	     (Mode->SynthClock),(Mode->SynthClock / 10), Private->EncoderMode);
294
 
295
    /* Set up magic value that's used for list lookup */
296
    value = ((Mode->SynthClock / 10 / ((Private->RunDualLink) ? 2 : 1)) & 0xffff)
297
	| (Private->EncoderMode << 16)
298
	| ((doCoherent ? 0x2 : 0) << 24);
299
 
300
    RHDDebug(Output->scrnIndex, "%s: GetConditionalGoldenSettings for: %x\n", __func__, value);
301
 
302
    /* Get data from DIG2TransmitterControl table */
303
    data.val = 0x4d;
304
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS, ATOMBIOS_GET_CODE_DATA_TABLE,
305
			&data) == ATOM_SUCCESS) {
306
	AtomBiosArgRec data1;
307
	CARD32 *d_p = NULL;
308
 
309
	data1.GoldenSettings.BIOSPtr = data.CommandDataTable.loc;
310
	data1.GoldenSettings.End = data1.GoldenSettings.BIOSPtr + data.CommandDataTable.size;
311
	data1.GoldenSettings.value = value;
312
 
313
	/* now find pointer */
314
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
315
			    ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, &data1) == ATOM_SUCCESS) {
316
	    d_p = (CARD32*)data1.GoldenSettings.BIOSPtr;
317
	} else {
318
	    /* nothing found, now try toggling the coherent setting */
319
	    doCoherent = !doCoherent;
320
	    value = (value & ~(0x2 << 24)) | ((doCoherent ? 0x2 : 0) << 24);
321
	    data1.GoldenSettings.value = value;
322
 
323
        if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
324
			    ATOM_GET_CONDITIONAL_GOLDEN_SETTINGS, &data1) == ATOM_SUCCESS) {
325
		d_p = (CARD32*)data1.GoldenSettings.BIOSPtr;
326
		/* set coherent / not coherent mode; whatever that is */
327
		xf86DrvMsg(Output->scrnIndex, X_INFO, "%s: %soherent Mode not supported, switching to %soherent.\n",
328
			   __func__, doCoherent ? "Inc" : "C", doCoherent ? "C" : "Inc");
329
		if (Output->Connector->Type != RHD_CONNECTOR_PANEL)
330
		    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
331
			       doCoherent ? 0 : RV62_LVTMA_BYPASS_PLL, RV62_LVTMA_BYPASS_PLL);
332
	    } else
333
		doCoherent = Private->Coherent; /* reset old value if nothing found either */
334
	}
335
	if (d_p) {
336
	    RHDDebug(Output->scrnIndex, "TransmitterAdjust: 0x%8.8x\n",d_p[0]);
337
	    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, d_p[0]);
338
 
339
	    RHDDebug(Output->scrnIndex, "PreemphasisControl: 0x%8.8x\n",d_p[1]);
340
	    RHDRegWrite(Output, RV620_LVTMA_PREEMPHASIS_CONTROL, d_p[1]);
341
 
342
	    RHDDebug(Output->scrnIndex, "MacroControl: 0x%8.8x\n",d_p[2]);
343
	    RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, d_p[2]);
344
	} else
345
	    xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: cannot get golden settings\n",__func__);
346
    } else
347
#endif
348
    {
349
	xf86DrvMsg(Output->scrnIndex, X_WARNING, "%s: No AtomBIOS supplied "
350
		   "electrical parameters available\n", __func__);
351
    }
352
}
353
 
354
/*
355
 *
356
 */
357
static void
358
LVTMATransmitterSave(struct rhdOutput *Output)
359
{
360
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
361
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
362
 
363
    Private->StoredTransmitterControl       = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_CONTROL);
364
    Private->StoredTransmitterAdjust        = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_ADJUST);
365
    Private->StoredPreemphasisControl       = RHDRegRead(Output, RV620_LVTMA_PREEMPHASIS_CONTROL);
366
    Private->StoredMacroControl             = RHDRegRead(Output, RV620_LVTMA_MACRO_CONTROL);
367
    Private->StoredLVTMADataSynchronization = RHDRegRead(Output, RV620_LVTMA_DATA_SYNCHRONIZATION);
368
    Private->StoredTransmiterEnable         = RHDRegRead(Output, RV620_LVTMA_TRANSMITTER_ENABLE);
369
}
370
 
371
/*
372
 *
373
 */
374
static void
375
LVTMATransmitterRestore(struct rhdOutput *Output)
376
{
377
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
378
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
379
 
380
    RHDFUNC(Output);
381
 
382
    /* write control values back */
383
    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl);
384
    usleep (14);
385
    /* reset PLL */
386
    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl
387
		| RV62_LVTMA_PLL_RESET);
388
    usleep (10);
389
    /* unreset PLL */
390
    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_CONTROL,Private->StoredTransmitterControl);
391
    usleep(1000);
392
    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, Private->StoredTransmitterAdjust);
393
    RHDRegWrite(Output, RV620_LVTMA_PREEMPHASIS_CONTROL, Private->StoredPreemphasisControl);
394
    RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, Private->StoredMacroControl);
395
    /* start data synchronization */
396
    RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, (Private->StoredLVTMADataSynchronization
397
							   & ~(CARD32)RV62_LVTMA_DSYNSEL)
398
		| RV62_LVTMA_PFREQCHG);
399
    usleep (1);
400
    RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, Private->StoredLVTMADataSynchronization);
401
    usleep(10);
402
    RHDRegWrite(Output, RV620_LVTMA_DATA_SYNCHRONIZATION, Private->StoredLVTMADataSynchronization);
403
    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ENABLE, Private->StoredTransmiterEnable);
404
}
405
 
406
/*
407
 *
408
 */
409
static void
410
LVTMA_TMDSTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
411
{
412
    RHDFUNC(Output);
413
 
414
    /* TMDS Mode */
415
    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
416
	       RV62_LVTMA_USE_CLK_DATA, RV62_LVTMA_USE_CLK_DATA);
417
 
418
    LVTMATransmitterSet(Output, Crtc, Mode);
419
 
420
    /* use differential post divider input */
421
    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
422
	       RV62_LVTMA_IDSCKSEL, RV62_LVTMA_IDSCKSEL);
423
}
424
 
425
/*
426
 *
427
 */
428
static void
429
LVTMA_TMDSTransmitterPower(struct rhdOutput *Output, int Power)
430
{
431
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
432
 
433
    RHDFUNC(Output);
434
 
435
    switch (Power) {
436
	case RHD_POWER_ON:
437
	    /* enable PLL */
438
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
439
		       RV62_LVTMA_PLL_ENABLE, RV62_LVTMA_PLL_ENABLE);
440
	    usleep(14);
441
	    /* PLL reset on */
442
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
443
		       RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
444
	    usleep(10);
445
	    /* PLL reset off */
446
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
447
		       0, RV62_LVTMA_PLL_RESET);
448
	    usleep(1000);
449
	    /* start data synchronization */
450
	    RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
451
		       RV62_LVTMA_PFREQCHG, RV62_LVTMA_PFREQCHG);
452
	    usleep(1);
453
	    /* restart write address logic */
454
	    RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
455
		       RV62_LVTMA_DSYNSEL, RV62_LVTMA_DSYNSEL);
456
#if 1
457
	    /* TMDS Mode ?? */
458
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
459
		       RV62_LVTMA_MODE, RV62_LVTMA_MODE);
460
#endif
461
	    /* enable lower link */
462
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
463
		       RV62_LVTMA_LNKL,
464
		       RV62_LVTMA_LNK_ALL);
465
	    if (Private->RunDualLink) {
466
		usleep (28);
467
		/* enable upper link */
468
		RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
469
			   RV62_LVTMA_LNKU,
470
			   RV62_LVTMA_LNKU);
471
	    }
472
	    return;
473
	case RHD_POWER_RESET:
474
	    /* disable all links */
475
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
476
		       0, RV62_LVTMA_LNK_ALL);
477
	    return;
478
	case RHD_POWER_SHUTDOWN:
479
	default:
480
	    /* disable transmitter */
481
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE,
482
		       0, RV62_LVTMA_LNK_ALL);
483
	    /* PLL reset */
484
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
485
		       RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
486
	    usleep(10);
487
	    /* end PLL reset */
488
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
489
		       0, RV62_LVTMA_PLL_RESET);
490
	    /* disable data synchronization */
491
	    RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
492
		       0, RV62_LVTMA_DSYNSEL);
493
	    /* reset macro control */
494
	    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, 0);
495
 
496
	    return;
497
    }
498
}
499
 
500
/*
501
 *
502
 */
503
static void
504
LVTMA_TMDSTransmitterSave(struct rhdOutput *Output)
505
{
506
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
507
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
508
 
509
    RHDFUNC(Output);
510
 
511
    LVTMATransmitterSave(Output);
512
 
513
    Private->Stored = TRUE;
514
}
515
 
516
/*
517
 *
518
 */
519
static void
520
LVTMA_TMDSTransmitterRestore(struct rhdOutput *Output)
521
{
522
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
523
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
524
 
525
    RHDFUNC(Output);
526
 
527
    if (!Private->Stored) {
528
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
529
		   "%s: No registers stored.\n", __func__);
530
	return;
531
    }
532
 
533
    LVTMATransmitterRestore(Output);
534
}
535
 
536
/*
537
 *
538
 */
539
static void
540
LVTMA_LVDSTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
541
{
542
    RHDFUNC(Output);
543
 
544
    /* LVDS Mode */
545
    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
546
	       0, RV62_LVTMA_USE_CLK_DATA);
547
 
548
    LVTMATransmitterSet(Output, Crtc, Mode);
549
 
550
    /* use IDCLK */
551
    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL, RV62_LVTMA_IDSCKSEL, RV62_LVTMA_IDSCKSEL);
552
    /* enable pwrseq, pwrseq overwrite PPL enable, reset */
553
    RHDRegMask(Output,  RV620_LVTMA_PWRSEQ_CNTL,
554
	       RV62_LVTMA_PWRSEQ_EN
555
	       | RV62_LVTMA_PLL_ENABLE_PWRSEQ_MASK
556
	       | RV62_LVTMA_PLL_RESET_PWRSEQ_MASK,
557
	       RV62_LVTMA_PWRSEQ_EN
558
	       | RV62_LVTMA_PLL_ENABLE_PWRSEQ_MASK
559
	       | RV62_LVTMA_PLL_RESET_PWRSEQ_MASK
560
	);
561
 
562
}
563
 
564
/*
565
 *
566
 */
567
static void
568
LVTMA_LVDSTransmitterPower(struct rhdOutput *Output, int Power)
569
{
570
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
571
    CARD32 tmp, tmp1;
572
    int i;
573
 
574
    RHDFUNC(Output);
575
 
576
    switch (Power) {
577
	case RHD_POWER_ON:
578
	    /* enable PLL */
579
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
580
		       RV62_LVTMA_PLL_ENABLE, RV62_LVTMA_PLL_ENABLE);
581
	    usleep(14);
582
	    /* PLL reset on */
583
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
584
		       RV62_LVTMA_PLL_RESET, RV62_LVTMA_PLL_RESET);
585
	    usleep(10);
586
	    /* PLL reset off */
587
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
588
		       0, RV62_LVTMA_PLL_RESET);
589
	    usleep(1000);
590
	    /* start data synchronization */
591
	    RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
592
		       RV62_LVTMA_PFREQCHG, RV62_LVTMA_PFREQCHG);
593
	    usleep(1);
594
	    /* restart write address logic */
595
	    RHDRegMask(Output, RV620_LVTMA_DATA_SYNCHRONIZATION,
596
		       RV62_LVTMA_DSYNSEL, RV62_LVTMA_DSYNSEL);
597
	    /* SYNCEN disables pwrseq ?? */
598
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL,
599
		       RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN,
600
		       RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN);
601
	    /* LVDS Mode ?? */
602
	    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_CONTROL,
603
		       0, RV62_LVTMA_MODE);
604
	    /* enable links */
605
	    if (Private->RunDualLink) {
606
		if (Private->FMTDither.LVDS24Bit)
607
		    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x3ff, 0x3ff);
608
		else
609
		    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x1ef, 0x3ff);
610
		    } else {
611
		if (Private->FMTDither.LVDS24Bit)
612
		    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x1f, 0x3ff);
613
		else
614
		    RHDRegMask(Output, RV620_LVTMA_TRANSMITTER_ENABLE, 0x0f, 0x3ff);
615
	    }
616
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0,
617
		       RV62_LVTMA_DIGON_OVRD | RV62_LVTMA_BLON_OVRD);
618
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_REF_DIV, 3999, 0xffff); /* 4000 - 1 */
619
	    tmp = Private->PowerSequenceDe2Bl * 10 / 4;
620
	    tmp1 = Private->PowerSequenceDig2De * 10 / 4;
621
	    /* power sequencing delay for on / off between DIGON and SYNCEN, and SYNCEN and BLON */
622
	    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY1, (tmp1 << 24) | tmp1 | (tmp << 8) | (tmp << 16));
623
	    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY2, Private->OffDelay / 4);
624
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0, RV62_LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN);
625
	    for (i = 0; i < 500; i++) {
626
		CARD32 tmp;
627
 
628
		usleep(1000);
629
		tmp = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_STATE);
630
		tmp >>= RV62_LVTMA_PWRSEQ_STATE_SHIFT;
631
		tmp &= 0xff;
632
		if (tmp <= RV62_POWERUP_DONE)
633
		    break;
634
		if (tmp >= RV62_POWERDOWN_DONE)
635
		    break;
636
	    }
637
	    /* LCD on */
638
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, RV62_LVTMA_PWRSEQ_TARGET_STATE,
639
		       RV62_LVTMA_PWRSEQ_TARGET_STATE);
640
	    return;
641
 
642
	case RHD_POWER_RESET:
643
	    /* Disable LCD and BL */
644
	    RHDRegMask(Output, RV620_LVTMA_PWRSEQ_CNTL, 0,
645
		       RV62_LVTMA_PWRSEQ_TARGET_STATE
646
		       | RV62_LVTMA_DIGON_OVRD
647
		       | RV62_LVTMA_BLON_OVRD);
648
	    for (i = 0; i < 500; i++) {
649
		CARD32 tmp;
650
 
651
		usleep(1000);
652
		tmp = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_STATE);
653
		tmp >>= RV62_LVTMA_PWRSEQ_STATE_SHIFT;
654
		tmp &= 0xff;
655
		if (tmp >= RV62_POWERDOWN_DONE)
656
		    break;
657
	    }
658
	    return;
659
	case RHD_POWER_SHUTDOWN:
660
	    LVTMA_LVDSTransmitterPower(Output, RHD_POWER_RESET);
661
	    /* op-amp down, bias current for output driver down, shunt resistor down */
662
	    RHDRegWrite(Output, RV620_LVTMA_TRANSMITTER_ADJUST, 0x00e00000);
663
	    /* set macro control */
664
	    RHDRegWrite(Output, RV620_LVTMA_MACRO_CONTROL, 0x07430408);
665
	default:
666
	    return;
667
    }
668
}
669
 
670
/*
671
 *
672
 */
673
static void
674
LVTMA_LVDSTransmitterSave(struct rhdOutput *Output)
675
{
676
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
677
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
678
 
679
    RHDFUNC(Output);
680
 
681
    LVTMATransmitterSave(Output);
682
 
683
    Private->StoredPwrSeqCntl               = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_CNTL);
684
    Private->StoredPwrSeqRevDiv             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_REF_DIV);
685
    Private->StoredPwrSeqDelay1             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_DELAY1);
686
    Private->StoredPwrSeqDelay2             = RHDRegRead(Output, RV620_LVTMA_PWRSEQ_DELAY2);
687
 
688
    Private->Stored = TRUE;
689
}
690
 
691
/*
692
 *
693
 */
694
static void
695
LVTMA_LVDSTransmitterRestore(struct rhdOutput *Output)
696
{
697
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
698
    struct LVTMATransmitterPrivate *Private = (struct LVTMATransmitterPrivate*)digPrivate->Transmitter.Private;
699
 
700
    RHDFUNC(Output);
701
 
702
    if (!Private->Stored) {
703
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
704
		   "%s: No registers stored.\n", __func__);
705
	return;
706
    }
707
 
708
    LVTMATransmitterRestore(Output);
709
 
710
    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_REF_DIV, Private->StoredPwrSeqRevDiv);
711
    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY1, Private->StoredPwrSeqDelay1);
712
    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_DELAY2, Private->StoredPwrSeqDelay2);
713
    RHDRegWrite(Output, RV620_LVTMA_PWRSEQ_CNTL, Private->StoredPwrSeqCntl);
714
}
715
 
716
/*
717
 *
718
 */
719
static void
720
LVTMATransmitterDestroy(struct rhdOutput *Output)
721
{
722
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
723
 
724
    RHDFUNC(Output);
725
 
726
    if (!digPrivate)
727
	return;
728
 
729
    xfree(digPrivate->Transmitter.Private);
730
}
731
 
732
#if defined(ATOM_BIOS) && defined(ATOM_BIOS_PARSER)
733
 
734
struct ATOMTransmitterPrivate
735
{
736
    struct atomTransmitterConfig atomTransmitterConfig;
737
    enum atomTransmitter atomTransmitterID;
738
};
739
 
740
/*
741
 *
742
 */
743
static ModeStatus
744
ATOMTransmitterModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
745
{
746
 
747
    RHDFUNC(Output);
748
 
749
    if (Output->Connector->Type == RHD_CONNECTOR_DVI_SINGLE
750
	&& Mode->SynthClock > 165000)
751
	return MODE_CLOCK_HIGH;
752
 
753
    return MODE_OK;
754
}
755
 
756
/*
757
 *
758
 */
759
void
760
rhdPrintDigDebug(RHDPtr rhdPtr, const char *name)
761
{
762
    xf86DrvMsgVerb(rhdPtr->scrnIndex, X_INFO, 7, "%s: DIGn_CNTL: n=1: 0x%x n=2: 0x%x\n",
763
	   name, RHDRegRead(rhdPtr, RV620_DIG1_CNTL),
764
	   RHDRegRead(rhdPtr, DIG2_OFFSET + RV620_DIG1_CNTL));
765
}
766
 
767
/*
768
 *
769
 */
770
static void
771
ATOMTransmitterSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
772
{
773
    RHDPtr rhdPtr = RHDPTRI(Output);
774
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
775
    struct ATOMTransmitterPrivate *transPrivate
776
	= (struct ATOMTransmitterPrivate*) Private->Transmitter.Private;
777
    struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
778
 
779
    RHDFUNC(Output);
780
 
781
    atc->Coherent = Private->Coherent;
782
    atc->PixelClock = Mode->SynthClock;
783
 
784
    rhdPrintDigDebug(rhdPtr,__func__);
785
 
786
    if (Private->RunDualLink) {
787
	atc->Mode = atomDualLink;
788
 
789
	if (atc->Link == atomTransLinkA)
790
	    atc->Link = atomTransLinkAB;
791
	else if (atc->Link == atomTransLinkB)
792
	    atc->Link = atomTransLinkBA;
793
 
794
    } else {
795
	atc->Mode = atomSingleLink;
796
 
797
	if (atc->Link == atomTransLinkAB)
798
	    atc->Link = atomTransLinkA;
799
	else if (atc->Link == atomTransLinkBA)
800
	    atc->Link = atomTransLinkB;
801
 
802
    }
803
 
804
    atc->PixelClock = Mode->SynthClock;
805
 
806
    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
807
				 atomTransSetup, atc);
808
    rhdPrintDigDebug(rhdPtr,__func__);
809
}
810
 
811
/*
812
 *
813
 */
814
static CARD32
815
digProbeEncoder(struct rhdOutput *Output)
816
{
817
    if (Output->Id == RHD_OUTPUT_KLDSKP_LVTMA) {
818
	return ENCODER_DIG2;
819
    } else {
820
	Bool swap = (RHDRegRead(Output, RV620_DCIO_LINK_STEER_CNTL)
821
		     & RV62_LINK_STEER_SWAP) == RV62_LINK_STEER_SWAP;
822
 
823
	switch (Output->Id) {
824
	    case RHD_OUTPUT_UNIPHYA:
825
		if (swap) {
826
		    RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG2 for UNIPHYA\n",__func__);
827
		    return ENCODER_DIG2;
828
		} else {
829
		    RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG1 for UNIPHYA\n",__func__);
830
		    return ENCODER_DIG1;
831
		}
832
		break;
833
	    case RHD_OUTPUT_UNIPHYB:
834
		if (swap) {
835
		    RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG1 for UNIPHYB\n",__func__);
836
		    return ENCODER_DIG1;
837
		} else {
838
		    RHDDebug(Output->scrnIndex, "%s: detected ENCODER_DIG2 for UNIPHYB\n",__func__);
839
		    return ENCODER_DIG2;
840
		}
841
		break;
842
	    default:
843
		return ENCODER_NONE; /* should not get here */
844
	}
845
    }
846
    return ENCODER_NONE;
847
}
848
 
849
/*
850
 *
851
 */
852
static void
853
ATOMTransmitterPower(struct rhdOutput *Output, int Power)
854
{
855
    RHDPtr rhdPtr = RHDPTRI(Output);
856
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
857
    struct ATOMTransmitterPrivate *transPrivate
858
	= (struct ATOMTransmitterPrivate*) Private->Transmitter.Private;
859
    struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
860
 
861
    RHDFUNC(Output);
862
 
863
    rhdPrintDigDebug(rhdPtr,__func__);
864
 
865
    if (Private->RunDualLink)
866
	atc->LinkCnt = atomDualLink;
867
    else
868
	atc->LinkCnt = atomSingleLink;
869
 
870
    atc->Coherent = Private->Coherent;
871
 
872
    if (atc->Encoder == atomEncoderNone) {
873
	switch (digProbeEncoder(Output)) {
874
	    case ENCODER_DIG1:
875
		if (rhdPtr->DigEncoderOutput[0]) {
876
		    RHDDebug(Output->scrnIndex,"%s: DIG1 for %s already taken\n",__func__,Output->Name);
877
		    return;
878
		}
879
		atc->Encoder = atomEncoderDIG1;
880
		break;
881
	    case ENCODER_DIG2:
882
		if (rhdPtr->DigEncoderOutput[1]) {
883
		    RHDDebug(Output->scrnIndex,"%s: DIG2 for %s already taken\n",__func__,Output->Name);
884
		    return;
885
		}
886
		atc->Encoder = atomEncoderDIG2;
887
		break;
888
	    default:
889
		return;
890
	}
891
    }
892
 
893
    switch (Power) {
894
	case RHD_POWER_ON:
895
	    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
896
					 atomTransEnable, atc);
897
	    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
898
					 atomTransEnableOutput, atc);
899
	    break;
900
	case RHD_POWER_RESET:
901
	    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
902
					 atomTransDisableOutput, atc);
903
	    break;
904
	case RHD_POWER_SHUTDOWN:
905
	    if (!Output->Connector || Output->Connector->Type == RHD_CONNECTOR_DVI)
906
		atc->Mode = atomDVI;
907
 
908
	    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
909
					 atomTransDisableOutput, atc);
910
	    rhdAtomDigTransmitterControl(rhdPtr->atomBIOS, transPrivate->atomTransmitterID,
911
					 atomTransDisable, atc);
912
	    break;
913
    }
914
    rhdPrintDigDebug(rhdPtr,__func__);
915
}
916
 
917
/*
918
 *
919
 */
920
static void
921
ATOMTransmitterSave(struct rhdOutput *Output)
922
{
923
    RHDFUNC(Output);
924
}
925
 
926
/*
927
 *
928
 */
929
static void
930
ATOMTransmitterRestore(struct rhdOutput *Output)
931
{
932
    RHDFUNC(Output);
933
}
934
 
935
/*
936
 *
937
 */
938
static void
939
ATOMTransmitterDestroy(struct rhdOutput *Output)
940
{
941
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
942
 
943
    RHDFUNC(Output);
944
 
945
    if (!digPrivate)
946
	return;
947
 
948
    xfree(digPrivate->Transmitter.Private);
949
}
950
 
951
#endif /* ATOM_BIOS && ATOM_BIOS_PASER */
952
 
953
/*
954
 *  Encoder
955
 */
956
 
957
struct DIGEncoder
958
{
959
    Bool Stored;
960
 
961
    CARD32 StoredOff;
962
 
963
    CARD32 StoredRegExt1DiffPostDivCntl;
964
    CARD32 StoredRegExt2DiffPostDivCntl;
965
    CARD32 StoredDIGClockPattern;
966
    CARD32 StoredLVDSDataCntl;
967
    CARD32 StoredTMDSPixelEncoding;
968
    CARD32 StoredTMDSCntl;
969
    CARD32 StoredDIGCntl;
970
    CARD32 StoredDIGMisc1;
971
    CARD32 StoredDIGMisc2;
972
    CARD32 StoredDIGMisc3;
973
    CARD32 StoredDCCGPclkDigCntl;
974
    CARD32 StoredDCCGSymclkCntl;
975
    CARD32 StoredDCIOLinkSteerCntl;
976
    CARD32 StoredBlModCntl;
977
};
978
 
979
/*
980
 *
981
 */
982
static ModeStatus
983
EncoderModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
984
{
985
    RHDFUNC(Output);
986
 
987
    return MODE_OK;
988
}
989
 
990
/*
991
 *
992
 */
993
static void
994
LVDSEncoder(struct rhdOutput *Output)
995
{
996
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
997
    CARD32 off;
998
 
999
    RHDFUNC(Output);
1000
 
1001
 
1002
    off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1003
    /* Clock pattern ? */
1004
    RHDRegMask(Output, off + RV620_DIG1_CLOCK_PATTERN, 0x0063, 0xFFFF);
1005
    /* set panel type: 18/24 bit mode */
1006
    RHDRegMask(Output, off + RV620_LVDS1_DATA_CNTL,
1007
	       (Private->FMTDither.LVDS24Bit ? RV62_LVDS_24BIT_ENABLE : 0)
1008
	       | (Private->FPDI ? RV62_LVDS_24BIT_FORMAT : 0),
1009
	       RV62_LVDS_24BIT_ENABLE | RV62_LVDS_24BIT_FORMAT);
1010
 
1011
    Output->Crtc->FMTModeSet(Output->Crtc, &Private->FMTDither);
1012
}
1013
 
1014
/*
1015
 *
1016
 */
1017
static void
1018
TMDSEncoder(struct rhdOutput *Output)
1019
{
1020
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1021
    CARD32 off;
1022
 
1023
    RHDFUNC(Output);
1024
 
1025
    off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1026
    /* clock pattern ? */
1027
    RHDRegMask(Output, off + RV620_DIG1_CLOCK_PATTERN, 0x001F, 0xFFFF);
1028
    /* color format RGB - normal color format 24bpp, Twin-Single 30bpp or Dual 48bpp*/
1029
    RHDRegMask(Output, off + RV620_TMDS1_CNTL, 0x0,
1030
	       RV62_TMDS_PIXEL_ENCODING | RV62_TMDS_COLOR_FORMAT);
1031
    /* no dithering */
1032
    Output->Crtc->FMTModeSet(Output->Crtc, NULL);
1033
}
1034
 
1035
/*
1036
 *
1037
 */
1038
static void
1039
EncoderSet(struct rhdOutput *Output, struct rhdCrtc *Crtc, DisplayModePtr Mode)
1040
{
1041
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1042
    RHDPtr rhdPtr = RHDPTRI(Output);
1043
    CARD32 off;
1044
 
1045
    RHDFUNC(Output);
1046
 
1047
    off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1048
 
1049
    rhdPrintDigDebug(rhdPtr,__func__);
1050
 
1051
    RHDRegMask(Output, off + RV620_DIG1_CNTL, Output->Crtc->Id,
1052
	       RV62_DIG_SOURCE_SELECT);
1053
 
1054
    if (Output->Id == RHD_OUTPUT_UNIPHYA) {
1055
	/* select LinkA ?? */
1056
	RHDRegMask(Output, RV620_DCIO_LINK_STEER_CNTL,
1057
		   ((Private->EncoderID == ENCODER_DIG2)
1058
		    ? RV62_LINK_STEER_SWAP
1059
		    : 0), RV62_LINK_STEER_SWAP); /* swap if DIG2 */
1060
	if (!Private->RunDualLink) {
1061
	    RHDRegMask(Output, off + RV620_DIG1_CNTL,
1062
		       0,
1063
		       RV62_DIG_SWAP |RV62_DIG_DUAL_LINK_ENABLE);
1064
	} else {
1065
	    RHDRegMask(Output, off + RV620_DIG1_CNTL,
1066
		       RV62_DIG_DUAL_LINK_ENABLE,
1067
		       RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE);
1068
	}
1069
    } else if (Output->Id == RHD_OUTPUT_UNIPHYB) {
1070
	/* select LinkB ?? */
1071
	RHDRegMask(Output, RV620_DCIO_LINK_STEER_CNTL,
1072
		   ((Private->EncoderID == ENCODER_DIG2)
1073
		    ? 0
1074
		    : RV62_LINK_STEER_SWAP), RV62_LINK_STEER_SWAP);
1075
	if (!Private->RunDualLink)
1076
	    RHDRegMask(Output, off + RV620_DIG1_CNTL,
1077
		       0,
1078
		       RV62_DIG_SWAP |  RV62_DIG_DUAL_LINK_ENABLE);
1079
	 else
1080
	    RHDRegMask(Output, off + RV620_DIG1_CNTL,
1081
		       RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE,
1082
		       RV62_DIG_SWAP | RV62_DIG_DUAL_LINK_ENABLE);
1083
    } else { /* LVTMA */
1084
	RHDRegMask(Output, RV620_EXT2_DIFF_POST_DIV_CNTL, 0, RV62_EXT2_DIFF_DRIVER_ENABLE);
1085
    }
1086
 
1087
    if (Private->EncoderMode == LVDS)
1088
	LVDSEncoder(Output);
1089
    else if (Private->EncoderMode == DISPLAYPORT)
1090
      dbgprintf("No displayport support yet!",__FILE__, __LINE__, __func__);  /* bugger ! */
1091
    else
1092
	TMDSEncoder(Output);
1093
 
1094
    /* Start DIG, set links, disable stereo sync, select FMT source */
1095
    RHDRegMask(Output, off + RV620_DIG1_CNTL,
1096
	       (Private->EncoderMode & 0x7) << 8
1097
	       | RV62_DIG_START
1098
	       | (Private->RunDualLink ? RV62_DIG_DUAL_LINK_ENABLE : 0)
1099
	       | Output->Crtc->Id,
1100
	       RV62_DIG_MODE
1101
	       | RV62_DIG_START
1102
	       | RV62_DIG_DUAL_LINK_ENABLE
1103
	       | RV62_DIG_STEREOSYNC_SELECT
1104
	       | RV62_DIG_SOURCE_SELECT);
1105
    rhdPrintDigDebug(rhdPtr,__func__);
1106
}
1107
 
1108
/*
1109
 *
1110
 */
1111
static void
1112
EncoderPower(struct rhdOutput *Output, int Power)
1113
{
1114
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1115
    CARD32 off;
1116
    enum encoderID EncoderID = Private->EncoderID;
1117
    RHDPtr rhdPtr = Output->rhdPtr;
1118
 
1119
    RHDFUNC(Output);
1120
 
1121
    if (EncoderID == ENCODER_NONE) {
1122
	EncoderID = digProbeEncoder(Output);
1123
	switch (EncoderID) {
1124
	    case ENCODER_DIG1:
1125
		if (rhdPtr->DigEncoderOutput[0]) {
1126
		    RHDDebug(Output->scrnIndex,"%s: DIG1 for %s already taken\n",__func__,Output->Name);
1127
		    return;
1128
		}
1129
		break;
1130
	    case ENCODER_DIG2:
1131
		if (rhdPtr->DigEncoderOutput[1]) {
1132
		    RHDDebug(Output->scrnIndex,"%s: DIG2 for %s already taken\n",__func__,Output->Name);
1133
		    return;
1134
		}
1135
		break;
1136
	    default:
1137
		return;
1138
	}
1139
    }
1140
 
1141
    off = (EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1142
 
1143
    /* clock src is pixel PLL */
1144
    RHDRegMask(Output, RV620_DCCG_SYMCLK_CNTL, 0x0,
1145
	       0x3 << ((EncoderID == ENCODER_DIG2)
1146
		       ? RV62_SYMCLKB_SRC_SHIFT
1147
		       : RV62_SYMCLKA_SRC_SHIFT));
1148
 
1149
    rhdPrintDigDebug(rhdPtr,__func__);
1150
    switch (Power) {
1151
	case RHD_POWER_ON:
1152
	    RHDDebug(Output->scrnIndex,"%s(RHD_POWER_ON, %i)\n",__func__,
1153
		     EncoderID);
1154
	    /* enable DIG */
1155
	    RHDRegMask(Output, off + RV620_DIG1_CNTL, 0x10, 0x10);
1156
	    RHDRegMask(Output, (EncoderID == ENCODER_DIG2)
1157
		       ? RV620_DCCG_PCLK_DIGB_CNTL
1158
		       : RV620_DCCG_PCLK_DIGA_CNTL,
1159
		       RV62_PCLK_DIGA_ON, RV62_PCLK_DIGA_ON); /* @@@ */
1160
	    rhdPrintDigDebug(rhdPtr,__func__);
1161
	    return;
1162
	case RHD_POWER_RESET:
1163
	case RHD_POWER_SHUTDOWN:
1164
	default:
1165
	    RHDDebug(Output->scrnIndex,"%s(RHD_POWER_SHUTDOWN, %i)\n",__func__,
1166
		     EncoderID);
1167
	    /* disable differential clock driver */
1168
	    if (EncoderID == ENCODER_DIG1)
1169
		RHDRegMask(Output, RV620_EXT1_DIFF_POST_DIV_CNTL,
1170
			   0,
1171
			   RV62_EXT1_DIFF_DRIVER_ENABLE);
1172
	    else
1173
		RHDRegMask(Output, RV620_EXT2_DIFF_POST_DIV_CNTL,
1174
			   0,
1175
			   RV62_EXT2_DIFF_DRIVER_ENABLE);
1176
	    /* disable DIG */
1177
	    RHDRegMask(Output, off + RV620_DIG1_CNTL, 0x0, 0x10);
1178
	    RHDRegMask(Output, (EncoderID == ENCODER_DIG2)
1179
		       ? RV620_DCCG_PCLK_DIGB_CNTL
1180
		       : RV620_DCCG_PCLK_DIGA_CNTL,
1181
		       0, RV62_PCLK_DIGA_ON); /* @@@ */
1182
	    rhdPrintDigDebug(rhdPtr,__func__);
1183
	    return;
1184
    }
1185
}
1186
 
1187
/*
1188
 *
1189
 */
1190
static void
1191
EncoderSave(struct rhdOutput *Output)
1192
{
1193
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
1194
    struct DIGEncoder *Private = (struct DIGEncoder *)(digPrivate->Encoder.Private);
1195
    CARD32 off;
1196
    enum encoderID EncoderID;
1197
 
1198
    RHDFUNC(Output);
1199
 
1200
    EncoderID = digProbeEncoder(Output);
1201
    off = (EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1202
    Private->StoredOff = off;
1203
 
1204
    Private->StoredRegExt1DiffPostDivCntl          = RHDRegRead(Output, off + RV620_EXT1_DIFF_POST_DIV_CNTL);
1205
    Private->StoredRegExt2DiffPostDivCntl          = RHDRegRead(Output, off + RV620_EXT2_DIFF_POST_DIV_CNTL);
1206
    Private->StoredDIGClockPattern = RHDRegRead(Output, off + RV620_DIG1_CLOCK_PATTERN);
1207
    Private->StoredLVDSDataCntl    = RHDRegRead(Output, off + RV620_LVDS1_DATA_CNTL);
1208
    Private->StoredDIGCntl         = RHDRegRead(Output, off + RV620_DIG1_CNTL);
1209
    Private->StoredTMDSCntl        = RHDRegRead(Output, off + RV620_TMDS1_CNTL);
1210
    Private->StoredDCIOLinkSteerCntl = RHDRegRead(Output, RV620_DCIO_LINK_STEER_CNTL);
1211
    Private->StoredDCCGPclkDigCntl    = RHDRegRead(Output,
1212
						   (off == DIG2_OFFSET)
1213
						   ? RV620_DCCG_PCLK_DIGB_CNTL
1214
						   : RV620_DCCG_PCLK_DIGA_CNTL);
1215
    Private->StoredDCCGSymclkCntl     = RHDRegRead(Output, RV620_DCCG_SYMCLK_CNTL);
1216
    Private->StoredBlModCntl          = RHDRegRead(Output, RV620_LVTMA_BL_MOD_CNTL);
1217
 
1218
    Private->Stored = TRUE;
1219
}
1220
 
1221
/*
1222
 *
1223
 */
1224
static void
1225
EncoderRestore(struct rhdOutput *Output)
1226
{
1227
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
1228
    struct DIGEncoder *Private = (struct DIGEncoder *)(digPrivate->Encoder.Private);
1229
    CARD32 off;
1230
 
1231
    RHDFUNC(Output);
1232
 
1233
    if (!Private->Stored) {
1234
	xf86DrvMsg(Output->scrnIndex, X_ERROR,
1235
		   "%s: No registers stored.\n", __func__);
1236
	return;
1237
    }
1238
    off = Private->StoredOff;
1239
 
1240
    RHDRegWrite(Output, off + RV620_EXT1_DIFF_POST_DIV_CNTL, Private->StoredRegExt1DiffPostDivCntl);
1241
    RHDRegWrite(Output, off + RV620_EXT2_DIFF_POST_DIV_CNTL, Private->StoredRegExt2DiffPostDivCntl);
1242
    /* reprogram all values but don't start the encoder, yet */
1243
    RHDRegWrite(Output, off + RV620_DIG1_CNTL, Private->StoredDIGCntl & ~(CARD32)RV62_DIG_START);
1244
    RHDRegWrite(Output, RV620_DCIO_LINK_STEER_CNTL, Private->StoredDCIOLinkSteerCntl);
1245
    RHDRegWrite(Output, off + RV620_DIG1_CLOCK_PATTERN, Private->StoredDIGClockPattern);
1246
    RHDRegWrite(Output, off + RV620_LVDS1_DATA_CNTL, Private->StoredLVDSDataCntl);
1247
    RHDRegWrite(Output, off + RV620_TMDS1_CNTL, Private->StoredTMDSCntl);
1248
    RHDRegWrite(Output, (off == DIG2_OFFSET)
1249
		? RV620_DCCG_PCLK_DIGB_CNTL
1250
		: RV620_DCCG_PCLK_DIGA_CNTL,
1251
		Private->StoredDCCGPclkDigCntl);
1252
    /* now enable the encoder */
1253
    RHDRegWrite(Output, off + RV620_DIG1_CNTL, Private->StoredDIGCntl);
1254
    RHDRegWrite(Output, RV620_DCCG_SYMCLK_CNTL, Private->StoredDCCGSymclkCntl);
1255
    RHDRegWrite(Output, RV620_LVTMA_BL_MOD_CNTL, Private->StoredBlModCntl);
1256
}
1257
 
1258
/*
1259
 *
1260
 */
1261
static void
1262
EncoderDestroy(struct rhdOutput *Output)
1263
{
1264
    struct DIGPrivate *digPrivate = (struct DIGPrivate *)Output->Private;
1265
 
1266
    RHDFUNC(Output);
1267
 
1268
    if (!digPrivate || !digPrivate->Encoder.Private)
1269
	return;
1270
 
1271
    xfree(digPrivate->Encoder.Private);
1272
}
1273
 
1274
/*
1275
 * Housekeeping
1276
 */
1277
void
1278
GetLVDSInfo(RHDPtr rhdPtr, struct DIGPrivate *Private)
1279
{
1280
    CARD32 off = (Private->EncoderID == ENCODER_DIG2) ? DIG2_OFFSET : DIG1_OFFSET;
1281
    CARD32 tmp;
1282
 
1283
    RHDFUNC(rhdPtr);
1284
 
1285
    Private->FPDI = ((RHDRegRead(rhdPtr, off + RV620_LVDS1_DATA_CNTL)
1286
				 & RV62_LVDS_24BIT_FORMAT) != 0);
1287
    Private->RunDualLink = ((RHDRegRead(rhdPtr, off + RV620_DIG1_CNTL)
1288
				 & RV62_DIG_DUAL_LINK_ENABLE) != 0);
1289
    Private->FMTDither.LVDS24Bit = ((RHDRegRead(rhdPtr, off  + RV620_LVDS1_DATA_CNTL)
1290
			   & RV62_LVDS_24BIT_ENABLE) != 0);
1291
 
1292
    tmp = RHDRegRead(rhdPtr, RV620_LVTMA_BL_MOD_CNTL);
1293
    if (tmp & 0x1)
1294
	Private->BlLevel = ( tmp >> LVTMA_BL_MOD_LEVEL_SHIFT )  & 0xff;
1295
    else
1296
	Private->BlLevel = -1;
1297
 
1298
    tmp = RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_REF_DIV);
1299
    tmp &= 0xffff;
1300
    tmp += 1;
1301
    tmp /= 1000;
1302
    Private->PowerSequenceDig2De = Private->PowerSequenceDe2Bl =
1303
	RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_REF_DIV);
1304
    Private->PowerSequenceDig2De = ((Private->PowerSequenceDig2De & 0xff) * tmp) / 10;
1305
    Private->PowerSequenceDe2Bl = (((Private->PowerSequenceDe2Bl >> 8) & 0xff) * tmp) / 10;
1306
    Private->OffDelay = RHDRegRead(rhdPtr, RV620_LVTMA_PWRSEQ_DELAY2);
1307
    Private->OffDelay *= tmp;
1308
 
1309
    /* This is really ugly! */
1310
    {
1311
	CARD32 fmt_offset;
1312
 
1313
	tmp = RHDRegRead(rhdPtr, off + RV620_DIG1_CNTL);
1314
	fmt_offset = (tmp & RV62_DIG_SOURCE_SELECT) ? FMT2_OFFSET :0;
1315
	tmp = RHDRegRead(rhdPtr, fmt_offset + RV620_FMT1_BIT_DEPTH_CONTROL);
1316
	Private->FMTDither.LVDSSpatialDither = ((tmp & 0x100) != 0);
1317
	Private->FMTDither.LVDSGreyLevel = ((tmp & 0x10000) != 0);
1318
	Private->FMTDither.LVDSTemporalDither
1319
	    = (Private->FMTDither.LVDSGreyLevel > 0) || ((tmp & 0x1000000) != 0);
1320
    }
1321
 
1322
#ifdef ATOM_BIOS
1323
    {
1324
	AtomBiosArgRec data;
1325
 
1326
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1327
				 ATOM_LVDS_FPDI, &data) == ATOM_SUCCESS)
1328
	    Private->FPDI = data.val;
1329
 
1330
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1331
			    ATOM_LVDS_DUALLINK, &data) == ATOM_SUCCESS)
1332
	    Private->RunDualLink = data.val;
1333
 
1334
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1335
			    ATOM_LVDS_GREYLVL, &data) == ATOM_SUCCESS)
1336
	    Private->FMTDither.LVDSGreyLevel = data.val;
1337
 
1338
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1339
			    ATOM_LVDS_SEQ_DIG_ONTO_DE, &data) == ATOM_SUCCESS)
1340
	    Private->PowerSequenceDig2De = data.val;
1341
 
1342
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1343
			    ATOM_LVDS_SEQ_DE_TO_BL, &data) == ATOM_SUCCESS)
1344
	    Private->PowerSequenceDe2Bl = data.val;
1345
 
1346
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1347
			    ATOM_LVDS_OFF_DELAY, &data) == ATOM_SUCCESS)
1348
	    Private->OffDelay = data.val;
1349
 
1350
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1351
			    ATOM_LVDS_24BIT, &data) == ATOM_SUCCESS)
1352
	    Private->FMTDither.LVDS24Bit = data.val;
1353
 
1354
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1355
			    ATOM_LVDS_SPATIAL_DITHER, &data) == ATOM_SUCCESS)
1356
	    Private->FMTDither.LVDSSpatialDither = data.val;
1357
 
1358
    if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS,
1359
			    ATOM_LVDS_TEMPORAL_DITHER, &data) == ATOM_SUCCESS)
1360
	    Private->FMTDither.LVDSTemporalDither = data.val;
1361
 
1362
	Private->PowerSequenceDe2Bl = data.val;
1363
 
1364
    }
1365
#endif
1366
 
1367
}
1368
 
1369
/*
1370
 * Infrastructure
1371
 */
1372
 
1373
static ModeStatus
1374
DigModeValid(struct rhdOutput *Output, DisplayModePtr Mode)
1375
{
1376
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1377
    struct transmitter *Transmitter = &Private->Transmitter;
1378
    struct encoder *Encoder = &Private->Encoder;
1379
    ModeStatus Status;
1380
 
1381
    RHDFUNC(Output);
1382
 
1383
    if ((Status = Transmitter->ModeValid(Output, Mode)) == MODE_OK)
1384
	return ((Encoder->ModeValid(Output, Mode)));
1385
    else
1386
	return Status;
1387
}
1388
 
1389
/*
1390
 *
1391
 */
1392
static void
1393
DigPower(struct rhdOutput *Output, int Power)
1394
{
1395
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1396
    struct transmitter *Transmitter = &Private->Transmitter;
1397
    struct encoder *Encoder = &Private->Encoder;
1398
    Bool enableHDMI;
1399
 
1400
    RHDDebug(Output->scrnIndex, "%s(%s,%s)\n",__func__,Output->Name,
1401
	     rhdPowerString[Power]);
1402
 
1403
    if(Output->Connector != NULL) {
1404
	/* check if attached monitor supports HDMI */
1405
	enableHDMI = RHDConnectorEnableHDMI(Output->Connector);
1406
	if (enableHDMI && Private->EncoderMode == TMDS_DVI)
1407
	    Private->EncoderMode = TMDS_HDMI;
1408
	else if (!enableHDMI && Private->EncoderMode == TMDS_HDMI)
1409
	    Private->EncoderMode = TMDS_DVI;
1410
    }
1411
 
1412
    switch (Power) {
1413
	case RHD_POWER_ON:
1414
	    Encoder->Power(Output, Power);
1415
	    Transmitter->Power(Output, Power);
1416
	    RHDHdmiEnable(Private->Hdmi, Private->EncoderMode == TMDS_HDMI);
1417
	    return;
1418
	case RHD_POWER_RESET:
1419
	    Transmitter->Power(Output, Power);
1420
	    Encoder->Power(Output, Power);
1421
	    return;
1422
	case RHD_POWER_SHUTDOWN:
1423
	default:
1424
	    Transmitter->Power(Output, Power);
1425
	    Encoder->Power(Output, Power);
1426
	    RHDHdmiEnable(Private->Hdmi, FALSE);
1427
	    return;
1428
    }
1429
}
1430
 
1431
/*
1432
 *
1433
 */
1434
static Bool
1435
DigPropertyControl(struct rhdOutput *Output,
1436
			      enum rhdPropertyAction Action, enum rhdOutputProperty Property, union rhdPropertyData *val)
1437
{
1438
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1439
 
1440
    RHDFUNC(Output);
1441
 
1442
    switch(Property) {
1443
	case RHD_OUTPUT_COHERENT:
1444
	case RHD_OUTPUT_BACKLIGHT:
1445
	{
1446
	    if (!Private->Transmitter.Property)
1447
		return FALSE;
1448
	    Private->Transmitter.Property(Output, Action, Property, val);
1449
	    break;
1450
	}
1451
	default:
1452
	    return FALSE;
1453
    }
1454
    return TRUE;
1455
}
1456
 
1457
 
1458
/*
1459
 *
1460
 */
1461
static void
1462
DigMode(struct rhdOutput *Output, DisplayModePtr Mode)
1463
{
1464
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1465
    struct transmitter *Transmitter = &Private->Transmitter;
1466
    struct encoder *Encoder = &Private->Encoder;
1467
    struct rhdCrtc *Crtc = Output->Crtc;
1468
 
1469
    RHDFUNC(Output);
1470
 
1471
    /*
1472
     * For dual link capable DVI we need to decide from the pix clock if we are dual link.
1473
     * Do it here as it is convenient.
1474
     */
1475
    if (Output->Connector->Type == RHD_CONNECTOR_DVI)
1476
	Private->RunDualLink = (Mode->SynthClock > 165000) ? TRUE : FALSE;
1477
 
1478
    Encoder->Mode(Output, Crtc, Mode);
1479
    Transmitter->Mode(Output, Crtc, Mode);
1480
    RHDHdmiSetMode(Private->Hdmi, Mode);
1481
}
1482
 
1483
/*
1484
 *
1485
 */
1486
static void
1487
DigSave(struct rhdOutput *Output)
1488
{
1489
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1490
    struct transmitter *Transmitter = &Private->Transmitter;
1491
    struct encoder *Encoder = &Private->Encoder;
1492
 
1493
    RHDFUNC(Output);
1494
 
1495
    Encoder->Save(Output);
1496
    Transmitter->Save(Output);
1497
    RHDHdmiSave(Private->Hdmi);
1498
}
1499
 
1500
/*
1501
 *
1502
 */
1503
static void
1504
DigRestore(struct rhdOutput *Output)
1505
{
1506
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1507
    struct transmitter *Transmitter = &Private->Transmitter;
1508
    struct encoder *Encoder = &Private->Encoder;
1509
 
1510
    RHDFUNC(Output);
1511
 
1512
    Encoder->Restore(Output);
1513
    Transmitter->Restore(Output);
1514
    RHDHdmiRestore(Private->Hdmi);
1515
}
1516
 
1517
/*
1518
 *
1519
 */
1520
static void
1521
DigDestroy(struct rhdOutput *Output)
1522
{
1523
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1524
    struct transmitter *Transmitter = &Private->Transmitter;
1525
    struct encoder *Encoder = &Private->Encoder;
1526
 
1527
    RHDFUNC(Output);
1528
 
1529
    Encoder->Destroy(Output);
1530
    Transmitter->Destroy(Output);
1531
    RHDHdmiDestroy(Private->Hdmi);
1532
#ifdef NOT_YET
1533
    if (Transmitter->PropertyPrivate)
1534
	RhdAtomDestroyBacklightControlProperty(Output, Transmitter->PropertyPrivate);
1535
#endif
1536
    xfree(Private);
1537
    Output->Private = NULL;
1538
}
1539
 
1540
/*
1541
 *
1542
 */
1543
static Bool
1544
DigAllocFree(struct rhdOutput *Output, enum rhdOutputAllocation Alloc)
1545
{
1546
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1547
    RHDPtr rhdPtr = RHDPTRI(Output);
1548
    char *TransmitterName;
1549
 
1550
    RHDFUNC(rhdPtr);
1551
 
1552
    switch (Output->Id) {
1553
	case RHD_OUTPUT_KLDSKP_LVTMA:
1554
	    TransmitterName = "KLDSKP_LVTMA";
1555
	    break;
1556
	case RHD_OUTPUT_UNIPHYA:
1557
	    TransmitterName = "UNIPHYA";
1558
	    break;
1559
	case RHD_OUTPUT_UNIPHYB:
1560
	    TransmitterName = "UNIPHYB";
1561
	    break;
1562
	default:
1563
	    return FALSE;
1564
    }
1565
    switch (Alloc) {
1566
	case RHD_OUTPUT_ALLOC:
1567
 
1568
	    if (Private->EncoderID != ENCODER_NONE)
1569
		return TRUE;
1570
 
1571
	    /*
1572
	     * LVTMA can only use DIG2. Thus exclude
1573
	     * DIG1 for LVTMA and prefer it for the
1574
	     * UNIPHYs.
1575
	     */
1576
	    if (Output->Id == RHD_OUTPUT_KLDSKP_LVTMA) {
1577
		if (!rhdPtr->DigEncoderOutput[1]) {
1578
		    rhdPtr->DigEncoderOutput[1] = Output;
1579
		    Private->EncoderID = ENCODER_DIG2;
1580
		    xf86DrvMsg(Output->scrnIndex, X_INFO,
1581
			       "Mapping DIG2 encoder to %s\n",TransmitterName);
1582
		return TRUE;
1583
		} else
1584
		    return FALSE;
1585
	    } else {
1586
		struct ATOMTransmitterPrivate *transPrivate =
1587
		    (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
1588
		struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
1589
		if (!rhdPtr->DigEncoderOutput[0]) {
1590
		    rhdPtr->DigEncoderOutput[0] = Output;
1591
		    Private->EncoderID = ENCODER_DIG1;
1592
		    atc->Encoder = atomEncoderDIG1;
1593
		    xf86DrvMsg(Output->scrnIndex, X_INFO,
1594
			       "Mapping DIG1 encoder to %s\n",TransmitterName);
1595
		    return TRUE;
1596
		} else if (!rhdPtr->DigEncoderOutput[1]) {
1597
		    rhdPtr->DigEncoderOutput[1] = Output;
1598
		    Private->EncoderID = ENCODER_DIG2;
1599
		    atc->Encoder = atomEncoderDIG2;
1600
		    xf86DrvMsg(Output->scrnIndex, X_INFO,
1601
			       "Mapping DIG2 encoder to %s\n",TransmitterName);
1602
		    return TRUE;
1603
		} else
1604
		    return FALSE;
1605
	    }
1606
 
1607
	case RHD_OUTPUT_FREE:
1608
		Private->EncoderID = ENCODER_NONE;
1609
	    if (rhdPtr->DigEncoderOutput[0] == Output) {
1610
		rhdPtr->DigEncoderOutput[0] = NULL;
1611
		return TRUE;
1612
	    } else if (rhdPtr->DigEncoderOutput[1] == Output) {
1613
		rhdPtr->DigEncoderOutput[1] = NULL;
1614
		return TRUE;
1615
	    } else
1616
		return FALSE;
1617
	    break;
1618
	default:
1619
	    return FALSE;
1620
    }
1621
}
1622
 
1623
/*
1624
 *
1625
 */
1626
static Bool
1627
rhdDIGSetCoherent(RHDPtr rhdPtr,struct rhdOutput *Output)
1628
{
1629
    Bool coherent = FALSE;
1630
//    int  from = X_CONFIG;
1631
 
1632
//    switch (RhdParseBooleanOption(&rhdPtr->coherent, Output->Name)) {
1633
//    case RHD_OPTION_NOT_SET:
1634
//    case RHD_OPTION_DEFAULT:
1635
//        from = X_DEFAULT;
1636
//        coherent = FALSE;
1637
//        break;
1638
//    case RHD_OPTION_ON:
1639
//        coherent = TRUE;
1640
//        break;
1641
//    case RHD_OPTION_OFF:
1642
//        coherent = FALSE;
1643
//        break;
1644
//    }
1645
//    xf86DrvMsg(rhdPtr->scrnIndex,from,"Setting %s to %scoherent\n",
1646
//           Output->Name,coherent ? "" : "in");
1647
 
1648
    return coherent;
1649
}
1650
 
1651
/*
1652
 *
1653
 */
1654
#ifdef NOT_YET
1655
static Bool
1656
digTransmitterPropertyWrapper(struct rhdOutput *Output,
1657
			      enum rhdPropertyAction Action,
1658
			      enum rhdOutputProperty Property,
1659
			      union rhdPropertyData *val)
1660
{
1661
    struct DIGPrivate *Private = (struct DIGPrivate *)Output->Private;
1662
    void *storePrivate = Output->Private;
1663
    Bool (*func)(struct rhdOutput *,enum rhdPropertyAction, enum rhdOutputProperty,
1664
		  union rhdPropertyData *) = Private->Transmitter.WrappedPropertyCallback;
1665
    Bool ret;
1666
 
1667
    Output->Private = Private->Transmitter.PropertyPrivate;
1668
    ret = func(Output, Action, Property, val);
1669
    Output->Private = storePrivate;
1670
 
1671
    return ret;
1672
}
1673
#endif
1674
 
1675
/*
1676
 *
1677
 */
1678
struct rhdOutput *
1679
RHDDIGInit(RHDPtr rhdPtr,  enum rhdOutputType outputType, CARD8 ConnectorType)
1680
{
1681
    struct rhdOutput *Output;
1682
    struct DIGPrivate *Private;
1683
    struct DIGEncoder *Encoder;
1684
 
1685
    RHDFUNC(rhdPtr);
1686
 
1687
    Output = xnfcalloc(sizeof(struct rhdOutput), 1);
1688
 
1689
    Output->scrnIndex = rhdPtr->scrnIndex;
1690
    Output->Id = outputType;
1691
 
1692
    Output->Sense = NULL;
1693
    Output->ModeValid = DigModeValid;
1694
    Output->Mode = DigMode;
1695
    Output->Power = DigPower;
1696
    Output->Save = DigSave;
1697
    Output->Restore = DigRestore;
1698
    Output->Destroy = DigDestroy;
1699
    Output->Property = DigPropertyControl;
1700
    Output->AllocFree = DigAllocFree;
1701
 
1702
    Private = xnfcalloc(sizeof(struct DIGPrivate), 1);
1703
    Output->Private = Private;
1704
 
1705
    Private->EncoderID = ENCODER_NONE;
1706
 
1707
    switch (outputType) {
1708
	case RHD_OUTPUT_UNIPHYA:
1709
#if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
1710
	    Output->Name = "UNIPHY_A";
1711
	    Private->Transmitter.Private =
1712
		(struct ATOMTransmitterPrivate *)xnfcalloc(sizeof (struct ATOMTransmitterPrivate), 1);
1713
 
1714
	    Private->Transmitter.Sense = NULL;
1715
	    Private->Transmitter.ModeValid = ATOMTransmitterModeValid;
1716
	    Private->Transmitter.Mode = ATOMTransmitterSet;
1717
	    Private->Transmitter.Power = ATOMTransmitterPower;
1718
	    Private->Transmitter.Save = ATOMTransmitterSave;
1719
	    Private->Transmitter.Restore = ATOMTransmitterRestore;
1720
	    Private->Transmitter.Destroy = ATOMTransmitterDestroy;
1721
	    Private->Transmitter.Property = TMDSTransmitterPropertyControl;
1722
	    {
1723
		struct ATOMTransmitterPrivate *transPrivate =
1724
		    (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
1725
		struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
1726
		atc->Coherent = Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
1727
		atc->Link = atomTransLinkA;
1728
		atc->Encoder = atomEncoderNone;
1729
		if (RHDIsIGP(rhdPtr->ChipSet)) {
1730
		    AtomBiosArgRec data;
1731
		    data.val = 1;
1732
            if (RHDAtomBiosFunc(rhdPtr, rhdPtr->atomBIOS, ATOM_GET_PCIE_LANES,
1733
					&data) == ATOM_SUCCESS)
1734
			atc->Lanes = data.pcieLanes.Chassis; /* only do 'chassis' for now */
1735
		    else {
1736
			xfree(Private);
1737
			xfree(Output);
1738
			return NULL;
1739
		    }
1740
		}
1741
		if (RHDIsIGP(rhdPtr->ChipSet))
1742
		    transPrivate->atomTransmitterID = atomTransmitterPCIEPHY;
1743
		else
1744
		    transPrivate->atomTransmitterID = atomTransmitterUNIPHY;
1745
	    }
1746
	    break;
1747
#else
1748
	    xfree(Private);
1749
	    xfree(Output);
1750
	    return NULL;
1751
#endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
1752
 
1753
	case RHD_OUTPUT_UNIPHYB:
1754
#if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
1755
	    Output->Name = "UNIPHY_B";
1756
	    Private->Transmitter.Private =
1757
		(struct atomTransmitterPrivate *)xnfcalloc(sizeof (struct ATOMTransmitterPrivate), 1);
1758
 
1759
	    Private->Transmitter.Sense = NULL;
1760
	    Private->Transmitter.ModeValid = ATOMTransmitterModeValid;
1761
	    Private->Transmitter.Mode = ATOMTransmitterSet;
1762
	    Private->Transmitter.Power = ATOMTransmitterPower;
1763
	    Private->Transmitter.Save = ATOMTransmitterSave;
1764
	    Private->Transmitter.Restore = ATOMTransmitterRestore;
1765
	    Private->Transmitter.Destroy = ATOMTransmitterDestroy;
1766
	    Private->Transmitter.Property = TMDSTransmitterPropertyControl;
1767
	    {
1768
		struct ATOMTransmitterPrivate *transPrivate =
1769
		    (struct ATOMTransmitterPrivate *)Private->Transmitter.Private;
1770
		struct atomTransmitterConfig *atc = &transPrivate->atomTransmitterConfig;
1771
		atc->Coherent = Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
1772
		atc->Link = atomTransLinkB;
1773
		atc->Encoder = atomEncoderNone;
1774
		if (RHDIsIGP(rhdPtr->ChipSet)) {
1775
		    AtomBiosArgRec data;
1776
		    data.val = 2;
1777
		    if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_GET_PCIE_LANES,
1778
					&data) == ATOM_SUCCESS)
1779
			atc->Lanes = data.pcieLanes.Chassis; /* only do 'chassis' for now */
1780
		    else {
1781
			xfree(Private);
1782
			xfree(Output);
1783
			return NULL;
1784
		    }
1785
		}
1786
		if (RHDIsIGP(rhdPtr->ChipSet))
1787
		    transPrivate->atomTransmitterID = atomTransmitterPCIEPHY;
1788
		else
1789
		    transPrivate->atomTransmitterID = atomTransmitterUNIPHY;
1790
	    }
1791
	    break;
1792
#else
1793
	    xfree(Private);
1794
	    xfree(Output);
1795
	    return NULL;
1796
#endif /* ATOM_BIOS && ATOM_BIOS_PARSER */
1797
 
1798
	case RHD_OUTPUT_KLDSKP_LVTMA:
1799
	    Output->Name = "UNIPHY_KLDSKP_LVTMA";
1800
	    Private->Coherent = rhdDIGSetCoherent(rhdPtr, Output);
1801
	    Private->Transmitter.Private =
1802
		(struct LVTMATransmitterPrivate *)xnfcalloc(sizeof (struct LVTMATransmitterPrivate), 1);
1803
 
1804
	    Private->Transmitter.Sense = NULL;
1805
	    Private->Transmitter.ModeValid = LVTMATransmitterModeValid;
1806
	    if (ConnectorType != RHD_CONNECTOR_PANEL) {
1807
		Private->Transmitter.Mode = LVTMA_TMDSTransmitterSet;
1808
		Private->Transmitter.Power = LVTMA_TMDSTransmitterPower;
1809
		Private->Transmitter.Save = LVTMA_TMDSTransmitterSave;
1810
		Private->Transmitter.Restore = LVTMA_TMDSTransmitterRestore;
1811
	    } else {
1812
		Private->Transmitter.Mode = LVTMA_LVDSTransmitterSet;
1813
		Private->Transmitter.Power = LVTMA_LVDSTransmitterPower;
1814
		Private->Transmitter.Save = LVTMA_LVDSTransmitterSave;
1815
		Private->Transmitter.Restore = LVTMA_LVDSTransmitterRestore;
1816
	    }
1817
	    Private->Transmitter.Destroy = LVTMATransmitterDestroy;
1818
	    if (ConnectorType == RHD_CONNECTOR_PANEL)
1819
		Private->Transmitter.Property = LVDSTransmitterPropertyControl;
1820
	    else
1821
		Private->Transmitter.Property = TMDSTransmitterPropertyControl;
1822
	    break;
1823
 
1824
	default:
1825
	    xfree(Private);
1826
	    xfree(Output);
1827
	    return NULL;
1828
    }
1829
 
1830
    Encoder = (struct DIGEncoder *)(xnfcalloc(sizeof (struct DIGEncoder),1));
1831
    Private->Encoder.Private = Encoder;
1832
    Private->Encoder.ModeValid = EncoderModeValid;
1833
    Private->Encoder.Mode = EncoderSet;
1834
    Private->Encoder.Power = EncoderPower;
1835
    Private->Encoder.Save = EncoderSave;
1836
    Private->Encoder.Restore = EncoderRestore;
1837
    Private->Encoder.Destroy = EncoderDestroy;
1838
 
1839
    switch (ConnectorType) {
1840
	case RHD_CONNECTOR_PANEL:
1841
	    Private->EncoderMode = LVDS;
1842
	    GetLVDSInfo(rhdPtr, Private);
1843
#ifdef ATOM_BIOS
1844
#ifdef NOT_YET
1845
	    if (Private->BlLevel < 0) {
1846
		Private->BlLevel = RhdAtomSetupBacklightControlProperty(Output,
1847
									&Private->Transmitter.WrappedPropertyCallback,
1848
									&Private->Transmitter.PropertyPrivate);
1849
		if (Private->Transmitter.PropertyPrivate)
1850
		    Private->Transmitter.Property = digTransmitterPropertyWrapper;
1851
	    }
1852
#endif
1853
#endif
1854
	    Private->Hdmi = NULL;
1855
	    break;
1856
	case RHD_CONNECTOR_DVI:
1857
	    Private->RunDualLink = FALSE; /* will be set later acc to pxclk */
1858
	    Private->EncoderMode = TMDS_DVI;
1859
	    Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
1860
	    break;
1861
	case RHD_CONNECTOR_DVI_SINGLE:
1862
	    Private->RunDualLink = FALSE;
1863
	    Private->EncoderMode = TMDS_DVI; /* changed later to HDMI if aplicateable */
1864
	    Private->Hdmi = RHDHdmiInit(rhdPtr, Output);
1865
	    break;
1866
    }
1867
 
1868
    return Output;
1869
}