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 | #if HAVE_XF86_ANSIC_H |
||
33 | # include "xf86_ansic.h" |
||
34 | #else |
||
35 | # include |
||
36 | #endif |
||
37 | |||
38 | #include "rhd.h" |
||
39 | #include "rhd_crtc.h" |
||
40 | #include "rhd_pll.h" |
||
41 | #include "rhd_lut.h" |
||
42 | #include "rhd_regs.h" |
||
43 | #include "rhd_modes.h" |
||
44 | #include "rhd_mc.h" |
||
45 | #if defined (ATOM_BIOS) && defined (ATOM_BIOS_PARSER) |
||
46 | # include "rhd_atombios.h" |
||
47 | |||
48 | # define D1_REG_OFFSET 0x0000 |
||
49 | # define D2_REG_OFFSET 0x0800 |
||
50 | |||
51 | struct rhdCrtcScalePrivate { |
||
52 | void *RegList; |
||
53 | CARD32 StoreViewportSize; |
||
54 | CARD32 StoreViewportStart; |
||
55 | }; |
||
56 | |||
57 | /* |
||
58 | * |
||
59 | */ |
||
60 | static void |
||
61 | rhdAtomCrtcRestore(struct rhdCrtc *Crtc, void *Store) |
||
62 | { |
||
63 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
64 | union AtomBiosArg data; |
||
65 | |||
66 | RHDFUNC(rhdPtr); |
||
67 | |||
68 | data.Address = Store; |
||
69 | RHDAtomBiosFunc(Crtc->scrnIndex, rhdPtr->atomBIOS, ATOM_RESTORE_REGISTERS, &data); |
||
70 | } |
||
71 | |||
72 | /* |
||
73 | * |
||
74 | */ |
||
75 | static void |
||
76 | rhdAtomScaleSet(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type, |
||
77 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
78 | { |
||
79 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
80 | struct rhdScalerOverscan Overscan; |
||
81 | struct atomCrtcOverscan AtomOverscan; |
||
82 | enum atomCrtc AtomCrtc = RHD_CRTC_1; |
||
83 | enum atomScaler Scaler = 0; |
||
84 | enum atomScaleMode ScaleMode = 0; |
||
85 | union AtomBiosArg data; |
||
86 | CARD32 RegOff = 0; |
||
87 | |||
88 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s viewport: %ix%i\n", __func__, Crtc->Name, |
||
89 | Mode->CrtcHDisplay, Mode->CrtcVDisplay); |
||
90 | |||
91 | /* D1Mode registers */ |
||
92 | if (Crtc->Id == RHD_CRTC_1) |
||
93 | RegOff = D1_REG_OFFSET; |
||
94 | else |
||
95 | RegOff = D2_REG_OFFSET; |
||
96 | |||
97 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, |
||
98 | Mode->CrtcVDisplay | (Mode->CrtcHDisplay << 16)); |
||
99 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, 0); |
||
100 | |||
101 | Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type); |
||
102 | Type = Overscan.Type; |
||
103 | |||
104 | ASSERT(Crtc->ScalePriv); |
||
105 | data.Address = &((Crtc->ScalePriv)->RegList); |
||
106 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
107 | |||
108 | AtomOverscan.ovscnLeft = Overscan.OverscanLeft; |
||
109 | AtomOverscan.ovscnRight = Overscan.OverscanRight; |
||
110 | AtomOverscan.ovscnTop = Overscan.OverscanTop; |
||
111 | AtomOverscan.ovscnBottom = Overscan.OverscanBottom; |
||
112 | |||
113 | switch (Crtc->Id) { |
||
114 | case RHD_CRTC_1: |
||
115 | Scaler = atomScaler1; |
||
116 | AtomCrtc = atomCrtc1; |
||
117 | break; |
||
118 | case RHD_CRTC_2: |
||
119 | Scaler = atomScaler2; |
||
120 | AtomCrtc = atomCrtc2; |
||
121 | break; |
||
122 | } |
||
123 | |||
124 | rhdAtomSetCRTCOverscan(rhdPtr->atomBIOS, AtomCrtc, &AtomOverscan); |
||
125 | |||
126 | switch (Type) { |
||
127 | case RHD_CRTC_SCALE_TYPE_NONE: |
||
128 | ScaleMode = atomScaleDisable; |
||
129 | break; |
||
130 | case RHD_CRTC_SCALE_TYPE_CENTER: |
||
131 | ScaleMode = atomScaleCenter; |
||
132 | break; |
||
133 | case RHD_CRTC_SCALE_TYPE_SCALE: |
||
134 | case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO: /* scaled to fullscreen */ |
||
135 | ScaleMode = atomScaleExpand; |
||
136 | break; |
||
137 | } |
||
138 | rhdAtomSetScaler(rhdPtr->atomBIOS, Scaler, ScaleMode); |
||
139 | |||
140 | data.Address = NULL; |
||
141 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
142 | |||
143 | RHDMCTuneAccessForDisplay(rhdPtr, Crtc->Id, Mode, |
||
144 | ScaledToMode ? ScaledToMode : Mode); |
||
145 | } |
||
146 | |||
147 | /* |
||
148 | * |
||
149 | */ |
||
150 | static void |
||
151 | rhdAtomScaleSave(struct rhdCrtc *Crtc) |
||
152 | { |
||
153 | struct rhdCrtcScalePrivate* ScalePriv; |
||
154 | CARD32 RegOff = 0; |
||
155 | |||
156 | RHDFUNC(Crtc); |
||
157 | |||
158 | if (!Crtc->ScalePriv) { |
||
159 | if(!(ScalePriv = (struct rhdCrtcScalePrivate*)xnfcalloc(1, sizeof(struct rhdCrtcScalePrivate)))) |
||
160 | return; |
||
161 | Crtc->ScalePriv = ScalePriv; |
||
162 | } else |
||
163 | ScalePriv = Crtc->ScalePriv; |
||
164 | |||
165 | if (Crtc->Id == RHD_CRTC_1) |
||
166 | RegOff = D1_REG_OFFSET; |
||
167 | else |
||
168 | RegOff = D2_REG_OFFSET; |
||
169 | |||
170 | ScalePriv->StoreViewportSize = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_SIZE); |
||
171 | ScalePriv->StoreViewportStart = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_START); |
||
172 | ScalePriv->RegList = NULL; |
||
173 | } |
||
174 | |||
175 | /* |
||
176 | * |
||
177 | */ |
||
178 | static void |
||
179 | rhdAtomCrtcScaleRestore(struct rhdCrtc *Crtc) |
||
180 | { |
||
181 | struct rhdCrtcScalePrivate* ScalePriv; |
||
182 | CARD32 RegOff = 0; |
||
183 | |||
184 | RHDFUNC(Crtc); |
||
185 | |||
186 | rhdAtomCrtcRestore(Crtc, &(((struct rhdCrtcScalePrivate*)Crtc->ScalePriv)->RegList)); |
||
187 | |||
188 | if (Crtc->Id == RHD_CRTC_1) |
||
189 | RegOff = D1_REG_OFFSET; |
||
190 | else |
||
191 | RegOff = D2_REG_OFFSET; |
||
192 | |||
193 | ScalePriv = (struct rhdCrtcScalePrivate*)Crtc->ScalePriv; |
||
194 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, ScalePriv->StoreViewportSize); |
||
195 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, ScalePriv->StoreViewportStart); |
||
196 | } |
||
197 | |||
198 | /* |
||
199 | * |
||
200 | */ |
||
201 | static void |
||
202 | rhdAtomCrtcScaleDestroy(struct rhdCrtc *Crtc) |
||
203 | { |
||
204 | RHDFUNC(Crtc); |
||
205 | |||
206 | if (Crtc->ScalePriv) { |
||
207 | xfree(Crtc->ScalePriv->RegList); |
||
208 | xfree(Crtc->ScalePriv); |
||
209 | Crtc->ScalePriv = NULL; |
||
210 | } |
||
211 | } |
||
212 | |||
213 | /* |
||
214 | * |
||
215 | */ |
||
216 | struct rhdCrtcModePrivate { |
||
217 | void *RegList; |
||
218 | CARD32 StoreModeDataFormat; |
||
219 | }; |
||
220 | |||
221 | static void |
||
222 | rhdAtomModeSet(struct rhdCrtc *Crtc, DisplayModePtr Mode) |
||
223 | { |
||
224 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
225 | union AtomBiosArg data; |
||
226 | CARD32 RegOff = 0; |
||
227 | |||
228 | RHDFUNC(rhdPtr); |
||
229 | |||
230 | ASSERT(Crtc->ModePriv); |
||
231 | data.Address = &((Crtc->ModePriv)->RegList); |
||
232 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
233 | |||
234 | if (!rhdAtomSetCRTCTimings(rhdPtr->atomBIOS, |
||
235 | Crtc->Id == RHD_CRTC_1 ? atomCrtc1 : atomCrtc2, |
||
236 | Mode, 32)) |
||
237 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: failed to set mode.\n",__func__); |
||
238 | |||
239 | /* set interlaced - AtomBIOS never sets the data format - never tested? */ |
||
240 | if (Crtc->Id == RHD_CRTC_1) |
||
241 | RegOff = D1_REG_OFFSET; |
||
242 | else |
||
243 | RegOff = D2_REG_OFFSET; |
||
244 | |||
245 | if (Mode->Flags & V_INTERLACE) |
||
246 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x1); |
||
247 | else |
||
248 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x0); |
||
249 | |||
250 | data.Address = NULL; |
||
251 | RHDAtomBiosFunc(Crtc->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
252 | } |
||
253 | |||
254 | /* |
||
255 | * |
||
256 | */ |
||
257 | static Bool |
||
258 | rhdAtomCrtcPower(struct rhdCrtc *Crtc, int Power) |
||
259 | { |
||
260 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
261 | enum atomCrtc AtomCrtc = atomCrtc1; |
||
262 | union AtomBiosArg data; |
||
263 | |||
264 | RHDFUNC(Crtc); |
||
265 | |||
266 | switch (Crtc->Id) { |
||
267 | case RHD_CRTC_1: |
||
268 | AtomCrtc = atomCrtc1; |
||
269 | break; |
||
270 | case RHD_CRTC_2: |
||
271 | AtomCrtc = atomCrtc2; |
||
272 | break; |
||
273 | } |
||
274 | data.Address = &((Crtc->ModePriv)->RegList); |
||
275 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
276 | |||
277 | /* |
||
278 | * We call rhdAtomEnableCrtcMemReq blindly as this table seemed to have existed in all |
||
279 | * versions of AtomBIOS on the hardware we support |
||
280 | */ |
||
281 | switch (Power) { |
||
282 | case RHD_POWER_ON: |
||
283 | rhdAtomEnableCrtcMemReq(rhdPtr->atomBIOS, AtomCrtc, atomCrtcEnable); |
||
284 | rhdAtomEnableCrtc(rhdPtr->atomBIOS, AtomCrtc, atomCrtcEnable); |
||
285 | break; |
||
286 | case RHD_POWER_RESET: |
||
287 | case RHD_POWER_SHUTDOWN: |
||
288 | default: |
||
289 | rhdAtomEnableCrtc(rhdPtr->atomBIOS, AtomCrtc, atomCrtcDisable); |
||
290 | rhdAtomEnableCrtcMemReq(rhdPtr->atomBIOS, AtomCrtc, atomCrtcDisable); |
||
291 | break; |
||
292 | } |
||
293 | data.Address = NULL; |
||
294 | RHDAtomBiosFunc(Crtc->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
295 | |||
296 | /* |
||
297 | * we always claim we succeeded here, after all, we know, AtomBIOS knows |
||
298 | * how to do things, right? |
||
299 | * Err, no, when we use AtomBIOS we should not have a clue how to find out. |
||
300 | */ |
||
301 | return TRUE; |
||
302 | } |
||
303 | |||
304 | /* |
||
305 | * |
||
306 | */ |
||
307 | static void |
||
308 | rhdAtomCrtcBlank(struct rhdCrtc *Crtc, Bool Blank) |
||
309 | { |
||
310 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
311 | enum atomCrtc AtomCrtc = atomCrtc1; |
||
312 | struct atomCrtcBlank Config; |
||
313 | union AtomBiosArg data; |
||
314 | |||
315 | RHDFUNC(Crtc); |
||
316 | |||
317 | switch (Crtc->Id) { |
||
318 | case RHD_CRTC_1: |
||
319 | AtomCrtc = atomCrtc1; |
||
320 | break; |
||
321 | case RHD_CRTC_2: |
||
322 | AtomCrtc = atomCrtc2; |
||
323 | break; |
||
324 | } |
||
325 | if (Blank) |
||
326 | Config.Action = atomBlankOn; |
||
327 | else |
||
328 | Config.Action = atomBlankOff; |
||
329 | |||
330 | Config.r = Config.g = Config.b = 0; |
||
331 | |||
332 | data.Address = &((Crtc->ModePriv)->RegList); |
||
333 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
334 | |||
335 | rhdAtomBlankCRTC(rhdPtr->atomBIOS, AtomCrtc , &Config); |
||
336 | |||
337 | data.Address = NULL; |
||
338 | RHDAtomBiosFunc(Crtc->scrnIndex, rhdPtr->atomBIOS, ATOM_SET_REGISTER_LIST_LOCATION, &data); |
||
339 | } |
||
340 | |||
341 | /* |
||
342 | * |
||
343 | */ |
||
344 | static void |
||
345 | rhdAtomModeSave(struct rhdCrtc *Crtc) |
||
346 | { |
||
347 | struct rhdCrtcModePrivate* ModePriv; |
||
348 | CARD32 RegOff = 0; |
||
349 | |||
350 | if (!Crtc->ModePriv) { |
||
351 | if(!(ModePriv = (struct rhdCrtcModePrivate*)xnfcalloc(1, sizeof(struct rhdCrtcModePrivate)))) |
||
352 | return; |
||
353 | Crtc->ModePriv = ModePriv; |
||
354 | } else |
||
355 | ModePriv = Crtc->ModePriv; |
||
356 | |||
357 | if (Crtc->Id == RHD_CRTC_1) |
||
358 | RegOff = D1_REG_OFFSET; |
||
359 | else |
||
360 | RegOff = D2_REG_OFFSET; |
||
361 | |||
362 | ModePriv->StoreModeDataFormat = RHDRegRead(Crtc, RegOff + D1MODE_DATA_FORMAT); |
||
363 | ModePriv->RegList = NULL; |
||
364 | } |
||
365 | |||
366 | /* |
||
367 | * |
||
368 | */ |
||
369 | static void |
||
370 | rhdAtomModeRestore(struct rhdCrtc *Crtc) |
||
371 | { |
||
372 | struct rhdCrtcModePrivate* ModePriv; |
||
373 | CARD32 RegOff = 0; |
||
374 | |||
375 | if (Crtc->Id == RHD_CRTC_1) |
||
376 | RegOff = D1_REG_OFFSET; |
||
377 | else |
||
378 | RegOff = D2_REG_OFFSET; |
||
379 | |||
380 | ModePriv = Crtc->ModePriv; |
||
381 | |||
382 | rhdAtomCrtcRestore(Crtc, &ModePriv->RegList); |
||
383 | |||
384 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, ModePriv->StoreModeDataFormat); |
||
385 | } |
||
386 | |||
387 | /* |
||
388 | * |
||
389 | */ |
||
390 | static void |
||
391 | rhdAtomModeDestroy(struct rhdCrtc *Crtc) |
||
392 | { |
||
393 | RHDFUNC(Crtc); |
||
394 | |||
395 | if (Crtc->ModePriv) { |
||
396 | xfree(Crtc->ModePriv->RegList); |
||
397 | xfree(Crtc->ModePriv); |
||
398 | Crtc->ModePriv = NULL; |
||
399 | } |
||
400 | } |
||
401 | |||
402 | /* |
||
403 | * |
||
404 | */ |
||
405 | void |
||
406 | RHDAtomCrtcsInit(RHDPtr rhdPtr) |
||
407 | { |
||
408 | struct rhdCrtc *Crtc; |
||
409 | int i; |
||
410 | |||
411 | RHDFUNC(rhdPtr); |
||
412 | |||
413 | if (rhdPtr->Crtc[0] == NULL || rhdPtr->Crtc[1] == NULL) { |
||
414 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, "%s: CRTCs not initialized\n",__func__); |
||
415 | return; |
||
416 | } |
||
417 | |||
418 | for (i = 0; i < 2; i++) { |
||
419 | |||
420 | Crtc = rhdPtr->Crtc[i]; |
||
421 | |||
422 | if (i == 0) { |
||
423 | Crtc->Name = "ATOM CRTC 1"; |
||
424 | Crtc->Id = RHD_CRTC_1; |
||
425 | } else { |
||
426 | Crtc->Name = "ATOM CRTC 2"; |
||
427 | Crtc->Id = RHD_CRTC_2; |
||
428 | } |
||
429 | |||
430 | /* EnableGraphSurfaces is only a BIOS internal table. So use the hardcoded path. |
||
431 | Crtc->FBValid = atomFBValid; |
||
432 | Crtc->FBSet = atomFBSet; |
||
433 | Crtc->FBSave = atomSave; |
||
434 | Crtc->FBRestore = atomRestore; |
||
435 | */ |
||
436 | |||
437 | /* There is no separate function to set up the LUT thru AtomBIOS */ |
||
438 | |||
439 | /* Crtc->ScaleValid: From rhd_crtc.c */ |
||
440 | Crtc->ScaleSet = rhdAtomScaleSet; |
||
441 | Crtc->ScaleSave = rhdAtomScaleSave; |
||
442 | Crtc->ScaleRestore = rhdAtomCrtcScaleRestore; |
||
443 | Crtc->ScaleDestroy = rhdAtomCrtcScaleDestroy; |
||
444 | |||
445 | /* No such AtomBIOS table */ |
||
446 | /* Crtc->FrameSet = atomViewPortStart; */ |
||
447 | |||
448 | /* Crtc->ModeValid: From rhd_crtc.c */ |
||
449 | Crtc->ModeSet = rhdAtomModeSet; |
||
450 | Crtc->ModeSave = rhdAtomModeSave; |
||
451 | Crtc->ModeRestore = rhdAtomModeRestore; |
||
452 | Crtc->ModeDestroy = rhdAtomModeDestroy; |
||
453 | |||
454 | Crtc->Power = rhdAtomCrtcPower; |
||
455 | Crtc->Blank = rhdAtomCrtcBlank; |
||
456 | } |
||
457 | } |
||
458 | |||
459 | #endif /* ATOM_BIOS && ATOM_BIOS_PARSER */>><> |