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