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