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_pll.h"
42
#include "rhd_connector.h"
43
#include "rhd_output.h"
44
#include "rhd_crtc.h"
45
#include "rhd_regs.h"
46
#if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER)
47
# include "rhd_atombios.h"
48
# include "rhd_biosscratch.h"
49
 
50
struct atomPLLPrivate {
51
    enum atomPxclk Pxclk;
52
    struct atomPixelClockConfig Config;
53
    struct atomCodeTableVersion Version;
54
 
55
    CARD32 StoreFBDivFrac;
56
    enum atomDevice StoreDevice;
57
    enum rhdConnectorType StoreConnectorType;
58
    enum rhdOutputType StoreOutputType;
59
    int StoreCrtc;
60
};
61
 
62
/*
63
 *
64
 */
65
static void
66
getSetPixelClockParameters(struct rhdPLL *PLL, struct atomPixelClockConfig *Config,
67
			   enum rhdConnectorType ct, enum rhdOutputType ot, enum atomDevice device)
68
{
69
    RHDPtr rhdPtr = RHDPTRI(PLL);
70
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
71
 
72
    switch (Private->Version.cref) {
73
	case 1:
74
	    break;
75
	case 2:
76
	    Config->u.v2.Device = device;
77
	    Config->u.v2.Force = TRUE;
78
	    break;
79
	case 3:
80
	    switch (ct) {
81
		case RHD_CONNECTOR_VGA:
82
		    Config->u.v3.EncoderMode = atomNoEncoder;
83
		    break;
84
		case RHD_CONNECTOR_DVI:
85
		case RHD_CONNECTOR_DVI_SINGLE:
86
		    Config->u.v3.EncoderMode = atomDVI;
87
		    break;
88
		case RHD_CONNECTOR_PANEL:
89
		    Config->u.v3.EncoderMode = atomLVDS;
90
		    break;
91
#if 0
92
		case RHD_CONNECTOR_DP:
93
		case RHD_CONNECTOR_DP_DUAL:
94
		    Config->u.v3.EncoderMode = atomDP;
95
		    break;
96
		case RHD_CONNECTOR_HDMI_A:
97
		case RHD_CONNECTOR_HDMI_B:
98
		    Config->u.v3.EncoderMode = atomHDMI;
99
		    break;
100
#endif
101
		default:
102
		    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Unknown connector type: 0x%x\n",__func__,ct);
103
	    }
104
	    switch (ot) {
105
		case RHD_OUTPUT_DACA:
106
		    Config->u.v3.OutputType = atomOutputDacA;
107
		    break;
108
		case RHD_OUTPUT_DACB:
109
		    Config->u.v3.OutputType = atomOutputDacB;
110
		    break;
111
		case RHD_OUTPUT_KLDSKP_LVTMA:
112
		    Config->u.v3.OutputType = atomOutputKldskpLvtma;
113
		    break;
114
		case RHD_OUTPUT_UNIPHYA:
115
		    Config->u.v3.OutputType = atomOutputUniphyA;
116
		    break;
117
		case RHD_OUTPUT_UNIPHYB:
118
		    Config->u.v3.OutputType = atomOutputUniphyB;
119
		    break;
120
		case RHD_OUTPUT_UNIPHYC:
121
		    Config->u.v3.OutputType = atomOutputUniphyC;
122
		    break;
123
		case RHD_OUTPUT_UNIPHYD:
124
		    Config->u.v3.OutputType = atomOutputUniphyD;
125
		    break;
126
		case RHD_OUTPUT_UNIPHYE:
127
		    Config->u.v3.OutputType = atomOutputUniphyE;
128
		    break;
129
		case RHD_OUTPUT_UNIPHYF:
130
		    Config->u.v3.OutputType = atomOutputUniphyF;
131
		    break;
132
		case RHD_OUTPUT_DVO:
133
		    Config->u.v3.OutputType = atomOutputDvo;
134
		    break;
135
		default:
136
		    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: Unhandled ouptut type\n",__func__);
137
		    break;
138
	    }
139
	    Config->u.v3.Force = TRUE;
140
	    Config->u.v3.UsePpll = FALSE;
141
	    break;
142
	default:
143
	    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Unsupported SelectPixelClock version: %i\n",Private->Version.cref);
144
	    break;
145
    }
146
}
147
 
148
/*
149
 *
150
 */
151
static void
152
rhdAtomPLLSave(struct rhdPLL *PLL, CARD32 PllCntl, CARD32 OwnerVal)
153
{
154
    RHDPtr rhdPtr = RHDPTRI(PLL);
155
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
156
    CARD32 Crtc1Cntl, Crtc2Cntl;
157
    enum atomCrtc owner;
158
 
159
    RHDFUNC(PLL);
160
 
161
    Crtc1Cntl = RHDRegRead(PLL, PCLK_CRTC1_CNTL);
162
    Crtc2Cntl = RHDRegRead(PLL, PCLK_CRTC2_CNTL);
163
 
164
    if (PllCntl & 0x2)
165
	PLL->StoreActive = FALSE;
166
    else
167
	PLL->StoreActive = TRUE;
168
 
169
    if ((Crtc1Cntl & 0x00010000) == OwnerVal)
170
	owner = atomCrtc1;
171
    else if ((Crtc2Cntl & 0x00010000) == OwnerVal)
172
	owner = atomCrtc2;
173
    else {
174
	owner = atomCrtc1; /* whatever... */
175
	PLL->StoreActive = FALSE;
176
    }
177
 
178
    Private->StoreCrtc = owner;
179
    Private->StoreDevice = RHDGetDeviceOnCrtc(rhdPtr, owner);
180
 
181
    if (Private->StoreDevice != atomNone)
182
	RHDFindConnectorAndOutputTypesForDevice(rhdPtr, Private->StoreDevice,
183
						&Private->StoreOutputType, &Private->StoreConnectorType);
184
    else
185
	PLL->StoreActive = FALSE;
186
 
187
    RHDDebug(PLL->scrnIndex, "Saving PLL %i on CRTC: %i %s active - device: 0x%x\n",
188
	     (PLL->Id == PLL_ID_PLL1) ? 1 : 2,
189
	     (owner == atomCrtc1) ? 1 : 2,
190
	     (PLL->StoreActive) ? "" : "not",
191
	     Private->StoreDevice);
192
 
193
    PLL->Stored = TRUE;
194
 
195
    /* Set parameters found at startup for shutdownInactive(). This is somewhat ugly... */
196
    Private->Config.Crtc = Private->StoreCrtc;
197
    Private->Config.Enable = PLL->StoreActive;
198
    if (Private->StoreDevice != atomNone)
199
	getSetPixelClockParameters(PLL, &Private->Config, Private->StoreConnectorType,
200
				   Private->StoreOutputType, Private->StoreDevice);
201
}
202
 
203
/*
204
 *
205
 */
206
static void
207
rhdAtomPLL1Save(struct rhdPLL *PLL)
208
{
209
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
210
    CARD32 PllCntl;
211
 
212
    RHDFUNC(PLL);
213
 
214
    PLL->StoreSpreadSpectrum = RHDRegRead(PLL, P1PLL_INT_SS_CNTL);
215
    PLL->StoreRefDiv   = RHDRegRead(PLL, EXT1_PPLL_REF_DIV) & 0x1FF;
216
    PLL->StoreFBDiv    = (RHDRegRead(PLL, EXT1_PPLL_FB_DIV) >> 16) & 0x7FF;
217
    Private->StoreFBDivFrac = RHDRegRead(PLL, EXT1_PPLL_FB_DIV) & 0x7;
218
    PLL->StorePostDiv  = RHDRegRead(PLL, EXT1_PPLL_POST_DIV) & 0x3F;
219
    PllCntl = RHDRegRead(PLL, P1PLL_CNTL);
220
    RHDDebug(PLL->scrnIndex, "Saving %i kHz clock on PLL1\n",
221
	     ((PLL->StoreFBDiv * PLL->RefClock * 10)
222
	      / (PLL->StorePostDiv * PLL->StoreRefDiv)));
223
 
224
    rhdAtomPLLSave(PLL, PllCntl, 0x00000000);
225
}
226
 
227
 
228
/*
229
 *
230
 */
231
static void
232
rhdAtomPLL2Save(struct rhdPLL *PLL)
233
{
234
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
235
    CARD32 PllCntl;
236
 
237
    RHDFUNC(PLL);
238
 
239
    PLL->StoreSpreadSpectrum = RHDRegRead(PLL, P2PLL_INT_SS_CNTL);
240
    PLL->StoreRefDiv   = RHDRegRead(PLL, EXT2_PPLL_REF_DIV) & 0x1FF;
241
    PLL->StoreFBDiv    = (RHDRegRead(PLL, EXT2_PPLL_FB_DIV) >> 16) & 0x7FF;
242
    Private->StoreFBDivFrac = RHDRegRead(PLL, EXT2_PPLL_FB_DIV) & 0x7;
243
    PLL->StorePostDiv  = RHDRegRead(PLL, EXT2_PPLL_POST_DIV) & 0x3F;
244
    PllCntl = RHDRegRead(PLL, P2PLL_CNTL);
245
    RHDDebug(PLL->scrnIndex, "Saving %i kHz clock on PLL2\n",
246
	     ((PLL->StoreFBDiv * PLL->RefClock * 10)
247
	      / (PLL->StorePostDiv * PLL->StoreRefDiv)));
248
 
249
    rhdAtomPLLSave(PLL, PllCntl, 0x00010000);
250
}
251
 
252
/*
253
 *
254
 */
255
static void
256
rhdAtomPLLRestore(struct rhdPLL *PLL)
257
{
258
    RHDPtr rhdPtr = RHDPTRI(PLL);
259
    struct atomPixelClockConfig Config;
260
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
261
 
262
    RHDFUNC(PLL);
263
 
264
    if (!PLL->Stored) {
265
	xf86DrvMsg(PLL->scrnIndex, X_ERROR, "%s: %s: trying to restore "
266
		   "uninitialized values.\n", __func__, PLL->Name);
267
	return;
268
    }
269
    Config.PixelClock = PLL->StoreActive
270
	? ((PLL->StoreFBDiv * PLL->RefClock * 10) / (PLL->StorePostDiv * PLL->StoreRefDiv))
271
	: 0;
272
 
273
    Config.Enable = PLL->StoreActive;
274
    Config.RefDiv = PLL->StoreRefDiv;
275
    Config.FbDiv = PLL->StoreFBDiv;
276
    Config.PostDiv = PLL->StorePostDiv;
277
    Config.FracFbDiv = Private->StoreFBDivFrac;
278
    Config.Crtc = Private->StoreCrtc;
279
 
280
    if (Private->StoreDevice != atomNone)
281
	getSetPixelClockParameters(PLL, &Config, Private->StoreConnectorType,
282
				   Private->StoreOutputType, Private->StoreDevice);
283
    RHDDebug(PLL->scrnIndex, "Restoring PixelClock %i with %i kHz, (%i * %i) / ( %i * %i )"
284
	     " on CRTC %i device: %x\n",
285
	     Private->Pxclk, Config.PixelClock, PLL->RefClock, PLL->StoreFBDiv, PLL->StorePostDiv,
286
	     PLL->StoreRefDiv, (Config.Crtc == atomCrtc1) ? 1 : 2, Config.u.v2.Device);
287
 
288
    /* Restore spread spectrum: AtomBIOS doesn't handle this for us */
289
    RHDRegWrite(PLL, (PLL->Id == PLL_ID_PLL1) ? P1PLL_INT_SS_CNTL : P2PLL_INT_SS_CNTL, PLL->StoreSpreadSpectrum);
290
 
291
    rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, &Config);
292
}
293
 
294
/*
295
 *
296
 */
297
static void
298
rhdAtomPLLPower(struct rhdPLL *PLL, int Power)
299
{
300
    RHDPtr rhdPtr = RHDPTRI(PLL);
301
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
302
    struct atomPixelClockConfig *config = &Private->Config;
303
 
304
    RHDFUNC(PLL);
305
 
306
    switch (Power) {
307
	case RHD_POWER_ON:
308
	    if (config->PixelClock > 0)
309
		config->Enable = TRUE;
310
	    else {
311
		xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR,
312
			   "%s: cannot enable pixel clock without frequency set\n",__func__);
313
		config->Enable = FALSE;
314
	    }
315
	    break;
316
	case RHD_POWER_RESET:
317
	case RHD_POWER_SHUTDOWN:
318
	    return;
319
	    config->Enable = FALSE;
320
	default:
321
	    break;
322
    }
323
    rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, config);
324
}
325
 
326
/*
327
 *
328
 */
329
static void
330
rhdAtomPLLSet(struct rhdPLL *PLL, int PixelClock, CARD16 ReferenceDivider,
331
	    CARD16 FeedbackDivider, CARD8 PostDivider)
332
{
333
    RHDPtr rhdPtr = RHDPTRI(PLL);
334
    struct atomPLLPrivate *Private = (struct atomPLLPrivate *)PLL->Private;
335
    struct rhdCrtc *Crtc = NULL;
336
 
337
    RHDFUNC(PLL);
338
    RHDDebug(rhdPtr->scrnIndex, "%s: %i kHz RefDiv: %x FeedbackDiv: %x PostDiv: %x\n",
339
	     __func__, PixelClock, ReferenceDivider, FeedbackDivider, PostDivider);
340
 
341
    Private->Config.PixelClock = PixelClock;
342
    Private->Config.RefDiv = ReferenceDivider;
343
    Private->Config.FbDiv = FeedbackDivider;
344
    Private->Config.PostDiv = PostDivider;
345
    Private->Config.FracFbDiv = 0;
346
    if (rhdPtr->Crtc[0]->PLL == PLL) {
347
	Private->Config.Crtc = atomCrtc1;
348
	Crtc = rhdPtr->Crtc[0];
349
    } else if (rhdPtr->Crtc[1]->PLL == PLL) {
350
	Private->Config.Crtc = atomCrtc2;
351
	Crtc = rhdPtr->Crtc[1];
352
    } else
353
	xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Trying to set an unassigned PLL\n");
354
 
355
    if (Crtc && Private->Version.cref > 1) {
356
	struct rhdOutput *Output;
357
	for (Output = rhdPtr->Outputs; Output; Output = Output->Next) {
358
	    if (Output->Crtc == Crtc)
359
		break;
360
	}
361
	if (Output)
362
	    getSetPixelClockParameters(PLL, &Private->Config,
363
				      Output->Connector->Type, Output->Id,
364
				      Output->OutputDriverPrivate->Device);
365
    }
366
 
367
    /* Disable spread spectrum. AtomBIOS doesn't do this for us */
368
    RHDRegMask(PLL, (PLL->Id == PLL_ID_PLL1) ? P1PLL_INT_SS_CNTL : P2PLL_INT_SS_CNTL, 0, 0x00000001);
369
 
370
    Private->Config.Enable = TRUE;
371
    rhdAtomSetPixelClock(rhdPtr->atomBIOS, Private->Pxclk, &Private->Config);
372
}
373
 
374
/*
375
 *
376
 */
377
Bool
378
RHDAtomPLLsInit(RHDPtr rhdPtr)
379
{
380
    struct rhdPLL *PLL;
381
    struct atomPLLPrivate *Private;
382
    CARD32 RefClock, IntMin, IntMax, PixMin, PixMax;
383
    int i;
384
 
385
    RHDFUNC(rhdPtr);
386
 
387
    RHDSetupLimits(rhdPtr, &RefClock, &IntMin, &IntMax, &PixMin, &PixMax);
388
 
389
    for (i = 0; i < 2; i++) {
390
 
391
	PLL = (struct rhdPLL *) xnfcalloc(sizeof(struct rhdPLL), 1);
392
	Private = (struct atomPLLPrivate *) xnfcalloc(sizeof(struct atomPLLPrivate),1);
393
	PLL->Private = Private;
394
 
395
	Private->Version = rhdAtomSetPixelClockVersion(rhdPtr->atomBIOS);
396
	if (Private->Version.cref > 3) {
397
	    xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "Unsupported SelectPixelClock version; %i\n",
398
		       Private->Version.cref);
399
	    xfree(PLL->Private);
400
	    xfree(PLL);
401
	    return FALSE;
402
	}
403
 
404
	PLL->scrnIndex = rhdPtr->scrnIndex;
405
	if (i == 0) {
406
	    PLL->Name = PLL_NAME_PLL1;
407
	    PLL->Id = PLL_ID_PLL1;
408
	    PLL->Save = rhdAtomPLL1Save;
409
	    Private->Pxclk = atomPclk1;
410
	} else {
411
	    PLL->Name = PLL_NAME_PLL2;
412
	    PLL->Id = PLL_ID_PLL2;
413
	    PLL->Save = rhdAtomPLL2Save;
414
	    Private->Pxclk = atomPclk2;
415
	}
416
 
417
	PLL->RefClock = RefClock;
418
	PLL->IntMin = IntMin;
419
	PLL->IntMax = IntMax;
420
	PLL->PixMin = PixMin;
421
	PLL->PixMax = PixMax;
422
 
423
	PLL->Valid = NULL;
424
 
425
	PLL->Set = rhdAtomPLLSet;
426
	PLL->Power = rhdAtomPLLPower;
427
	PLL->Restore = rhdAtomPLLRestore;
428
 
429
	rhdPtr->PLLs[i] = PLL;
430
    }
431
 
432
 
433
    return TRUE;
434
}
435
 
436
#endif /* ATOM_BIOS && ATOM_BIOS_PARSER */