Rev 1029 | Details | Compare with Previous | 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_lut.h" |
||
43 | #include "rhd_regs.h" |
||
44 | #include "rhd_modes.h" |
||
45 | #include "rhd_mc.h" |
||
46 | #ifdef ATOM_BIOS |
||
47 | # include "rhd_atombios.h" |
||
48 | #endif |
||
49 | |||
50 | #define D1_REG_OFFSET 0x0000 |
||
51 | #define D2_REG_OFFSET 0x0800 |
||
52 | #define FMT1_REG_OFFSET 0x0000 |
||
53 | #define FMT2_REG_OFFSET 0x800 |
||
54 | |||
55 | struct rhdCrtcFMTPrivate { |
||
56 | CARD32 StoreControl; |
||
57 | CARD32 StoreBitDepthControl; |
||
58 | CARD32 StoreClampCntl; |
||
59 | }; |
||
60 | |||
61 | struct rhdCrtcFBPrivate { |
||
62 | CARD32 StoreGrphEnable; |
||
63 | CARD32 StoreGrphControl; |
||
64 | CARD32 StoreGrphXStart; |
||
65 | CARD32 StoreGrphYStart; |
||
66 | CARD32 StoreGrphXEnd; |
||
67 | CARD32 StoreGrphYEnd; |
||
68 | CARD32 StoreGrphSwap; |
||
69 | CARD32 StoreGrphPrimarySurfaceAddress; |
||
70 | CARD32 StoreGrphSurfaceOffsetX; |
||
71 | CARD32 StoreGrphSurfaceOffsetY; |
||
72 | CARD32 StoreGrphPitch; |
||
73 | CARD32 StoreModeDesktopHeight; |
||
74 | }; |
||
75 | |||
76 | struct rhdCrtcLUTPrivate { |
||
77 | CARD32 StoreGrphLutSel; |
||
78 | }; |
||
79 | |||
80 | struct rhdCrtcScalePrivate { |
||
81 | CARD32 StoreModeViewPortSize; |
||
82 | |||
83 | CARD32 StoreModeOverScanH; |
||
84 | CARD32 StoreModeOverScanV; |
||
85 | |||
86 | CARD32 StoreModeViewPortStart; |
||
87 | CARD32 StoreScaleEnable; |
||
88 | CARD32 StoreScaleTapControl; |
||
89 | CARD32 StoreModeCenter; |
||
90 | CARD32 StoreScaleHV; |
||
91 | CARD32 StoreScaleHFilter; |
||
92 | CARD32 StoreScaleVFilter; |
||
93 | CARD32 StoreScaleDither; |
||
94 | }; |
||
95 | |||
96 | struct rhdCrtcModePrivate { |
||
97 | CARD32 StoreCrtcControl; |
||
98 | |||
99 | CARD32 StoreCrtcHTotal; |
||
100 | CARD32 StoreCrtcHBlankStartEnd; |
||
101 | CARD32 StoreCrtcHSyncA; |
||
102 | CARD32 StoreCrtcHSyncACntl; |
||
103 | CARD32 StoreCrtcHSyncB; |
||
104 | CARD32 StoreCrtcHSyncBCntl; |
||
105 | |||
106 | CARD32 StoreCrtcVTotal; |
||
107 | CARD32 StoreCrtcVBlankStartEnd; |
||
108 | CARD32 StoreCrtcVSyncA; |
||
109 | CARD32 StoreCrtcVSyncACntl; |
||
110 | CARD32 StoreCrtcVSyncB; |
||
111 | CARD32 StoreCrtcVSyncBCntl; |
||
112 | CARD32 StoreCrtcCountControl; |
||
113 | |||
114 | CARD32 StoreModeDataFormat; |
||
115 | CARD32 StoreCrtcInterlaceControl; |
||
116 | |||
117 | CARD32 StoreCrtcBlackColor; |
||
118 | CARD32 StoreCrtcBlankControl; |
||
119 | }; |
||
120 | |||
121 | /* |
||
122 | * Checks whether Width, Height are within boundaries. |
||
123 | * If MODE_OK is returned and pPitch is not NULL, it is set. |
||
124 | */ |
||
125 | static ModeStatus |
||
126 | DxFBValid(struct rhdCrtc *Crtc, CARD16 Width, CARD16 Height, int bpp, |
||
127 | CARD32 Offset, CARD32 Size, CARD32 *pPitch) |
||
128 | { |
||
129 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
130 | ScrnInfoPtr pScrn = rhdPtr->pScrn; |
||
131 | |||
132 | CARD16 Pitch; |
||
133 | unsigned int BytesPerPixel; |
||
134 | CARD8 PitchMask = 0xFF; |
||
135 | |||
136 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s\n", __func__, Crtc->Name); |
||
137 | |||
138 | /* If we hit this, then the memory claimed so far is not properly aligned */ |
||
139 | if (Offset & 0xFFF) { |
||
140 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: Offset (0x%08X) is invalid!\n", |
||
141 | __func__, (int) Offset); |
||
142 | return MODE_ERROR; |
||
143 | } |
||
144 | |||
145 | switch (pScrn->bitsPerPixel) { |
||
146 | case 8: |
||
147 | BytesPerPixel = 1; |
||
148 | break; |
||
149 | case 15: |
||
150 | case 16: |
||
151 | BytesPerPixel = 2; |
||
152 | PitchMask /= BytesPerPixel; |
||
153 | break; |
||
154 | case 24: |
||
155 | case 32: |
||
156 | BytesPerPixel = 4; |
||
157 | PitchMask /= BytesPerPixel; |
||
158 | break; |
||
159 | default: |
||
160 | xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s: %dbpp is not implemented!\n", |
||
161 | __func__, pScrn->bitsPerPixel); |
||
162 | return MODE_BAD; |
||
163 | } |
||
164 | |||
165 | if((Width==720)&&(Height==400)) //skip textmode |
||
166 | return MODE_BAD; |
||
167 | |||
168 | /* Be reasonable */ |
||
169 | if (Width < 640) |
||
170 | return MODE_H_ILLEGAL; |
||
171 | if (Height < 480) |
||
172 | return MODE_V_ILLEGAL; |
||
173 | |||
174 | /* D1GRPH_X_START is 14bits while D1_MODE_VIEWPORT_X_START is only 13 bits. |
||
175 | * Since it is reasonable to assume that modes will be at least 1x1 |
||
176 | * limit at 13bits + 1 */ |
||
177 | if (Width > 0x2000) |
||
178 | return MODE_VIRTUAL_X; |
||
179 | |||
180 | /* D1GRPH_Y_START is 14bits while D1_MODE_VIEWPORT_Y_START is only 13 bits. |
||
181 | * Since it is reasonable to assume that modes will be at least 1x1 |
||
182 | * limit at 13bits + 1 */ |
||
183 | if (Height > 0x2000) |
||
184 | return MODE_VIRTUAL_Y; |
||
185 | |||
186 | Pitch = (Width + PitchMask) & ~PitchMask; |
||
187 | /* D1_PITCH limit: should never happen after clamping Width to 0x2000 */ |
||
188 | if (Pitch >= 0x4000) |
||
189 | return MODE_VIRTUAL_X; |
||
190 | |||
191 | if ((Pitch * BytesPerPixel * Height) > Size) |
||
192 | return MODE_MEM_VIRT; |
||
193 | |||
194 | if (pPitch) |
||
195 | *pPitch = Pitch; |
||
196 | return MODE_OK; |
||
197 | } |
||
198 | |||
199 | /* |
||
200 | * |
||
201 | */ |
||
202 | static void |
||
203 | DxFBSet(struct rhdCrtc *Crtc, CARD16 Pitch, CARD16 Width, CARD16 Height, |
||
204 | int bpp, CARD32 Offset) |
||
205 | { |
||
206 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
207 | CARD16 RegOff; |
||
208 | |||
209 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s (%i[%i]x%i@%ibpp) +0x%x )\n", |
||
210 | __func__, Crtc->Name, Width, Pitch, Height, bpp, Offset); |
||
211 | |||
212 | if (Crtc->Id == RHD_CRTC_1) |
||
213 | RegOff = D1_REG_OFFSET; |
||
214 | else |
||
215 | RegOff = D2_REG_OFFSET; |
||
216 | |||
217 | RHDRegMask(Crtc, RegOff + D1GRPH_ENABLE, 1, 0x00000001); |
||
218 | |||
219 | /* disable R/B swap, disable tiling, disable 16bit alpha, etc. */ |
||
220 | RHDRegWrite(Crtc, RegOff + D1GRPH_CONTROL, 0); |
||
221 | |||
222 | switch (bpp) { |
||
223 | case 8: |
||
224 | RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0, 0x00000703); |
||
225 | break; |
||
226 | case 15: |
||
227 | RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000001, 0x00000703); |
||
228 | break; |
||
229 | case 16: |
||
230 | RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000101, 0x00000703); |
||
231 | break; |
||
232 | case 24: |
||
233 | case 32: |
||
234 | default: |
||
235 | RHDRegMask(Crtc, RegOff + D1GRPH_CONTROL, 0x000002, 0x00000703); |
||
236 | break; |
||
237 | /* TODO: 64bpp ;p */ |
||
238 | } |
||
239 | |||
240 | /* Make sure that we are not swapping colours around */ |
||
241 | if (rhdPtr->ChipSet > RHD_R600) |
||
242 | RHDRegWrite(Crtc, RegOff + D1GRPH_SWAP_CNTL, 0); |
||
243 | /* R5xx - RS690 case is GRPH_CONTROL bit 16 */ |
||
244 | |||
245 | RHDRegWrite(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS, |
||
246 | rhdPtr->FbIntAddress + Offset); |
||
247 | RHDRegWrite(Crtc, RegOff + D1GRPH_PITCH, Pitch); |
||
248 | RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X, 0); |
||
249 | RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y, 0); |
||
250 | RHDRegWrite(Crtc, RegOff + D1GRPH_X_START, 0); |
||
251 | RHDRegWrite(Crtc, RegOff + D1GRPH_Y_START, 0); |
||
252 | RHDRegWrite(Crtc, RegOff + D1GRPH_X_END, Width); |
||
253 | RHDRegWrite(Crtc, RegOff + D1GRPH_Y_END, Height); |
||
254 | |||
255 | /* D1Mode registers */ |
||
256 | RHDRegWrite(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT, Height); |
||
257 | |||
258 | Crtc->Pitch = Pitch; |
||
259 | Crtc->Width = Width; |
||
260 | Crtc->Height = Height; |
||
261 | Crtc->bpp = bpp; |
||
262 | Crtc->Offset = Offset; |
||
263 | } |
||
264 | |||
265 | /* |
||
266 | * |
||
267 | */ |
||
268 | static void |
||
269 | DxFBSave(struct rhdCrtc *Crtc) |
||
270 | { |
||
271 | struct rhdCrtcFBPrivate *FBPriv; |
||
272 | CARD32 RegOff; |
||
273 | |||
274 | if (!Crtc->FBPriv) |
||
275 | FBPriv = xnfcalloc(1, sizeof(struct rhdCrtcFBPrivate)); |
||
276 | else |
||
277 | FBPriv = Crtc->FBPriv; |
||
278 | |||
279 | if (Crtc->Id == RHD_CRTC_1) |
||
280 | RegOff = D1_REG_OFFSET; |
||
281 | else |
||
282 | RegOff = D2_REG_OFFSET; |
||
283 | |||
284 | FBPriv->StoreGrphEnable = RHDRegRead(Crtc, RegOff + D1GRPH_ENABLE); |
||
285 | FBPriv->StoreGrphControl = RHDRegRead(Crtc, RegOff + D1GRPH_CONTROL); |
||
286 | FBPriv->StoreGrphXStart = RHDRegRead(Crtc, RegOff + D1GRPH_X_START); |
||
287 | FBPriv->StoreGrphYStart = RHDRegRead(Crtc, RegOff + D1GRPH_Y_START); |
||
288 | FBPriv->StoreGrphXEnd = RHDRegRead(Crtc, RegOff + D1GRPH_X_END); |
||
289 | FBPriv->StoreGrphYEnd = RHDRegRead(Crtc, RegOff + D1GRPH_Y_END); |
||
290 | if (RHDPTRI(Crtc)->ChipSet >= RHD_R600) |
||
291 | FBPriv->StoreGrphSwap = RHDRegRead(Crtc, RegOff + D1GRPH_SWAP_CNTL); |
||
292 | FBPriv->StoreGrphPrimarySurfaceAddress = |
||
293 | RHDRegRead(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS); |
||
294 | FBPriv->StoreGrphSurfaceOffsetX = |
||
295 | RHDRegRead(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X); |
||
296 | FBPriv->StoreGrphSurfaceOffsetY = |
||
297 | RHDRegRead(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y); |
||
298 | FBPriv->StoreGrphPitch = RHDRegRead(Crtc, RegOff + D1GRPH_PITCH); |
||
299 | FBPriv->StoreModeDesktopHeight = RHDRegRead(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT); |
||
300 | |||
301 | Crtc->FBPriv = FBPriv; |
||
302 | } |
||
303 | |||
304 | /* |
||
305 | * |
||
306 | */ |
||
307 | static void |
||
308 | DxFBRestore(struct rhdCrtc *Crtc) |
||
309 | { |
||
310 | struct rhdCrtcFBPrivate *FBPriv = Crtc->FBPriv; |
||
311 | CARD32 RegOff; |
||
312 | |||
313 | if (!FBPriv) { |
||
314 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n", |
||
315 | __func__); |
||
316 | return; |
||
317 | } |
||
318 | |||
319 | if (Crtc->Id == RHD_CRTC_1) |
||
320 | RegOff = D1_REG_OFFSET; |
||
321 | else |
||
322 | RegOff = D2_REG_OFFSET; |
||
323 | |||
324 | /* FBSet */ |
||
325 | RHDRegWrite(Crtc, RegOff + D1GRPH_CONTROL, FBPriv->StoreGrphControl); |
||
326 | RHDRegWrite(Crtc, RegOff + D1GRPH_X_START, FBPriv->StoreGrphXStart); |
||
327 | RHDRegWrite(Crtc, RegOff + D1GRPH_Y_START, FBPriv->StoreGrphYStart); |
||
328 | RHDRegWrite(Crtc, RegOff + D1GRPH_X_END, FBPriv->StoreGrphXEnd); |
||
329 | RHDRegWrite(Crtc, RegOff + D1GRPH_Y_END, FBPriv->StoreGrphYEnd); |
||
330 | if (RHDPTRI(Crtc)->ChipSet >= RHD_R600) |
||
331 | RHDRegWrite(Crtc, RegOff + D1GRPH_SWAP_CNTL, FBPriv->StoreGrphSwap); |
||
332 | |||
333 | /* disable read requests */ |
||
334 | RHDRegMask(Crtc, RegOff + D1CRTC_CONTROL, 0x01000000, 0x01000000); |
||
335 | RHDRegMask(Crtc, RegOff + D1GRPH_ENABLE, 0, 0x00000001); |
||
336 | usleep (10); |
||
337 | |||
338 | RHDRegWrite(Crtc, RegOff + D1GRPH_PRIMARY_SURFACE_ADDRESS, |
||
339 | FBPriv->StoreGrphPrimarySurfaceAddress); |
||
340 | usleep(10); |
||
341 | |||
342 | RHDRegWrite(Crtc, RegOff + D1GRPH_ENABLE, FBPriv->StoreGrphEnable); |
||
343 | |||
344 | RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_X, |
||
345 | FBPriv->StoreGrphSurfaceOffsetX); |
||
346 | RHDRegWrite(Crtc, RegOff + D1GRPH_SURFACE_OFFSET_Y, |
||
347 | FBPriv->StoreGrphSurfaceOffsetY); |
||
348 | |||
349 | RHDRegWrite(Crtc, RegOff + D1GRPH_PITCH, FBPriv->StoreGrphPitch); |
||
350 | RHDRegWrite(Crtc, RegOff + D1MODE_DESKTOP_HEIGHT, FBPriv->StoreModeDesktopHeight); |
||
351 | } |
||
352 | |||
353 | /* |
||
354 | * |
||
355 | */ |
||
356 | static void |
||
357 | DxFBDestroy(struct rhdCrtc *Crtc) |
||
358 | { |
||
359 | if (Crtc->FBPriv) |
||
360 | xfree(Crtc->FBPriv); |
||
361 | Crtc->FBPriv = NULL; |
||
362 | } |
||
363 | |||
364 | /* |
||
365 | * |
||
366 | */ |
||
367 | static ModeStatus |
||
368 | DxModeValid(struct rhdCrtc *Crtc, DisplayModePtr Mode) |
||
369 | { |
||
370 | CARD32 tmp; |
||
371 | |||
372 | RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name); |
||
373 | |||
374 | /* Work around HW bug: need at least 2 lines of front porch |
||
375 | for interlaced mode */ |
||
376 | if ((Mode->Flags & V_INTERLACE) |
||
377 | && (Mode->CrtcVSyncStart < (Mode->CrtcVDisplay + 2))) { |
||
378 | Mode->CrtcVSyncStart = Mode->CrtcVDisplay + 2; |
||
379 | Mode->CrtcVAdjusted = TRUE; |
||
380 | } |
||
381 | |||
382 | /* D1CRTC_H_TOTAL - 1 : 13bits */ |
||
383 | if (Mode->CrtcHTotal > 0x2000) |
||
384 | return MODE_BAD_HVALUE; |
||
385 | |||
386 | tmp = Mode->CrtcHTotal + Mode->CrtcHBlankStart - Mode->CrtcHSyncStart; |
||
387 | /* D1CRTC_H_BLANK_START: 13bits */ |
||
388 | if (tmp >= 0x2000) |
||
389 | return MODE_BAD_HVALUE; |
||
390 | |||
391 | tmp = Mode->CrtcHBlankEnd - Mode->CrtcHSyncStart; |
||
392 | /* D1CRTC_H_BLANK_END: 13bits */ |
||
393 | if (tmp >= 0x2000) |
||
394 | return MODE_BAD_HVALUE; |
||
395 | |||
396 | tmp = Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart; |
||
397 | /* D1CRTC_H_SYNC_A_END: 13bits */ |
||
398 | if (tmp >= 0x2000) |
||
399 | return MODE_HSYNC_WIDE; |
||
400 | |||
401 | /* D1CRTC_V_TOTAL - 1 : 13bits */ |
||
402 | if (Mode->CrtcVTotal > 0x2000) |
||
403 | return MODE_BAD_VVALUE; |
||
404 | |||
405 | tmp = Mode->CrtcVTotal + Mode->CrtcVBlankStart - Mode->CrtcVSyncStart; |
||
406 | /* D1CRTC_V_BLANK_START: 13bits */ |
||
407 | if (tmp >= 0x2000) |
||
408 | return MODE_BAD_VVALUE; |
||
409 | |||
410 | tmp = Mode->CrtcVBlankEnd - Mode->CrtcVSyncStart; |
||
411 | /* D1CRTC_V_BLANK_END: 13bits */ |
||
412 | if (tmp >= 0x2000) |
||
413 | return MODE_BAD_VVALUE; |
||
414 | |||
415 | tmp = Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart; |
||
416 | /* D1CRTC_V_SYNC_A_END: 13bits */ |
||
417 | if (tmp >= 0x2000) |
||
418 | return MODE_VSYNC_WIDE; |
||
419 | |||
420 | return MODE_OK; |
||
421 | } |
||
422 | |||
423 | /* |
||
424 | * |
||
425 | */ |
||
426 | static void |
||
427 | DxModeSet(struct rhdCrtc *Crtc, DisplayModePtr Mode) |
||
428 | { |
||
429 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
430 | CARD16 BlankStart, BlankEnd; |
||
431 | CARD16 RegOff; |
||
432 | |||
433 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s\n", __func__, Crtc->Name); |
||
434 | |||
435 | if (rhdPtr->verbosity > 6) { |
||
436 | xf86DrvMsg(Crtc->scrnIndex, X_INFO, "%s: Setting ",__func__); |
||
437 | RHDPrintModeline(Mode); |
||
438 | } |
||
439 | |||
440 | if (Crtc->Id == RHD_CRTC_1) |
||
441 | RegOff = D1_REG_OFFSET; |
||
442 | else |
||
443 | RegOff = D2_REG_OFFSET; |
||
444 | |||
445 | /* enable read requests */ |
||
446 | RHDRegMask(Crtc, RegOff + D1CRTC_CONTROL, 0, 0x01000000); |
||
447 | |||
448 | /* Horizontal */ |
||
449 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_TOTAL, Mode->CrtcHTotal - 1); |
||
450 | |||
451 | BlankStart = Mode->CrtcHTotal + Mode->CrtcHBlankStart - Mode->CrtcHSyncStart; |
||
452 | BlankEnd = Mode->CrtcHBlankEnd - Mode->CrtcHSyncStart; |
||
453 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_BLANK_START_END, |
||
454 | BlankStart | (BlankEnd << 16)); |
||
455 | |||
456 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A, |
||
457 | (Mode->CrtcHSyncEnd - Mode->CrtcHSyncStart) << 16); |
||
458 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL, Mode->Flags & V_NHSYNC); |
||
459 | |||
460 | /* Vertical */ |
||
461 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_TOTAL, Mode->CrtcVTotal - 1); |
||
462 | |||
463 | BlankStart = Mode->CrtcVTotal + Mode->CrtcVBlankStart - Mode->CrtcVSyncStart; |
||
464 | BlankEnd = Mode->CrtcVBlankEnd - Mode->CrtcVSyncStart; |
||
465 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_BLANK_START_END, |
||
466 | BlankStart | (BlankEnd << 16)); |
||
467 | |||
468 | /* set interlaced */ |
||
469 | if (Mode->Flags & V_INTERLACE) { |
||
470 | RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, 0x1); |
||
471 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x1); |
||
472 | } else { |
||
473 | RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, 0x0); |
||
474 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, 0x0); |
||
475 | } |
||
476 | |||
477 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, |
||
478 | (Mode->CrtcVSyncEnd - Mode->CrtcVSyncStart) << 16); |
||
479 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL, Mode->Flags & V_NVSYNC); |
||
480 | |||
481 | /* set D1CRTC_HORZ_COUNT_BY2_EN to 0; should only be set to 1 on 30bpp DVI modes */ |
||
482 | RHDRegMask(Crtc, RegOff + D1CRTC_COUNT_CONTROL, 0x0, 0x1); |
||
483 | |||
484 | Crtc->CurrentMode = Mode; |
||
485 | } |
||
486 | |||
487 | /* |
||
488 | * |
||
489 | */ |
||
490 | static void |
||
491 | DxModeSave(struct rhdCrtc *Crtc) |
||
492 | { |
||
493 | struct rhdCrtcModePrivate *ModePriv; |
||
494 | CARD32 RegOff; |
||
495 | |||
496 | if (!Crtc->ModePriv) |
||
497 | ModePriv = xnfcalloc(1, sizeof(struct rhdCrtcModePrivate)); |
||
498 | else |
||
499 | ModePriv = Crtc->ModePriv; |
||
500 | |||
501 | if (Crtc->Id == RHD_CRTC_1) |
||
502 | RegOff = D1_REG_OFFSET; |
||
503 | else |
||
504 | RegOff = D2_REG_OFFSET; |
||
505 | |||
506 | ModePriv->StoreCrtcControl = RHDRegRead(Crtc, RegOff + D1CRTC_CONTROL); |
||
507 | |||
508 | ModePriv->StoreCrtcHTotal = RHDRegRead(Crtc, RegOff + D1CRTC_H_TOTAL); |
||
509 | ModePriv->StoreCrtcHBlankStartEnd = |
||
510 | RHDRegRead(Crtc, RegOff + D1CRTC_H_BLANK_START_END); |
||
511 | ModePriv->StoreCrtcHSyncA = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_A); |
||
512 | ModePriv->StoreCrtcHSyncACntl = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL); |
||
513 | ModePriv->StoreCrtcHSyncB = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_B); |
||
514 | ModePriv->StoreCrtcHSyncBCntl = RHDRegRead(Crtc, RegOff + D1CRTC_H_SYNC_B_CNTL); |
||
515 | |||
516 | ModePriv->StoreModeDataFormat = RHDRegRead(Crtc, RegOff + D1MODE_DATA_FORMAT); |
||
517 | ModePriv->StoreCrtcInterlaceControl = RHDRegRead(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL); |
||
518 | |||
519 | ModePriv->StoreCrtcVTotal = RHDRegRead(Crtc, RegOff + D1CRTC_V_TOTAL); |
||
520 | ModePriv->StoreCrtcVBlankStartEnd = |
||
521 | RHDRegRead(Crtc, RegOff + D1CRTC_V_BLANK_START_END); |
||
522 | ModePriv->StoreCrtcVSyncA = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_A); |
||
523 | ModePriv->StoreCrtcVSyncACntl = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL); |
||
524 | ModePriv->StoreCrtcVSyncB = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_B); |
||
525 | ModePriv->StoreCrtcVSyncBCntl = RHDRegRead(Crtc, RegOff + D1CRTC_V_SYNC_B_CNTL); |
||
526 | |||
527 | ModePriv->StoreCrtcBlackColor = RHDRegRead(Crtc, RegOff + D1CRTC_BLACK_COLOR); |
||
528 | ModePriv->StoreCrtcBlankControl = RHDRegRead(Crtc, RegOff + D1CRTC_BLANK_CONTROL); |
||
529 | |||
530 | ModePriv->StoreCrtcCountControl = RHDRegRead(Crtc, RegOff + D1CRTC_COUNT_CONTROL); |
||
531 | RHDDebug(Crtc->scrnIndex, "Saved CrtcCountControl[%i] = 0x%8.8x\n", |
||
532 | Crtc->Id,ModePriv->StoreCrtcCountControl); |
||
533 | |||
534 | Crtc->ModePriv = ModePriv; |
||
535 | } |
||
536 | |||
537 | /* |
||
538 | * |
||
539 | */ |
||
540 | static void |
||
541 | DxModeRestore(struct rhdCrtc *Crtc) |
||
542 | { |
||
543 | struct rhdCrtcModePrivate *ModePriv = Crtc->ModePriv; |
||
544 | CARD32 RegOff; |
||
545 | |||
546 | if (!ModePriv) { |
||
547 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n", |
||
548 | __func__); |
||
549 | return; |
||
550 | } |
||
551 | |||
552 | if (Crtc->Id == RHD_CRTC_1) |
||
553 | RegOff = D1_REG_OFFSET; |
||
554 | else |
||
555 | RegOff = D2_REG_OFFSET; |
||
556 | |||
557 | /* ModeSet */ |
||
558 | RHDRegWrite(Crtc, RegOff + D1CRTC_CONTROL, ModePriv->StoreCrtcControl); |
||
559 | |||
560 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_TOTAL, ModePriv->StoreCrtcHTotal); |
||
561 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_BLANK_START_END, |
||
562 | ModePriv->StoreCrtcHBlankStartEnd); |
||
563 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A, ModePriv->StoreCrtcHSyncA); |
||
564 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_A_CNTL, ModePriv->StoreCrtcHSyncACntl); |
||
565 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_B, ModePriv->StoreCrtcHSyncB); |
||
566 | RHDRegWrite(Crtc, RegOff + D1CRTC_H_SYNC_B_CNTL, ModePriv->StoreCrtcHSyncBCntl); |
||
567 | |||
568 | RHDRegWrite(Crtc, RegOff + D1MODE_DATA_FORMAT, ModePriv->StoreModeDataFormat); |
||
569 | RHDRegWrite(Crtc, RegOff + D1CRTC_INTERLACE_CONTROL, ModePriv->StoreCrtcInterlaceControl); |
||
570 | |||
571 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_TOTAL, ModePriv->StoreCrtcVTotal); |
||
572 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_BLANK_START_END, |
||
573 | ModePriv->StoreCrtcVBlankStartEnd); |
||
574 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, ModePriv->StoreCrtcVSyncA); |
||
575 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A_CNTL, ModePriv->StoreCrtcVSyncACntl); |
||
576 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_B, ModePriv->StoreCrtcVSyncB); |
||
577 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_B_CNTL, ModePriv->StoreCrtcVSyncBCntl); |
||
578 | |||
579 | RHDRegWrite(Crtc, RegOff + D1CRTC_COUNT_CONTROL, ModePriv->StoreCrtcCountControl); |
||
580 | |||
581 | /* Blank */ |
||
582 | RHDRegWrite(Crtc, RegOff + D1CRTC_BLACK_COLOR, ModePriv->StoreCrtcBlackColor); |
||
583 | RHDRegWrite(Crtc, RegOff + D1CRTC_BLANK_CONTROL, ModePriv->StoreCrtcBlankControl); |
||
584 | |||
585 | /* When VGA is enabled, it imposes its timing on us, so our CRTC SYNC |
||
586 | * timing can be set to 0. This doesn't always restore properly... |
||
587 | * Workaround is to set a valid sync length for a bit so VGA can |
||
588 | * latch in. */ |
||
589 | if (!ModePriv->StoreCrtcVSyncA && (ModePriv->StoreCrtcControl & 0x00000001)) { |
||
590 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, 0x00040000); |
||
591 | usleep(300000); /* seems a reliable timeout here */ |
||
592 | RHDRegWrite(Crtc, RegOff + D1CRTC_V_SYNC_A, ModePriv->StoreCrtcVSyncA); |
||
593 | } |
||
594 | } |
||
595 | |||
596 | /* |
||
597 | * |
||
598 | */ |
||
599 | static void |
||
600 | DxModeDestroy(struct rhdCrtc *Crtc) |
||
601 | { |
||
602 | RHDFUNC(Crtc); |
||
603 | |||
604 | if (Crtc->ModePriv) |
||
605 | xfree(Crtc->ModePriv); |
||
606 | Crtc->ModePriv = NULL; |
||
607 | } |
||
608 | |||
609 | /* |
||
610 | * |
||
611 | */ |
||
612 | struct rhdScalerOverscan |
||
613 | rhdCalculateOverscan(DisplayModePtr Mode, DisplayModePtr ScaledToMode, enum rhdCrtcScaleType Type) |
||
614 | { |
||
615 | struct rhdScalerOverscan Overscan; |
||
616 | int tmp; |
||
617 | |||
618 | Overscan.OverscanTop = Overscan.OverscanBottom = Overscan.OverscanLeft = Overscan.OverscanRight = 0; |
||
619 | Overscan.Type = Type; |
||
620 | |||
621 | if (ScaledToMode) { |
||
622 | Overscan.OverscanTop = ScaledToMode->CrtcVDisplay - Mode->CrtcVDisplay; |
||
623 | Overscan.OverscanLeft = ScaledToMode->CrtcHDisplay - Mode->CrtcHDisplay; |
||
624 | |||
625 | if (!Overscan.OverscanTop && !Overscan.OverscanLeft) |
||
626 | Overscan.Type = RHD_CRTC_SCALE_TYPE_NONE; |
||
627 | |||
628 | /* handle down scaling */ |
||
629 | if (Overscan.OverscanTop < 0) { |
||
630 | Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE; |
||
631 | Overscan.OverscanTop = 0; |
||
632 | } |
||
633 | if (Overscan.OverscanLeft < 0) { |
||
634 | Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE; |
||
635 | Overscan.OverscanLeft = 0; |
||
636 | } |
||
637 | } |
||
638 | |||
639 | switch (Type) { |
||
640 | case RHD_CRTC_SCALE_TYPE_NONE: |
||
641 | break; |
||
642 | |||
643 | case RHD_CRTC_SCALE_TYPE_CENTER: |
||
644 | tmp = Overscan.OverscanTop; |
||
645 | Overscan.OverscanTop >>= 1; |
||
646 | Overscan.OverscanBottom = tmp - Overscan.OverscanTop; |
||
647 | tmp = Overscan.OverscanLeft; |
||
648 | Overscan.OverscanLeft >>= 1; |
||
649 | Overscan.OverscanRight = tmp - Overscan.OverscanLeft; |
||
650 | break; |
||
651 | |||
652 | case RHD_CRTC_SCALE_TYPE_SCALE: |
||
653 | Overscan.OverscanLeft = Overscan.OverscanRight = Overscan.OverscanTop = Overscan.OverscanBottom = 0; |
||
654 | break; |
||
655 | case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO: |
||
656 | { |
||
657 | int p1, p2, tmp; |
||
658 | Overscan.OverscanLeft = Overscan.OverscanRight = Overscan.OverscanTop = Overscan.OverscanBottom = 0; |
||
659 | p1 = Mode->CrtcVDisplay * ScaledToMode->CrtcHDisplay; |
||
660 | p2 = ScaledToMode->CrtcVDisplay * Mode->CrtcHDisplay; |
||
661 | if (p1 == p2) { |
||
662 | Overscan.Type = RHD_CRTC_SCALE_TYPE_SCALE; |
||
663 | } else if (p1 > p2) { |
||
664 | tmp = (p2 / Mode->CrtcVDisplay); |
||
665 | tmp = ScaledToMode->CrtcHDisplay - tmp; |
||
666 | Overscan.OverscanLeft = tmp >> 1; |
||
667 | Overscan.OverscanRight = tmp - Overscan.OverscanLeft; |
||
668 | ErrorF("HScale %i %i\n", Overscan.OverscanLeft, Overscan.OverscanRight); |
||
669 | } else { |
||
670 | tmp = (p1 / Mode->CrtcHDisplay); |
||
671 | tmp = ScaledToMode->CrtcVDisplay - tmp; |
||
672 | Overscan.OverscanTop = tmp >> 1; |
||
673 | Overscan.OverscanBottom = tmp - Overscan.OverscanTop; |
||
674 | ErrorF("VScale %i %i\n", Overscan.OverscanTop, Overscan.OverscanBottom); |
||
675 | } |
||
676 | break; |
||
677 | } |
||
678 | } |
||
679 | |||
680 | return Overscan; |
||
681 | } |
||
682 | |||
683 | /* |
||
684 | * |
||
685 | */ |
||
686 | static ModeStatus |
||
687 | DxScaleValid(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type, |
||
688 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
689 | { |
||
690 | struct rhdScalerOverscan Overscan; |
||
691 | |||
692 | /* D1_MODE_VIEWPORT_WIDTH: 14bits */ |
||
693 | if (Mode->CrtcHDisplay >= 0x4000) |
||
694 | return MODE_BAD_HVALUE; |
||
695 | |||
696 | /* D1_MODE_VIEWPORT_HEIGHT: 14bits */ |
||
697 | if (Mode->CrtcVDisplay >= 0x4000) |
||
698 | return MODE_BAD_VVALUE; |
||
699 | |||
700 | Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type); |
||
701 | |||
702 | if (Overscan.OverscanLeft >= 4096 || Overscan.OverscanRight >= 4096) |
||
703 | return MODE_HBLANK_WIDE; |
||
704 | |||
705 | if (Overscan.OverscanTop >= 4096 || Overscan.OverscanBottom >= 4096) |
||
706 | return MODE_VBLANK_WIDE; |
||
707 | |||
708 | if ((Type == RHD_CRTC_SCALE_TYPE_SCALE |
||
709 | || Type == RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO) |
||
710 | && (Mode->Flags & V_INTERLACE)) |
||
711 | return MODE_NO_INTERLACE; |
||
712 | |||
713 | /* should we also fail of Type != Overscan.Type? */ |
||
714 | |||
715 | return MODE_OK; |
||
716 | } |
||
717 | |||
718 | /* |
||
719 | * |
||
720 | */ |
||
721 | static void |
||
722 | DxScaleSet(struct rhdCrtc *Crtc, enum rhdCrtcScaleType Type, |
||
723 | DisplayModePtr Mode, DisplayModePtr ScaledToMode) |
||
724 | { |
||
725 | RHDPtr rhdPtr = RHDPTRI(Crtc); |
||
726 | CARD16 RegOff; |
||
727 | struct rhdScalerOverscan Overscan; |
||
728 | |||
729 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s viewport: %ix%i\n", __func__, Crtc->Name, |
||
730 | Mode->CrtcHDisplay, Mode->CrtcVDisplay); |
||
731 | |||
732 | if (Crtc->Id == RHD_CRTC_1) |
||
733 | RegOff = D1_REG_OFFSET; |
||
734 | else |
||
735 | RegOff = D2_REG_OFFSET; |
||
736 | |||
737 | Overscan = rhdCalculateOverscan(Mode, ScaledToMode, Type); |
||
738 | Type = Overscan.Type; |
||
739 | |||
740 | RHDDebug(Crtc->scrnIndex, "FUNCTION: %s: %s viewport: %ix%i - OverScan: T: %i B: %i R: %i L: %i\n", |
||
741 | __func__, Crtc->Name, Mode->CrtcHDisplay, Mode->CrtcVDisplay, |
||
742 | Overscan.OverscanTop, Overscan.OverscanBottom, |
||
743 | Overscan.OverscanLeft, Overscan.OverscanRight); |
||
744 | |||
745 | /* D1Mode registers */ |
||
746 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, |
||
747 | Mode->CrtcVDisplay | (Mode->CrtcHDisplay << 16)); |
||
748 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, 0); |
||
749 | |||
750 | RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT, |
||
751 | (Overscan.OverscanLeft << 16) | Overscan.OverscanRight); |
||
752 | RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM, |
||
753 | (Overscan.OverscanTop << 16) | Overscan.OverscanBottom); |
||
754 | |||
755 | switch (Type) { |
||
756 | case RHD_CRTC_SCALE_TYPE_NONE: /* No scaling whatsoever */ |
||
757 | ErrorF("None\n"); |
||
758 | RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 0); |
||
759 | RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0); |
||
760 | RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 0); |
||
761 | break; |
||
762 | case RHD_CRTC_SCALE_TYPE_CENTER: /* center of the actual mode */ |
||
763 | ErrorF("Center\n"); |
||
764 | RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 0); |
||
765 | RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0); |
||
766 | RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 1); |
||
767 | break; |
||
768 | case RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO: /* scaled to fullscreen */ |
||
769 | case RHD_CRTC_SCALE_TYPE_SCALE: /* scaled to fullscreen */ |
||
770 | ErrorF("Full\n"); |
||
771 | if (Type == RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO) |
||
772 | RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 1); |
||
773 | else |
||
774 | RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, 0); |
||
775 | |||
776 | RHDRegWrite(Crtc, RegOff + D1SCL_UPDATE, 0); |
||
777 | RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, 0); |
||
778 | |||
779 | RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, 1); |
||
780 | RHDRegWrite(Crtc, RegOff + D1SCL_HVSCALE, 0x00010001); /* both h/v */ |
||
781 | |||
782 | RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, 0x00000101); |
||
783 | |||
784 | RHDRegWrite(Crtc, RegOff + D1SCL_HFILTER, 0x00030100); |
||
785 | RHDRegWrite(Crtc, RegOff + D1SCL_VFILTER, 0x00030100); |
||
786 | |||
787 | RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, 0x00001010); |
||
788 | break; |
||
789 | } |
||
790 | RHDMCTuneAccessForDisplay(rhdPtr, Crtc->Id, Mode, |
||
791 | ScaledToMode ? ScaledToMode : Mode); |
||
792 | } |
||
793 | |||
794 | /* |
||
795 | * |
||
796 | */ |
||
797 | static void |
||
798 | DxScaleSave(struct rhdCrtc *Crtc) |
||
799 | { |
||
800 | struct rhdCrtcScalePrivate *ScalePriv; |
||
801 | CARD32 RegOff; |
||
802 | |||
803 | if (!Crtc->ScalePriv) |
||
804 | ScalePriv = xnfcalloc(1, sizeof(struct rhdCrtcScalePrivate)); |
||
805 | else |
||
806 | ScalePriv = Crtc->ScalePriv; |
||
807 | |||
808 | if (Crtc->Id == RHD_CRTC_1) |
||
809 | RegOff = D1_REG_OFFSET; |
||
810 | else |
||
811 | RegOff = D2_REG_OFFSET; |
||
812 | |||
813 | ScalePriv->StoreModeViewPortSize = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_SIZE); |
||
814 | ScalePriv->StoreModeViewPortStart = RHDRegRead(Crtc, RegOff + D1MODE_VIEWPORT_START); |
||
815 | ScalePriv->StoreModeOverScanH = |
||
816 | RHDRegRead(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT); |
||
817 | ScalePriv->StoreModeOverScanV = |
||
818 | RHDRegRead(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM); |
||
819 | |||
820 | ScalePriv->StoreScaleEnable = RHDRegRead(Crtc, RegOff + D1SCL_ENABLE); |
||
821 | ScalePriv->StoreScaleTapControl = RHDRegRead(Crtc, RegOff + D1SCL_TAP_CONTROL); |
||
822 | ScalePriv->StoreModeCenter = RHDRegRead(Crtc, RegOff + D1MODE_CENTER); |
||
823 | ScalePriv->StoreScaleHV = RHDRegRead(Crtc, RegOff + D1SCL_HVSCALE); |
||
824 | ScalePriv->StoreScaleHFilter = RHDRegRead(Crtc, RegOff + D1SCL_HFILTER); |
||
825 | ScalePriv->StoreScaleVFilter = RHDRegRead(Crtc, RegOff + D1SCL_VFILTER); |
||
826 | ScalePriv->StoreScaleDither = RHDRegRead(Crtc, RegOff + D1SCL_DITHER); |
||
827 | |||
828 | Crtc->ScalePriv = ScalePriv; |
||
829 | } |
||
830 | |||
831 | /* |
||
832 | * |
||
833 | */ |
||
834 | static void |
||
835 | DxScaleRestore(struct rhdCrtc *Crtc) |
||
836 | { |
||
837 | struct rhdCrtcScalePrivate *ScalePriv = Crtc->ScalePriv; |
||
838 | CARD32 RegOff; |
||
839 | |||
840 | if (!ScalePriv) { |
||
841 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n", |
||
842 | __func__); |
||
843 | return; |
||
844 | } |
||
845 | |||
846 | if (Crtc->Id == RHD_CRTC_1) |
||
847 | RegOff = D1_REG_OFFSET; |
||
848 | else |
||
849 | RegOff = D2_REG_OFFSET; |
||
850 | |||
851 | /* ScaleSet */ |
||
852 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_SIZE, ScalePriv->StoreModeViewPortSize); |
||
853 | |||
854 | /* ScaleSet/ViewPortStart */ |
||
855 | RHDRegWrite(Crtc, RegOff + D1MODE_VIEWPORT_START, ScalePriv->StoreModeViewPortStart); |
||
856 | |||
857 | /* ScaleSet */ |
||
858 | RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_LEFT_RIGHT, |
||
859 | ScalePriv->StoreModeOverScanH); |
||
860 | RHDRegWrite(Crtc, RegOff + D1MODE_EXT_OVERSCAN_TOP_BOTTOM, |
||
861 | ScalePriv->StoreModeOverScanV); |
||
862 | |||
863 | RHDRegWrite(Crtc, RegOff + D1SCL_ENABLE, ScalePriv->StoreScaleEnable); |
||
864 | RHDRegWrite(Crtc, RegOff + D1SCL_TAP_CONTROL, ScalePriv->StoreScaleTapControl); |
||
865 | RHDRegWrite(Crtc, RegOff + D1MODE_CENTER, ScalePriv->StoreModeCenter); |
||
866 | RHDRegWrite(Crtc, RegOff + D1SCL_HVSCALE, ScalePriv->StoreScaleHV); |
||
867 | RHDRegWrite(Crtc, RegOff + D1SCL_HFILTER, ScalePriv->StoreScaleHFilter); |
||
868 | RHDRegWrite(Crtc, RegOff + D1SCL_VFILTER, ScalePriv->StoreScaleVFilter); |
||
869 | RHDRegWrite(Crtc, RegOff + D1SCL_DITHER, ScalePriv->StoreScaleDither); |
||
870 | } |
||
871 | |||
872 | /* |
||
873 | * |
||
874 | */ |
||
875 | static void |
||
876 | DxScaleDestroy(struct rhdCrtc *Crtc) |
||
877 | { |
||
878 | RHDFUNC(Crtc); |
||
879 | |||
880 | if (Crtc->ScalePriv) |
||
881 | xfree(Crtc->ScalePriv); |
||
882 | Crtc->ScalePriv = NULL; |
||
883 | } |
||
884 | |||
885 | /* |
||
886 | * |
||
887 | */ |
||
888 | static void |
||
889 | D1LUTSelect(struct rhdCrtc *Crtc, struct rhdLUT *LUT) |
||
890 | { |
||
891 | RHDFUNC(Crtc); |
||
892 | |||
893 | RHDRegWrite(Crtc, D1GRPH_LUT_SEL, LUT->Id & 1); |
||
894 | Crtc->LUT = LUT; |
||
895 | } |
||
896 | |||
897 | /* |
||
898 | * |
||
899 | */ |
||
900 | static void |
||
901 | D2LUTSelect(struct rhdCrtc *Crtc, struct rhdLUT *LUT) |
||
902 | { |
||
903 | RHDFUNC(Crtc); |
||
904 | |||
905 | RHDRegWrite(Crtc, D2GRPH_LUT_SEL, LUT->Id & 1); |
||
906 | Crtc->LUT = LUT; |
||
907 | } |
||
908 | |||
909 | /* |
||
910 | * |
||
911 | */ |
||
912 | static void |
||
913 | DxLUTSave(struct rhdCrtc *Crtc) |
||
914 | { |
||
915 | struct rhdCrtcLUTPrivate *LUTPriv; |
||
916 | CARD32 RegOff; |
||
917 | |||
918 | if (!Crtc->LUTPriv) |
||
919 | LUTPriv = xnfcalloc(1, sizeof(struct rhdCrtcLUTPrivate)); |
||
920 | else |
||
921 | LUTPriv = Crtc->LUTPriv; |
||
922 | |||
923 | if (Crtc->Id == RHD_CRTC_1) |
||
924 | RegOff = D1_REG_OFFSET; |
||
925 | else |
||
926 | RegOff = D2_REG_OFFSET; |
||
927 | |||
928 | LUTPriv->StoreGrphLutSel = RHDRegRead(Crtc, RegOff + D1GRPH_LUT_SEL); |
||
929 | |||
930 | Crtc->LUTPriv = LUTPriv; |
||
931 | } |
||
932 | |||
933 | /* |
||
934 | * |
||
935 | */ |
||
936 | static void |
||
937 | DxLUTRestore(struct rhdCrtc *Crtc) |
||
938 | { |
||
939 | struct rhdCrtcLUTPrivate *LUTPriv = Crtc->LUTPriv; |
||
940 | CARD32 RegOff; |
||
941 | |||
942 | if (!LUTPriv) { |
||
943 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, "%s: no registers stored!\n", |
||
944 | __func__); |
||
945 | return; |
||
946 | } |
||
947 | |||
948 | if (Crtc->Id == RHD_CRTC_1) |
||
949 | RegOff = D1_REG_OFFSET; |
||
950 | else |
||
951 | RegOff = D2_REG_OFFSET; |
||
952 | |||
953 | /* LUTSelect */ |
||
954 | RHDRegWrite(Crtc, RegOff + D1GRPH_LUT_SEL, LUTPriv->StoreGrphLutSel); |
||
955 | } |
||
956 | |||
957 | /* |
||
958 | * |
||
959 | */ |
||
960 | static void |
||
961 | DxLUTDestroy(struct rhdCrtc *Crtc) |
||
962 | { |
||
963 | RHDFUNC(Crtc); |
||
964 | |||
965 | if (Crtc->LUTPriv) |
||
966 | xfree(Crtc->LUTPriv); |
||
967 | Crtc->LUTPriv = NULL; |
||
968 | } |
||
969 | |||
970 | /* |
||
971 | * |
||
972 | */ |
||
973 | static void |
||
974 | D1ViewPortStart(struct rhdCrtc *Crtc, CARD16 X, CARD16 Y) |
||
975 | { |
||
976 | RHDFUNC(Crtc); |
||
977 | |||
978 | /* not as granular as docs make it seem to be. |
||
979 | * if the lower two bits are set the line buffer might screw up, requiring |
||
980 | * a power cycle. */ |
||
981 | X = (X + 0x02) & ~0x03; |
||
982 | Y &= ~0x01; |
||
983 | |||
984 | RHDRegMask(Crtc, D1SCL_UPDATE, 0x00010000, 0x0001000); |
||
985 | RHDRegWrite(Crtc, D1MODE_VIEWPORT_START, (X << 16) | Y); |
||
986 | RHDRegMask(Crtc, D1SCL_UPDATE, 0, 0x0001000); |
||
987 | |||
988 | Crtc->X = X; |
||
989 | Crtc->Y = Y; |
||
990 | } |
||
991 | |||
992 | /* |
||
993 | * |
||
994 | */ |
||
995 | static void |
||
996 | D2ViewPortStart(struct rhdCrtc *Crtc, CARD16 X, CARD16 Y) |
||
997 | { |
||
998 | RHDFUNC(Crtc); |
||
999 | |||
1000 | /* not as granular as docs make it seem to be. */ |
||
1001 | X = (X + 0x02) & ~0x03; |
||
1002 | Y &= ~0x01; |
||
1003 | |||
1004 | RHDRegMask(Crtc, D2SCL_UPDATE, 0x00010000, 0x0001000); |
||
1005 | RHDRegWrite(Crtc, D2MODE_VIEWPORT_START, (X << 16) | Y); |
||
1006 | RHDRegMask(Crtc, D2SCL_UPDATE, 0, 0x0001000); |
||
1007 | |||
1008 | Crtc->X = X; |
||
1009 | Crtc->Y = Y; |
||
1010 | } |
||
1011 | |||
1012 | #define CRTC_SYNC_WAIT 0x100000 |
||
1013 | /* |
||
1014 | * |
||
1015 | */ |
||
1016 | static Bool |
||
1017 | D1CRTCDisable(struct rhdCrtc *Crtc) |
||
1018 | { |
||
1019 | if (RHDRegRead(Crtc, D1CRTC_CONTROL) & 0x00000001) { |
||
1020 | CARD32 Control = RHDRegRead(Crtc, D1CRTC_CONTROL); |
||
1021 | int i; |
||
1022 | |||
1023 | RHDRegMask(Crtc, D1CRTC_CONTROL, 0, 0x00000301); |
||
1024 | (void)RHDRegRead(Crtc, D1CRTC_CONTROL); |
||
1025 | |||
1026 | for (i = 0; i < CRTC_SYNC_WAIT; i++) |
||
1027 | if (!(RHDRegRead(Crtc, D1CRTC_CONTROL) & 0x00010000)) { |
||
1028 | RHDDebug(Crtc->scrnIndex, "%s: %d loops\n", __func__, i); |
||
1029 | RHDRegMask(Crtc, D1CRTC_CONTROL, Control, 0x00000300); |
||
1030 | return TRUE; |
||
1031 | } |
||
1032 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, |
||
1033 | "%s: Failed to Unsync %s\n", __func__, Crtc->Name); |
||
1034 | RHDRegMask(Crtc, D1CRTC_CONTROL, Control, 0x00000300); |
||
1035 | return FALSE; |
||
1036 | } |
||
1037 | return TRUE; |
||
1038 | } |
||
1039 | |||
1040 | /* |
||
1041 | * |
||
1042 | */ |
||
1043 | static Bool |
||
1044 | D2CRTCDisable(struct rhdCrtc *Crtc) |
||
1045 | { |
||
1046 | if (RHDRegRead(Crtc, D2CRTC_CONTROL) & 0x00000001) { |
||
1047 | CARD32 Control = RHDRegRead(Crtc, D2CRTC_CONTROL); |
||
1048 | int i; |
||
1049 | |||
1050 | RHDRegMask(Crtc, D2CRTC_CONTROL, 0, 0x00000301); |
||
1051 | (void)RHDRegRead(Crtc, D2CRTC_CONTROL); |
||
1052 | |||
1053 | for (i = 0; i < CRTC_SYNC_WAIT; i++) |
||
1054 | if (!(RHDRegRead(Crtc, D2CRTC_CONTROL) & 0x00010000)) { |
||
1055 | RHDDebug(Crtc->scrnIndex, "%s: %d loops\n", __func__, i); |
||
1056 | RHDRegMask(Crtc, D2CRTC_CONTROL, Control, 0x00000300); |
||
1057 | return TRUE; |
||
1058 | } |
||
1059 | xf86DrvMsg(Crtc->scrnIndex, X_ERROR, |
||
1060 | "%s: Failed to Unsync %s\n", __func__, Crtc->Name); |
||
1061 | RHDRegMask(Crtc, D2CRTC_CONTROL, Control, 0x00000300); |
||
1062 | return FALSE; |
||
1063 | } |
||
1064 | return TRUE; |
||
1065 | } |
||
1066 | |||
1067 | /* |
||
1068 | * |
||
1069 | */ |
||
1070 | static Bool |
||
1071 | D1Power(struct rhdCrtc *Crtc, int Power) |
||
1072 | { |
||
1073 | Bool ret; |
||
1074 | RHDFUNC(Crtc); |
||
1075 | |||
1076 | switch (Power) { |
||
1077 | case RHD_POWER_ON: |
||
1078 | RHDRegMask(Crtc, D1GRPH_ENABLE, 0x00000001, 0x00000001); |
||
1079 | usleep(2); |
||
1080 | RHDRegMask(Crtc, D1CRTC_CONTROL, 0, 0x01000000); /* enable read requests */ |
||
1081 | RHDRegMask(Crtc, D1CRTC_CONTROL, 1, 1); |
||
1082 | return TRUE; |
||
1083 | case RHD_POWER_RESET: |
||
1084 | RHDRegMask(Crtc, D1CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */ |
||
1085 | return D1CRTCDisable(Crtc); |
||
1086 | case RHD_POWER_SHUTDOWN: |
||
1087 | default: |
||
1088 | RHDRegMask(Crtc, D1CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */ |
||
1089 | ret = D1CRTCDisable(Crtc); |
||
1090 | RHDRegMask(Crtc, D1GRPH_ENABLE, 0, 0x00000001); |
||
1091 | return ret; |
||
1092 | } |
||
1093 | } |
||
1094 | |||
1095 | /* |
||
1096 | * |
||
1097 | */ |
||
1098 | static Bool |
||
1099 | D2Power(struct rhdCrtc *Crtc, int Power) |
||
1100 | { |
||
1101 | Bool ret; |
||
1102 | RHDFUNC(Crtc); |
||
1103 | |||
1104 | switch (Power) { |
||
1105 | case RHD_POWER_ON: |
||
1106 | RHDRegMask(Crtc, D2GRPH_ENABLE, 0x00000001, 0x00000001); |
||
1107 | usleep(2); |
||
1108 | RHDRegMask(Crtc, D2CRTC_CONTROL, 0, 0x01000000); /* enable read requests */ |
||
1109 | RHDRegMask(Crtc, D2CRTC_CONTROL, 1, 1); |
||
1110 | return TRUE; |
||
1111 | case RHD_POWER_RESET: |
||
1112 | RHDRegMask(Crtc, D2CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */ |
||
1113 | return D2CRTCDisable(Crtc); |
||
1114 | case RHD_POWER_SHUTDOWN: |
||
1115 | default: |
||
1116 | RHDRegMask(Crtc, D2CRTC_CONTROL, 0x01000000, 0x01000000); /* disable read requests */ |
||
1117 | ret = D2CRTCDisable(Crtc); |
||
1118 | RHDRegMask(Crtc, D2GRPH_ENABLE, 0, 0x00000001); |
||
1119 | return ret; |
||
1120 | } |
||
1121 | } |
||
1122 | |||
1123 | /* |
||
1124 | * This is quite different from Power. Power disables and enables things, |
||
1125 | * this here makes the hw send out black, and can switch back and forth |
||
1126 | * immediately. Useful for covering up a framebuffer that is not filled |
||
1127 | * in yet. |
||
1128 | */ |
||
1129 | static void |
||
1130 | D1Blank(struct rhdCrtc *Crtc, Bool Blank) |
||
1131 | { |
||
1132 | RHDFUNC(Crtc); |
||
1133 | |||
1134 | RHDRegWrite(Crtc, D1CRTC_BLACK_COLOR, 0); |
||
1135 | if (Blank) |
||
1136 | RHDRegMask(Crtc, D1CRTC_BLANK_CONTROL, 0x00000100, 0x00000100); |
||
1137 | else |
||
1138 | RHDRegMask(Crtc, D1CRTC_BLANK_CONTROL, 0, 0x00000100); |
||
1139 | } |
||
1140 | |||
1141 | /* |
||
1142 | * |
||
1143 | */ |
||
1144 | static void |
||
1145 | D2Blank(struct rhdCrtc *Crtc, Bool Blank) |
||
1146 | { |
||
1147 | RHDFUNC(Crtc); |
||
1148 | |||
1149 | RHDRegWrite(Crtc, D2CRTC_BLACK_COLOR, 0); |
||
1150 | if (Blank) |
||
1151 | RHDRegMask(Crtc, D2CRTC_BLANK_CONTROL, 0x00000100, 0x00000100); |
||
1152 | else |
||
1153 | RHDRegMask(Crtc, D2CRTC_BLANK_CONTROL, 0, 0x00000100); |
||
1154 | } |
||
1155 | |||
1156 | /* |
||
1157 | * |
||
1158 | */ |
||
1159 | static void |
||
1160 | DxFMTSet(struct rhdCrtc *Crtc, struct rhdFMTDither *FMTDither) |
||
1161 | { |
||
1162 | CARD32 RegOff; |
||
1163 | CARD32 fmt_cntl = 0; |
||
1164 | |||
1165 | RHDFUNC(Crtc); |
||
1166 | |||
1167 | if (Crtc->Id == RHD_CRTC_1) |
||
1168 | RegOff = FMT1_REG_OFFSET; |
||
1169 | else |
||
1170 | RegOff = FMT2_REG_OFFSET; |
||
1171 | |||
1172 | if (FMTDither) { |
||
1173 | |||
1174 | /* set dither depth to 18/24 */ |
||
1175 | fmt_cntl = FMTDither->LVDS24Bit |
||
1176 | ? (RV62_FMT_SPATIAL_DITHER_DEPTH | RV62_FMT_TEMPORAL_DITHER_DEPTH) |
||
1177 | : 0; |
||
1178 | RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, fmt_cntl, |
||
1179 | RV62_FMT_SPATIAL_DITHER_DEPTH | RV62_FMT_TEMPORAL_DITHER_DEPTH); |
||
1180 | |||
1181 | /* set temporal dither */ |
||
1182 | if (FMTDither->LVDSTemporalDither) { |
||
1183 | fmt_cntl = FMTDither->LVDSGreyLevel ? RV62_FMT_TEMPORAL_LEVEL : 0x0; |
||
1184 | /* grey level */ |
||
1185 | RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, |
||
1186 | fmt_cntl, RV62_FMT_TEMPORAL_LEVEL); |
||
1187 | /* turn on temporal dither and reset */ |
||
1188 | RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, |
||
1189 | RV62_FMT_TEMPORAL_DITHER_EN | RV62_FMT_TEMPORAL_DITHER_RESET, |
||
1190 | RV62_FMT_TEMPORAL_DITHER_EN | RV62_FMT_TEMPORAL_DITHER_RESET); |
||
1191 | usleep(20); |
||
1192 | /* turn off reset */ |
||
1193 | RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, 0x0, |
||
1194 | RV62_FMT_TEMPORAL_DITHER_RESET); |
||
1195 | } |
||
1196 | /* spatial dither */ |
||
1197 | RHDRegMask(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, |
||
1198 | FMTDither->LVDSSpatialDither ? RV62_FMT_SPATIAL_DITHER_EN : 0, |
||
1199 | RV62_FMT_SPATIAL_DITHER_EN); |
||
1200 | } else |
||
1201 | RHDRegWrite(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, 0); |
||
1202 | |||
1203 | /* 4:4:4 encoding */ |
||
1204 | RHDRegMask(Crtc, RegOff + RV620_FMT1_CONTROL, 0, RV62_FMT_PIXEL_ENCODING); |
||
1205 | /* disable color clamping */ |
||
1206 | RHDRegWrite(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL, 0); |
||
1207 | } |
||
1208 | |||
1209 | /* |
||
1210 | * |
||
1211 | */ |
||
1212 | static void |
||
1213 | DxFMTSave(struct rhdCrtc *Crtc) |
||
1214 | { |
||
1215 | struct rhdCrtcFMTPrivate *FMTPrivate; |
||
1216 | CARD32 RegOff; |
||
1217 | |||
1218 | RHDFUNC(Crtc); |
||
1219 | |||
1220 | if (!Crtc->FMTPriv) |
||
1221 | FMTPrivate = xnfcalloc(sizeof (struct rhdCrtcFMTPrivate),1); |
||
1222 | else |
||
1223 | FMTPrivate = Crtc->FMTPriv; |
||
1224 | |||
1225 | if (Crtc->Id == RHD_CRTC_1) |
||
1226 | RegOff = FMT1_REG_OFFSET; |
||
1227 | else |
||
1228 | RegOff = FMT2_REG_OFFSET; |
||
1229 | |||
1230 | FMTPrivate->StoreControl = RHDRegRead(Crtc, RegOff + RV620_FMT1_CONTROL); |
||
1231 | FMTPrivate->StoreBitDepthControl = RHDRegRead(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL); |
||
1232 | FMTPrivate->StoreClampCntl = RHDRegRead(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL); |
||
1233 | |||
1234 | Crtc->FMTPriv = FMTPrivate; |
||
1235 | } |
||
1236 | |||
1237 | /* |
||
1238 | * |
||
1239 | */ |
||
1240 | static void |
||
1241 | DxFMTRestore(struct rhdCrtc *Crtc) |
||
1242 | { |
||
1243 | struct rhdCrtcFMTPrivate *FMTPrivate = Crtc->FMTPriv; |
||
1244 | CARD32 RegOff; |
||
1245 | |||
1246 | RHDFUNC(Crtc); |
||
1247 | |||
1248 | if (!FMTPrivate) |
||
1249 | return; |
||
1250 | |||
1251 | if (Crtc->Id == RHD_CRTC_1) |
||
1252 | RegOff = FMT1_REG_OFFSET; |
||
1253 | else |
||
1254 | RegOff = FMT2_REG_OFFSET; |
||
1255 | |||
1256 | RHDRegWrite(Crtc, RegOff + RV620_FMT1_CONTROL, FMTPrivate->StoreControl); |
||
1257 | RHDRegWrite(Crtc, RegOff + RV620_FMT1_BIT_DEPTH_CONTROL, FMTPrivate->StoreBitDepthControl); |
||
1258 | RHDRegWrite(Crtc, RegOff + RV620_FMT1_CLAMP_CNTL, FMTPrivate->StoreClampCntl); |
||
1259 | } |
||
1260 | |||
1261 | /* |
||
1262 | * |
||
1263 | */ |
||
1264 | static void |
||
1265 | DxFMTDestroy(struct rhdCrtc *Crtc) |
||
1266 | { |
||
1267 | RHDFUNC(Crtc); |
||
1268 | |||
1269 | if (Crtc->FMTPriv) |
||
1270 | xfree(Crtc->FMTPriv); |
||
1271 | Crtc->FMTPriv = NULL; |
||
1272 | } |
||
1273 | |||
1274 | /* |
||
1275 | * |
||
1276 | */ |
||
1277 | static enum rhdCrtcScaleType |
||
1278 | rhdInitScaleType(RHDPtr rhdPtr) |
||
1279 | { |
||
1280 | RHDFUNC(rhdPtr); |
||
1281 | /* |
||
1282 | if (rhdPtr->scaleTypeOpt.set) { |
||
1283 | if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "none")) |
||
1284 | return RHD_CRTC_SCALE_TYPE_NONE; |
||
1285 | else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "center")) |
||
1286 | return RHD_CRTC_SCALE_TYPE_CENTER; |
||
1287 | else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "scale")) |
||
1288 | return RHD_CRTC_SCALE_TYPE_SCALE; |
||
1289 | else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "scale_keep_aspect_ratio")) |
||
1290 | return RHD_CRTC_SCALE_TYPE_SCALE_KEEP_ASPECT_RATIO; |
||
1291 | else if (!strcasecmp(rhdPtr->scaleTypeOpt.val.string, "default")) |
||
1292 | return RHD_CRTC_SCALE_TYPE_DEFAULT; |
||
1293 | else { |
||
1294 | xf86DrvMsgVerb(rhdPtr->scrnIndex, X_ERROR, 0, |
||
1295 | "Unknown scale type: %s\n", rhdPtr->scaleTypeOpt.val.string); |
||
1296 | return RHD_CRTC_SCALE_TYPE_DEFAULT; |
||
1297 | } |
||
1298 | } else */ |
||
1299 | return RHD_CRTC_SCALE_TYPE_SCALE; |
||
1300 | } |
||
1301 | |||
1302 | /* |
||
1303 | * |
||
1304 | */ |
||
1305 | Bool |
||
1306 | RHDCrtcsInit(RHDPtr rhdPtr) |
||
1307 | { |
||
1308 | struct rhdCrtc *Crtc; |
||
1309 | enum rhdCrtcScaleType ScaleType; |
||
1310 | Bool useAtom; |
||
1311 | |||
1312 | RHDFUNC(rhdPtr); |
||
1313 | |||
1314 | useAtom = RHDUseAtom(rhdPtr, NULL, atomUsageCrtc); |
||
1315 | |||
1316 | ScaleType = rhdInitScaleType(rhdPtr); |
||
1317 | |||
1318 | Crtc = xnfcalloc(sizeof(struct rhdCrtc), 1); |
||
1319 | Crtc->scrnIndex = rhdPtr->scrnIndex; |
||
1320 | Crtc->Name = "CRTC 1"; |
||
1321 | Crtc->Id = RHD_CRTC_1; |
||
1322 | |||
1323 | Crtc->ScaleType = ScaleType; |
||
1324 | |||
1325 | if (rhdPtr->ChipSet >= RHD_RV620) { |
||
1326 | Crtc->FMTDestroy = DxFMTDestroy; |
||
1327 | Crtc->FMTSave = DxFMTSave; |
||
1328 | Crtc->FMTRestore = DxFMTRestore; |
||
1329 | Crtc->FMTModeSet = DxFMTSet; |
||
1330 | } |
||
1331 | Crtc->FMTPriv = NULL; |
||
1332 | |||
1333 | Crtc->FBValid = DxFBValid; |
||
1334 | Crtc->FBSet = DxFBSet; |
||
1335 | Crtc->FBSave = DxFBSave; |
||
1336 | Crtc->FBRestore = DxFBRestore; |
||
1337 | Crtc->FBDestroy = DxFBDestroy; |
||
1338 | |||
1339 | Crtc->ModeValid = DxModeValid; |
||
1340 | Crtc->ModeSet = DxModeSet; |
||
1341 | Crtc->ModeSave = DxModeSave; |
||
1342 | Crtc->ModeRestore = DxModeRestore; |
||
1343 | Crtc->ModeDestroy = DxModeDestroy; |
||
1344 | Crtc->ModePriv = NULL; |
||
1345 | |||
1346 | Crtc->ScaleValid = DxScaleValid; |
||
1347 | Crtc->ScaleSet = DxScaleSet; |
||
1348 | Crtc->ScaleSave = DxScaleSave; |
||
1349 | Crtc->ScaleRestore = DxScaleRestore; |
||
1350 | Crtc->ScaleDestroy = DxScaleDestroy; |
||
1351 | Crtc->ScalePriv = NULL; |
||
1352 | |||
1353 | Crtc->LUTSelect = D1LUTSelect; |
||
1354 | Crtc->LUTSave = DxLUTSave; |
||
1355 | Crtc->LUTRestore = DxLUTRestore; |
||
1356 | Crtc->LUTDestroy = DxLUTDestroy; |
||
1357 | Crtc->LUTPriv = NULL; |
||
1358 | |||
1359 | Crtc->FrameSet = D1ViewPortStart; |
||
1360 | |||
1361 | Crtc->Power = D1Power; |
||
1362 | Crtc->Blank = D1Blank; |
||
1363 | |||
1364 | rhdPtr->Crtc[0] = Crtc; |
||
1365 | |||
1366 | Crtc = xnfcalloc(sizeof(struct rhdCrtc), 1); |
||
1367 | Crtc->scrnIndex = rhdPtr->scrnIndex; |
||
1368 | Crtc->Name = "CRTC 2"; |
||
1369 | Crtc->Id = RHD_CRTC_2; |
||
1370 | |||
1371 | Crtc->ScaleType = ScaleType; |
||
1372 | |||
1373 | if (rhdPtr->ChipSet >= RHD_RV620) { |
||
1374 | Crtc->FMTDestroy = DxFMTDestroy; |
||
1375 | Crtc->FMTSave = DxFMTSave; |
||
1376 | Crtc->FMTRestore = DxFMTRestore; |
||
1377 | Crtc->FMTModeSet = DxFMTSet; |
||
1378 | } |
||
1379 | Crtc->FMTPriv = NULL; |
||
1380 | |||
1381 | Crtc->FBValid = DxFBValid; |
||
1382 | Crtc->FBSet = DxFBSet; |
||
1383 | Crtc->FBSave = DxFBSave; |
||
1384 | Crtc->FBRestore = DxFBRestore; |
||
1385 | Crtc->FBDestroy = DxFBDestroy; |
||
1386 | |||
1387 | Crtc->ModeValid = DxModeValid; |
||
1388 | Crtc->ModeSet = DxModeSet; |
||
1389 | Crtc->ModeSave = DxModeSave; |
||
1390 | Crtc->ModeRestore = DxModeRestore; |
||
1391 | Crtc->ModeDestroy = DxModeDestroy; |
||
1392 | Crtc->ModePriv = NULL; |
||
1393 | |||
1394 | Crtc->ScaleValid = DxScaleValid; |
||
1395 | Crtc->ScaleSet = DxScaleSet; |
||
1396 | Crtc->ScaleSave = DxScaleSave; |
||
1397 | Crtc->ScaleRestore = DxScaleRestore; |
||
1398 | Crtc->ScaleDestroy = DxScaleDestroy; |
||
1399 | Crtc->ScalePriv = NULL; |
||
1400 | |||
1401 | Crtc->LUTSelect = D2LUTSelect; |
||
1402 | Crtc->LUTSave = DxLUTSave; |
||
1403 | Crtc->LUTRestore = DxLUTRestore; |
||
1404 | Crtc->LUTDestroy = DxLUTDestroy; |
||
1405 | Crtc->LUTPriv = NULL; |
||
1406 | |||
1407 | Crtc->FrameSet = D2ViewPortStart; |
||
1408 | |||
1409 | Crtc->Power = D2Power; |
||
1410 | Crtc->Blank = D2Blank; |
||
1411 | |||
1412 | rhdPtr->Crtc[1] = Crtc; |
||
1413 | |||
1414 | return !useAtom; |
||
1415 | } |
||
1416 | |||
1417 | /* |
||
1418 | * |
||
1419 | */ |
||
1420 | void |
||
1421 | RHDCrtcsDestroy(RHDPtr rhdPtr) |
||
1422 | { |
||
1423 | struct rhdCrtc *Crtc; |
||
1424 | int i; |
||
1425 | |||
1426 | RHDFUNC(rhdPtr); |
||
1427 | |||
1428 | for (i = 0; i < 2; i++) { |
||
1429 | Crtc = rhdPtr->Crtc[i]; |
||
1430 | if (Crtc) { |
||
1431 | if (Crtc->FMTDestroy) |
||
1432 | Crtc->FMTDestroy(Crtc); |
||
1433 | |||
1434 | if (Crtc->LUTDestroy) |
||
1435 | Crtc->LUTDestroy(Crtc); |
||
1436 | |||
1437 | if (Crtc->FBDestroy) |
||
1438 | Crtc->FBDestroy(Crtc); |
||
1439 | |||
1440 | if (Crtc->ScaleDestroy) |
||
1441 | Crtc->ScaleDestroy(Crtc); |
||
1442 | |||
1443 | if (Crtc->ModeDestroy) |
||
1444 | Crtc->ModeDestroy(Crtc); |
||
1445 | |||
1446 | xfree(Crtc); |
||
1447 | rhdPtr->Crtc[i] = NULL; |
||
1448 | } |
||
1449 | } |
||
1450 | } |
||
1451 | |||
1452 | |||
1453 | /* |
||
1454 | * |
||
1455 | */ |
||
1456 | void |
||
1457 | RHDCrtcSave(struct rhdCrtc *Crtc) |
||
1458 | { |
||
1459 | RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name); |
||
1460 | |||
1461 | if (Crtc->FMTSave) |
||
1462 | Crtc->FMTSave(Crtc); |
||
1463 | |||
1464 | if (Crtc->FBSave) |
||
1465 | Crtc->FBSave(Crtc); |
||
1466 | |||
1467 | if (Crtc->LUTSave) |
||
1468 | Crtc->LUTSave(Crtc); |
||
1469 | |||
1470 | if (Crtc->ScaleSave) |
||
1471 | Crtc->ScaleSave(Crtc); |
||
1472 | |||
1473 | if (Crtc->ModeSave) |
||
1474 | Crtc->ModeSave(Crtc); |
||
1475 | } |
||
1476 | |||
1477 | /* |
||
1478 | * |
||
1479 | */ |
||
1480 | void |
||
1481 | RHDCrtcRestore(struct rhdCrtc *Crtc) |
||
1482 | { |
||
1483 | |||
1484 | RHDDebug(Crtc->scrnIndex, "%s: %s\n", __func__, Crtc->Name); |
||
1485 | |||
1486 | if (Crtc->FMTRestore) |
||
1487 | Crtc->FMTRestore(Crtc); |
||
1488 | |||
1489 | if (Crtc->FBRestore) |
||
1490 | Crtc->FBRestore(Crtc); |
||
1491 | |||
1492 | if (Crtc->LUTRestore) |
||
1493 | Crtc->LUTRestore(Crtc); |
||
1494 | |||
1495 | if (Crtc->ScaleRestore) |
||
1496 | Crtc->ScaleRestore(Crtc); |
||
1497 | |||
1498 | if (Crtc->ModeRestore) |
||
1499 | Crtc->ModeRestore(Crtc); |
||
1500 | }>>>><>><>><>><>><>>>><>><>><>><>>>> |