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 | # include |
||
38 | # include |
||
39 | #endif |
||
40 | |||
41 | #include "rhd.h" |
||
42 | #include "rhd_connector.h" |
||
43 | #include "rhd_output.h" |
||
44 | #include "rhd_crtc.h" |
||
45 | #include "rhd_regs.h" |
||
46 | #ifdef ATOM_BIOS |
||
47 | # include "rhd_atombios.h" |
||
48 | #endif |
||
49 | |||
50 | #define REG_DACA_OFFSET 0 |
||
51 | #define RV620_REG_DACA_OFFSET 0 |
||
52 | #define REG_DACB_OFFSET 0x200 |
||
53 | #define RV620_REG_DACB_OFFSET 0x100 |
||
54 | |||
55 | struct rhdDACPrivate { |
||
56 | Bool Stored; |
||
57 | |||
58 | CARD32 Store_Powerdown; |
||
59 | CARD32 Store_Force_Output_Control; |
||
60 | CARD32 Store_Force_Data; |
||
61 | CARD32 Store_Source_Select; |
||
62 | CARD32 Store_Sync_Select; |
||
63 | CARD32 Store_Enable; |
||
64 | CARD32 Store_Control1; |
||
65 | CARD32 Store_Control2; |
||
66 | CARD32 Store_Tristate_Control; |
||
67 | CARD32 Store_Auto_Calib_Control; |
||
68 | CARD32 Store_Dac_Bgadj_Src; |
||
69 | }; |
||
70 | |||
71 | /* ----------------------------------------------------------- */ |
||
72 | |||
73 | /* |
||
74 | * |
||
75 | */ |
||
76 | static unsigned char |
||
77 | DACSense(struct rhdOutput *Output, CARD32 offset, Bool TV) |
||
78 | { |
||
79 | CARD32 CompEnable, Control1, Control2, DetectControl, Enable; |
||
80 | CARD8 ret; |
||
81 | |||
82 | CompEnable = RHDRegRead(Output, offset + DACA_COMPARATOR_ENABLE); |
||
83 | Control1 = RHDRegRead(Output, offset + DACA_CONTROL1); |
||
84 | Control2 = RHDRegRead(Output, offset + DACA_CONTROL2); |
||
85 | DetectControl = RHDRegRead(Output, offset + DACA_AUTODETECT_CONTROL); |
||
86 | Enable = RHDRegRead(Output, offset + DACA_ENABLE); |
||
87 | |||
88 | RHDRegWrite(Output, offset + DACA_ENABLE, 1); |
||
89 | /* ack autodetect */ |
||
90 | RHDRegMask(Output, offset + DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01); |
||
91 | RHDRegMask(Output, offset + DACA_AUTODETECT_CONTROL, 0, 0x00000003); |
||
92 | RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00000001); |
||
93 | RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00ff0000); |
||
94 | |||
95 | if (offset) { /* We can do TV on DACA but only DACB has mux for separate connector */ |
||
96 | if (TV) |
||
97 | RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000100, 0x00000100); |
||
98 | else |
||
99 | RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x00000100); |
||
100 | } |
||
101 | RHDRegWrite(Output, offset + DACA_FORCE_DATA, 0); |
||
102 | RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000001, 0x0000001); |
||
103 | |||
104 | RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, 0x00070000, 0x00070101); |
||
105 | RHDRegWrite(Output, offset + DACA_CONTROL1, 0x00050802); |
||
106 | RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x00000001); /* Shut down Bandgap Voltage Reference Power */ |
||
107 | usleep(5); |
||
108 | |||
109 | RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */ |
||
110 | |||
111 | RHDRegWrite(Output, offset + DACA_FORCE_DATA, 0x1e6); /* 486 out of 1024 */ |
||
112 | usleep(200); |
||
113 | |||
114 | RHDRegMask(Output, offset + DACA_POWERDOWN, 0x01010100, 0x01010100); /* Enable RGB */ |
||
115 | usleep(88); |
||
116 | |||
117 | RHDRegMask(Output, offset + DACA_POWERDOWN, 0, 0x01010100); /* Shut down RGB */ |
||
118 | |||
119 | RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, 0x00000100, 0x00000100); |
||
120 | usleep(100); |
||
121 | |||
122 | /* Get RGB detect values |
||
123 | * If only G is detected, we could have a monochrome monitor, |
||
124 | * but we don't bother with this at the moment. |
||
125 | */ |
||
126 | ret = (RHDRegRead(Output, offset + DACA_COMPARATOR_OUTPUT) & 0x0E) >> 1; |
||
127 | |||
128 | RHDRegMask(Output, offset + DACA_COMPARATOR_ENABLE, CompEnable, 0x00FFFFFF); |
||
129 | RHDRegWrite(Output, offset + DACA_CONTROL1, Control1); |
||
130 | RHDRegMask(Output, offset + DACA_CONTROL2, Control2, 0x000001FF); |
||
131 | RHDRegMask(Output, offset + DACA_AUTODETECT_CONTROL, DetectControl, 0x000000FF); |
||
132 | RHDRegMask(Output, offset + DACA_ENABLE, Enable, 0x000000FF); |
||
133 | |||
134 | RHDDebug(Output->scrnIndex, "%s: DAC: 0x0%1X\n", __func__, ret); |
||
135 | |||
136 | return ret; |
||
137 | } |
||
138 | |||
139 | /* |
||
140 | * |
||
141 | */ |
||
142 | static enum rhdSensedOutput |
||
143 | DACASense(struct rhdOutput *Output, struct rhdConnector *Connector) |
||
144 | { |
||
145 | enum rhdConnectorType Type = Connector->Type; |
||
146 | RHDFUNC(Output); |
||
147 | |||
148 | switch (Type) { |
||
149 | case RHD_CONNECTOR_DVI: |
||
150 | case RHD_CONNECTOR_DVI_SINGLE: |
||
151 | case RHD_CONNECTOR_VGA: |
||
152 | return (DACSense(Output, REG_DACA_OFFSET, FALSE) == 0x7) |
||
153 | ? RHD_SENSED_VGA |
||
154 | : RHD_SENSED_NONE; |
||
155 | default: |
||
156 | xf86DrvMsg(Output->scrnIndex, X_WARNING, |
||
157 | "%s: connector type %d is not supported on DACA.\n", |
||
158 | __func__, Type); |
||
159 | return RHD_SENSED_NONE; |
||
160 | } |
||
161 | } |
||
162 | |||
163 | /* |
||
164 | * |
||
165 | */ |
||
166 | static enum rhdSensedOutput |
||
167 | DACBSense(struct rhdOutput *Output, struct rhdConnector *Connector) |
||
168 | { |
||
169 | enum rhdConnectorType Type = Connector->Type; |
||
170 | RHDFUNC(Output); |
||
171 | |||
172 | switch (Type) { |
||
173 | case RHD_CONNECTOR_DVI: |
||
174 | case RHD_CONNECTOR_DVI_SINGLE: |
||
175 | case RHD_CONNECTOR_VGA: |
||
176 | return (DACSense(Output, REG_DACB_OFFSET, FALSE) == 0x7) |
||
177 | ? RHD_SENSED_VGA |
||
178 | : RHD_SENSED_NONE; |
||
179 | case RHD_CONNECTOR_TV: |
||
180 | switch (DACSense(Output, REG_DACB_OFFSET, TRUE) & 0x7) { |
||
181 | case 0x7: |
||
182 | return RHD_SENSED_TV_COMPONENT; |
||
183 | case 0x6: |
||
184 | return RHD_SENSED_TV_SVIDEO; |
||
185 | case 0x1: |
||
186 | return RHD_SENSED_TV_COMPOSITE; |
||
187 | default: |
||
188 | return RHD_SENSED_NONE; |
||
189 | } |
||
190 | default: |
||
191 | xf86DrvMsg(Output->scrnIndex, X_WARNING, |
||
192 | "%s: connector type %d is not supported on DACB.\n", |
||
193 | __func__, Type); |
||
194 | return RHD_SENSED_NONE; |
||
195 | } |
||
196 | } |
||
197 | |||
198 | enum outputType { |
||
199 | TvPAL = 0, |
||
200 | TvNTSC, |
||
201 | VGA, |
||
202 | TvCV, |
||
203 | typeLast = VGA |
||
204 | }; |
||
205 | |||
206 | /* |
||
207 | * |
||
208 | */ |
||
209 | static void |
||
210 | DACGetElectrical(RHDPtr rhdPtr, enum outputType type, int dac, CARD8 *bandgap, CARD8 *whitefine) |
||
211 | { |
||
212 | #ifdef ATOM_BIOS |
||
213 | enum _AtomBiosRequestID bg = 0, wf = 0; |
||
214 | AtomBiosArgRec atomBiosArg; |
||
215 | #endif |
||
216 | struct |
||
217 | { |
||
218 | CARD16 pciIdMin; |
||
219 | CARD16 pciIdMax; |
||
220 | CARD8 bandgap[2][4]; |
||
221 | CARD8 whitefine[2][4]; |
||
222 | } list[] = { |
||
223 | { 0x791E, 0x791F, |
||
224 | { { 0x07, 0x07, 0x07, 0x07 }, |
||
225 | { 0x07, 0x07, 0x07, 0x07 } }, |
||
226 | { { 0x09, 0x09, 0x04, 0x09 }, |
||
227 | { 0x09, 0x09, 0x04, 0x09 } }, |
||
228 | }, |
||
229 | { 0x793F, 0x7942, |
||
230 | { { 0x09, 0x09, 0x09, 0x09 }, |
||
231 | { 0x09, 0x09, 0x09, 0x09 } }, |
||
232 | { { 0x0a, 0x0a, 0x08, 0x0a }, |
||
233 | { 0x0a, 0x0a, 0x08, 0x0a } }, |
||
234 | }, |
||
235 | { 0x9500, 0x9519, |
||
236 | { { 0x00, 0x00, 0x00, 0x00 }, |
||
237 | { 0x00, 0x00, 0x00, 0x00 } }, |
||
238 | { { 0x00, 0x00, 0x20, 0x00 }, |
||
239 | { 0x25, 0x25, 0x26, 0x26 } }, |
||
240 | }, |
||
241 | { 0, 0, |
||
242 | { { 0, 0, 0, 0 }, |
||
243 | { 0, 0, 0, 0 } }, |
||
244 | { { 0, 0, 0, 0 }, |
||
245 | { 0, 0, 0, 0 } } |
||
246 | } |
||
247 | }; |
||
248 | |||
249 | *bandgap = *whitefine = 0; |
||
250 | |||
251 | #ifdef ATOM_BIOS |
||
252 | switch (type) { |
||
253 | case TvPAL: |
||
254 | bg = ATOM_DAC2_PAL_BG_ADJ; |
||
255 | wf = ATOM_DAC2_PAL_DAC_ADJ; |
||
256 | break; |
||
257 | case TvNTSC: |
||
258 | bg = ATOM_DAC2_NTSC_BG_ADJ; |
||
259 | wf = ATOM_DAC2_NTSC_DAC_ADJ; |
||
260 | break; |
||
261 | case TvCV: |
||
262 | bg = ATOM_DAC2_CV_BG_ADJ; |
||
263 | wf = ATOM_DAC2_CV_DAC_ADJ; |
||
264 | break; |
||
265 | case VGA: |
||
266 | switch (dac) { |
||
267 | case 0: |
||
268 | bg = ATOM_DAC1_BG_ADJ; |
||
269 | wf = ATOM_DAC1_DAC_ADJ; |
||
270 | break; |
||
271 | default: |
||
272 | bg = ATOM_DAC2_CRTC2_BG_ADJ; |
||
273 | wf = ATOM_DAC2_CRTC2_DAC_ADJ; |
||
274 | break; |
||
275 | } |
||
276 | break; |
||
277 | } |
||
278 | if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, bg, &atomBiosArg) |
||
279 | == ATOM_SUCCESS) { |
||
280 | *bandgap = atomBiosArg.val; |
||
281 | RHDDebug(rhdPtr->scrnIndex, "%s: BandGap found in CompassionateData.\n",__func__); |
||
282 | } |
||
283 | if (RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, wf, &atomBiosArg) |
||
284 | == ATOM_SUCCESS) { |
||
285 | *whitefine = atomBiosArg.val; |
||
286 | RHDDebug(rhdPtr->scrnIndex, "%s: WhiteFine found in CompassionateData.\n",__func__); |
||
287 | } |
||
288 | if (*whitefine == 0) { |
||
289 | CARD8 w_f = 0, b_g = 0; |
||
290 | |||
291 | if (atomBiosArg.val = 0x18, |
||
292 | RHDAtomBiosFunc(rhdPtr->scrnIndex, rhdPtr->atomBIOS, |
||
293 | ATOMBIOS_GET_CODE_DATA_TABLE, |
||
294 | &atomBiosArg) == ATOM_SUCCESS) { |
||
295 | struct AtomDacCodeTableData *data |
||
296 | = (struct AtomDacCodeTableData *)atomBiosArg.CommandDataTable.loc; |
||
297 | if (atomBiosArg.CommandDataTable.size |
||
298 | < (sizeof (struct AtomDacCodeTableData) >> (dac ? 0 : 1))) { /* IGPs only have 1 DAC -> table_size / 2 */ |
||
299 | xf86DrvMsg(rhdPtr->scrnIndex, X_ERROR, |
||
300 | "Code table data size: %i doesn't match expected size: %u\n", |
||
301 | atomBiosArg.CommandDataTable.size, |
||
302 | (unsigned int) sizeof (struct AtomDacCodeTableData)); |
||
303 | return; |
||
304 | } |
||
305 | RHDDebug(rhdPtr->scrnIndex, "%s: WhiteFine found in Code Table.\n",__func__); |
||
306 | switch (type) { |
||
307 | case TvPAL: |
||
308 | w_f = dac ? data->DAC2PALWhiteFine : data->DAC1PALWhiteFine; |
||
309 | b_g = dac ? data->DAC2PALBandGap : data->DAC1PALBandGap; |
||
310 | break; |
||
311 | case TvNTSC: |
||
312 | w_f = dac ? data->DAC2NTSCWhiteFine : data->DAC1NTSCWhiteFine; |
||
313 | b_g = dac ? data->DAC2NTSCBandGap : data->DAC1NTSCBandGap; |
||
314 | break; |
||
315 | case TvCV: |
||
316 | w_f = dac ? data->DAC2CVWhiteFine : data->DAC1CVWhiteFine; |
||
317 | b_g = dac ? data->DAC2CVBandGap : data->DAC1CVBandGap; |
||
318 | break; |
||
319 | case VGA: |
||
320 | w_f = dac ? data->DAC2VGAWhiteFine : data->DAC1VGAWhiteFine; |
||
321 | b_g = dac ? data->DAC2VGABandGap : data->DAC1VGABandGap; |
||
322 | break; |
||
323 | } |
||
324 | *whitefine = w_f; |
||
325 | if (rhdPtr->ChipSet >= RHD_RV770) /* Dunno why this is broken on older ASICs */ |
||
326 | *bandgap = b_g; |
||
327 | } |
||
328 | } |
||
329 | #endif |
||
330 | if (*bandgap == 0 || *whitefine == 0) { |
||
331 | int i = 0; |
||
332 | while (list[i].pciIdMin != 0) { |
||
333 | if (list[i].pciIdMin <= rhdPtr->PciDeviceID |
||
334 | && list[i].pciIdMax >= rhdPtr->PciDeviceID) { |
||
335 | #if 0 |
||
336 | ErrorF(">> %x %x %x -- %x %x\n",list[i].pciIdMin, |
||
337 | rhdPtr->PciDeviceID,list[i].pciIdMax, |
||
338 | list[i].bandgap[dac][type],list[i].whitefine[dac][type]); |
||
339 | ErrorF(">> %i %i\n",dac,type); |
||
340 | #endif |
||
341 | if (*bandgap == 0) *bandgap = list[i].bandgap[dac][type]; |
||
342 | if (*whitefine == 0) *whitefine = list[i].whitefine[dac][type]; |
||
343 | break; |
||
344 | } |
||
345 | i++; |
||
346 | } |
||
347 | if (list[i].pciIdMin != 0) |
||
348 | RHDDebug(rhdPtr->scrnIndex, "%s: BandGap and WhiteFine found in Table.\n",__func__); |
||
349 | } |
||
350 | RHDDebug(rhdPtr->scrnIndex, "%s: DAC[%i] BandGap: 0x%2.2x WhiteFine: 0x%2.2x\n", |
||
351 | __func__, dac, *bandgap, *whitefine); |
||
352 | } |
||
353 | |||
354 | /* |
||
355 | * |
||
356 | */ |
||
357 | static inline void |
||
358 | DACSet(struct rhdOutput *Output, CARD16 offset) |
||
359 | { |
||
360 | RHDPtr rhdPtr = RHDPTRI(Output); |
||
361 | CARD8 Standard, WhiteFine, Bandgap; |
||
362 | Bool TV; |
||
363 | CARD32 Mask = 0; |
||
364 | |||
365 | switch (Output->SensedType) { |
||
366 | case RHD_SENSED_TV_SVIDEO: |
||
367 | case RHD_SENSED_TV_COMPOSITE: |
||
368 | /* might want to selectively enable lines based on type */ |
||
369 | TV = TRUE; |
||
370 | |||
371 | switch (rhdPtr->tvMode) { |
||
372 | case RHD_TV_NTSC: |
||
373 | case RHD_TV_NTSCJ: |
||
374 | DACGetElectrical(rhdPtr, TvNTSC, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
375 | Standard = 1; /* NTSC */ |
||
376 | break; |
||
377 | case RHD_TV_PAL: |
||
378 | case RHD_TV_PALN: |
||
379 | case RHD_TV_PALCN: |
||
380 | case RHD_TV_PAL60: |
||
381 | default: |
||
382 | DACGetElectrical(rhdPtr, TvPAL, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
383 | Standard = 0; /* PAL */ |
||
384 | break; |
||
385 | } |
||
386 | break; |
||
387 | |||
388 | case RHD_SENSED_TV_COMPONENT: |
||
389 | TV = TRUE; |
||
390 | DACGetElectrical(rhdPtr, TvCV, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
391 | Standard = 3; /* HDTV */ |
||
392 | break; |
||
393 | |||
394 | case RHD_SENSED_VGA: |
||
395 | default: |
||
396 | TV = FALSE; |
||
397 | DACGetElectrical(rhdPtr, VGA, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
398 | Standard = 2; /* VGA */ |
||
399 | break; |
||
400 | } |
||
401 | if (Bandgap) Mask |= 0xFF << 16; |
||
402 | if (WhiteFine) Mask |= 0xFF << 8; |
||
403 | |||
404 | RHDRegMask(Output, offset + DACA_CONTROL1, Standard, 0x000000FF); |
||
405 | /* white level fine adjust */ |
||
406 | RHDRegMask(Output, offset + DACA_CONTROL1, (Bandgap << 16) | (WhiteFine << 8), Mask); |
||
407 | |||
408 | if (TV) { |
||
409 | /* tv enable */ |
||
410 | if (offset) /* TV mux only available on DACB */ |
||
411 | RHDRegMask(Output, offset + DACA_CONTROL2, 0x00000100, 0x0000FF00); |
||
412 | /* select tv encoder */ |
||
413 | RHDRegMask(Output, offset + DACA_SOURCE_SELECT, 0x00000002, 0x00000003); |
||
414 | } else { |
||
415 | if (offset) /* TV mux only available on DACB */ |
||
416 | RHDRegMask(Output, offset + DACA_CONTROL2, 0, 0x0000FF00); |
||
417 | /* select a crtc */ |
||
418 | RHDRegMask(Output, offset + DACA_SOURCE_SELECT, Output->Crtc->Id & 0x01, 0x00000003); |
||
419 | } |
||
420 | |||
421 | RHDRegMask(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0x00000701, 0x00000701); |
||
422 | RHDRegMask(Output, offset + DACA_FORCE_DATA, 0, 0x0000FFFF); |
||
423 | } |
||
424 | |||
425 | /* |
||
426 | * |
||
427 | */ |
||
428 | static void |
||
429 | DACASet(struct rhdOutput *Output, DisplayModePtr unused) |
||
430 | { |
||
431 | RHDFUNC(Output); |
||
432 | |||
433 | DACSet(Output, REG_DACA_OFFSET); |
||
434 | } |
||
435 | |||
436 | /* |
||
437 | * |
||
438 | */ |
||
439 | static void |
||
440 | DACBSet(struct rhdOutput *Output, DisplayModePtr unused) |
||
441 | { |
||
442 | RHDFUNC(Output); |
||
443 | |||
444 | DACSet(Output, REG_DACB_OFFSET); |
||
445 | } |
||
446 | |||
447 | /* |
||
448 | * |
||
449 | */ |
||
450 | static inline void |
||
451 | DACPower(struct rhdOutput *Output, CARD16 offset, int Power) |
||
452 | { |
||
453 | CARD32 powerdown; |
||
454 | |||
455 | RHDDebug(Output->scrnIndex, "%s(%s,%s)\n",__func__,Output->Name, |
||
456 | rhdPowerString[Power]); |
||
457 | |||
458 | switch (Power) { |
||
459 | case RHD_POWER_ON: |
||
460 | switch (Output->SensedType) { |
||
461 | case RHD_SENSED_TV_SVIDEO: |
||
462 | powerdown = 0 /* 0x100 */; |
||
463 | break; |
||
464 | case RHD_SENSED_TV_COMPOSITE: |
||
465 | powerdown = 0 /* 0x1010000 */; |
||
466 | break; |
||
467 | case RHD_SENSED_TV_COMPONENT: |
||
468 | powerdown = 0; |
||
469 | break; |
||
470 | case RHD_SENSED_VGA: |
||
471 | default: |
||
472 | powerdown = 0; |
||
473 | break; |
||
474 | } |
||
475 | RHDRegWrite(Output, offset + DACA_ENABLE, 1); |
||
476 | RHDRegWrite(Output, offset + DACA_POWERDOWN, 0); |
||
477 | usleep (14); |
||
478 | RHDRegMask(Output, offset + DACA_POWERDOWN, powerdown, 0xFFFFFF00); |
||
479 | usleep(2); |
||
480 | RHDRegWrite(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0); |
||
481 | RHDRegMask(Output, offset + DACA_SYNC_SELECT, 0, 0x00000101); |
||
482 | RHDRegWrite(Output, offset + DACA_SYNC_TRISTATE_CONTROL, 0); |
||
483 | return; |
||
484 | case RHD_POWER_RESET: /* don't bother */ |
||
485 | return; |
||
486 | case RHD_POWER_SHUTDOWN: |
||
487 | default: |
||
488 | RHDRegMask(Output, offset + DACA_FORCE_DATA, 0, 0x0000FFFF); |
||
489 | RHDRegMask(Output, offset + DACA_FORCE_OUTPUT_CNTL, 0x0000701, 0x0000701); |
||
490 | RHDRegWrite(Output, offset + DACA_POWERDOWN, 0x01010100); |
||
491 | RHDRegWrite(Output, offset + DACA_POWERDOWN, 0x01010101); |
||
492 | RHDRegWrite(Output, offset + DACA_ENABLE, 0); |
||
493 | RHDRegWrite(Output, offset + DACA_ENABLE, 0); |
||
494 | return; |
||
495 | } |
||
496 | } |
||
497 | |||
498 | /* |
||
499 | * |
||
500 | */ |
||
501 | static void |
||
502 | DACAPower(struct rhdOutput *Output, int Power) |
||
503 | { |
||
504 | RHDFUNC(Output); |
||
505 | |||
506 | DACPower(Output, REG_DACA_OFFSET, Power); |
||
507 | } |
||
508 | |||
509 | /* |
||
510 | * |
||
511 | */ |
||
512 | static void |
||
513 | DACBPower(struct rhdOutput *Output, int Power) |
||
514 | { |
||
515 | RHDFUNC(Output); |
||
516 | |||
517 | DACPower(Output, REG_DACB_OFFSET, Power); |
||
518 | } |
||
519 | |||
520 | /* |
||
521 | * |
||
522 | */ |
||
523 | static inline void |
||
524 | DACSave(struct rhdOutput *Output, CARD16 offset) |
||
525 | { |
||
526 | struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private; |
||
527 | |||
528 | Private->Store_Powerdown = RHDRegRead(Output, offset + DACA_POWERDOWN); |
||
529 | Private->Store_Force_Output_Control = RHDRegRead(Output, offset + DACA_FORCE_OUTPUT_CNTL); |
||
530 | Private->Store_Force_Data = RHDRegRead(Output, offset + DACA_FORCE_DATA); |
||
531 | Private->Store_Source_Select = RHDRegRead(Output, offset + DACA_SOURCE_SELECT); |
||
532 | Private->Store_Sync_Select = RHDRegRead(Output, offset + DACA_SYNC_SELECT); |
||
533 | Private->Store_Enable = RHDRegRead(Output, offset + DACA_ENABLE); |
||
534 | Private->Store_Control1 = RHDRegRead(Output, offset + DACA_CONTROL1); |
||
535 | Private->Store_Control2 = RHDRegRead(Output, offset + DACA_CONTROL2); |
||
536 | Private->Store_Tristate_Control = RHDRegRead(Output, offset + DACA_SYNC_TRISTATE_CONTROL); |
||
537 | |||
538 | Private->Stored = TRUE; |
||
539 | } |
||
540 | |||
541 | /* |
||
542 | * |
||
543 | */ |
||
544 | static void |
||
545 | DACASave(struct rhdOutput *Output) |
||
546 | { |
||
547 | RHDFUNC(Output); |
||
548 | |||
549 | DACSave(Output, REG_DACA_OFFSET); |
||
550 | } |
||
551 | |||
552 | /* |
||
553 | * |
||
554 | */ |
||
555 | static void |
||
556 | DACBSave(struct rhdOutput *Output) |
||
557 | { |
||
558 | RHDFUNC(Output); |
||
559 | |||
560 | DACSave(Output, REG_DACB_OFFSET); |
||
561 | } |
||
562 | |||
563 | /* |
||
564 | * |
||
565 | */ |
||
566 | static inline void |
||
567 | DACRestore(struct rhdOutput *Output, CARD16 offset) |
||
568 | { |
||
569 | struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private; |
||
570 | |||
571 | RHDRegWrite(Output, offset + DACA_POWERDOWN, Private->Store_Powerdown); |
||
572 | RHDRegWrite(Output, offset + DACA_FORCE_OUTPUT_CNTL, Private->Store_Force_Output_Control); |
||
573 | RHDRegWrite(Output, offset + DACA_FORCE_DATA, Private->Store_Force_Data); |
||
574 | RHDRegWrite(Output, offset + DACA_SOURCE_SELECT, Private->Store_Source_Select); |
||
575 | RHDRegWrite(Output, offset + DACA_SYNC_SELECT, Private->Store_Sync_Select); |
||
576 | RHDRegWrite(Output, offset + DACA_ENABLE, Private->Store_Enable); |
||
577 | RHDRegWrite(Output, offset + DACA_CONTROL1, Private->Store_Control1); |
||
578 | RHDRegWrite(Output, offset + DACA_CONTROL2, Private->Store_Control2); |
||
579 | RHDRegWrite(Output, offset + DACA_SYNC_TRISTATE_CONTROL, Private->Store_Tristate_Control); |
||
580 | } |
||
581 | |||
582 | /* |
||
583 | * |
||
584 | */ |
||
585 | static void |
||
586 | DACARestore(struct rhdOutput *Output) |
||
587 | { |
||
588 | RHDFUNC(Output); |
||
589 | |||
590 | if (!((struct rhdDACPrivate *) Output->Private)->Stored) { |
||
591 | xf86DrvMsg(Output->scrnIndex, X_ERROR, |
||
592 | "%s: No registers stored.\n", __func__); |
||
593 | return; |
||
594 | } |
||
595 | |||
596 | DACRestore(Output, REG_DACA_OFFSET); |
||
597 | } |
||
598 | |||
599 | /* |
||
600 | * |
||
601 | */ |
||
602 | static void |
||
603 | DACBRestore(struct rhdOutput *Output) |
||
604 | { |
||
605 | RHDFUNC(Output); |
||
606 | |||
607 | if (!((struct rhdDACPrivate *) Output->Private)->Stored) { |
||
608 | xf86DrvMsg(Output->scrnIndex, X_ERROR, |
||
609 | "%s: No registers stored.\n", __func__); |
||
610 | return; |
||
611 | } |
||
612 | |||
613 | DACRestore(Output, REG_DACB_OFFSET); |
||
614 | } |
||
615 | |||
616 | /* ----------------------------------------------------------- */ |
||
617 | |||
618 | /* |
||
619 | * |
||
620 | */ |
||
621 | static CARD32 |
||
622 | DACSenseRV620(struct rhdOutput *Output, CARD32 offset, Bool TV) |
||
623 | { |
||
624 | CARD32 ret; |
||
625 | CARD32 DetectControl, AutodetectIntCtl, ForceData, |
||
626 | Control1, Control2, CompEnable; |
||
627 | |||
628 | RHDFUNC(Output); |
||
629 | |||
630 | Control1 = RHDRegRead(Output, offset + RV620_DACA_MACRO_CNTL); /* 7ef4 */ |
||
631 | Control2 = RHDRegRead(Output, offset + RV620_DACA_CONTROL2); /* 7058 */ |
||
632 | ForceData = RHDRegRead(Output, offset + RV620_DACA_FORCE_DATA); |
||
633 | AutodetectIntCtl = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL); |
||
634 | DetectControl = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_CONTROL); |
||
635 | CompEnable = RHDRegRead(Output, offset + RV620_DACA_COMPARATOR_ENABLE); |
||
636 | |||
637 | if (offset) { /* We can do TV on DACA but only DACB has mux for separate connector */ |
||
638 | if (TV) |
||
639 | RHDRegMask(Output, offset + RV620_DACA_CONTROL2, 0x100, 0xff00); |
||
640 | else |
||
641 | RHDRegMask(Output, offset + RV620_DACA_CONTROL2, 0x00, 0xff00); |
||
642 | } |
||
643 | RHDRegMask(Output, offset + RV620_DACA_FORCE_DATA, 0x18, 0xffff); |
||
644 | RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL, 0x01, 0x01); |
||
645 | RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_CONTROL, 0x00, 0xff); |
||
646 | RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL, |
||
647 | (offset > 0) ? 0x2502 : 0x2002, 0xffff); |
||
648 | /* enable comparators for R/G/B, disable DDET and SDET reference */ |
||
649 | RHDRegMask(Output, offset + RV620_DACA_COMPARATOR_ENABLE, 0x70000, 0x070101); |
||
650 | RHDRegMask(Output, offset + RV620_DACA_AUTODETECT_CONTROL, 0x01, 0xff); |
||
651 | usleep(32); |
||
652 | ret = RHDRegRead(Output, offset + RV620_DACA_AUTODETECT_STATUS); |
||
653 | RHDRegWrite(Output, offset + RV620_DACA_AUTODETECT_CONTROL, DetectControl); |
||
654 | RHDRegWrite(Output, offset + RV620_DACA_MACRO_CNTL, Control1); |
||
655 | RHDRegWrite(Output, offset + RV620_DACA_CONTROL2, Control2); |
||
656 | RHDRegWrite(Output, offset + RV620_DACA_FORCE_DATA, ForceData); |
||
657 | RHDRegWrite(Output, offset + RV620_DACA_AUTODETECT_INT_CONTROL, AutodetectIntCtl); |
||
658 | #ifdef DEBUG |
||
659 | RHDDebug(Output->scrnIndex, "DAC%i: ret = 0x%x %s\n",offset ? "A" : "B", |
||
660 | ret,TV ? "TV" : ""); |
||
661 | #endif |
||
662 | return ret; |
||
663 | } |
||
664 | |||
665 | /* |
||
666 | * |
||
667 | */ |
||
668 | static enum rhdSensedOutput |
||
669 | DACASenseRV620(struct rhdOutput *Output, struct rhdConnector *Connector) |
||
670 | { |
||
671 | enum rhdConnectorType Type = Connector->Type; |
||
672 | RHDFUNC(Output); |
||
673 | |||
674 | switch (Type) { |
||
675 | case RHD_CONNECTOR_DVI: |
||
676 | case RHD_CONNECTOR_DVI_SINGLE: |
||
677 | case RHD_CONNECTOR_VGA: |
||
678 | return (DACSenseRV620(Output, RV620_REG_DACA_OFFSET, FALSE) |
||
679 | & 0x1010100) ? RHD_SENSED_VGA : RHD_SENSED_NONE; |
||
680 | case RHD_CONNECTOR_TV: |
||
681 | switch (DACSenseRV620(Output, RV620_REG_DACA_OFFSET, TRUE) |
||
682 | & 0x1010100) { |
||
683 | case 0x1010100: |
||
684 | return RHD_SENSED_NONE; /* on DAC A we cannot distinguish VGA and CV */ |
||
685 | case 0x10100: |
||
686 | return RHD_SENSED_TV_SVIDEO; |
||
687 | case 0x1000000: |
||
688 | return RHD_SENSED_TV_COMPOSITE; |
||
689 | default: |
||
690 | return RHD_SENSED_NONE; |
||
691 | } |
||
692 | default: |
||
693 | xf86DrvMsg(Output->scrnIndex, X_WARNING, |
||
694 | "%s: connector type %d is not supported.\n", |
||
695 | __func__, Type); |
||
696 | return RHD_SENSED_NONE; |
||
697 | } |
||
698 | } |
||
699 | |||
700 | /* |
||
701 | * |
||
702 | */ |
||
703 | static enum rhdSensedOutput |
||
704 | DACBSenseRV620(struct rhdOutput *Output, struct rhdConnector *Connector) |
||
705 | { |
||
706 | enum rhdConnectorType Type = Connector->Type; |
||
707 | RHDFUNC(Output); |
||
708 | |||
709 | switch (Type) { |
||
710 | case RHD_CONNECTOR_DVI: |
||
711 | case RHD_CONNECTOR_DVI_SINGLE: |
||
712 | case RHD_CONNECTOR_VGA: |
||
713 | return (DACSenseRV620(Output, RV620_REG_DACB_OFFSET, FALSE) |
||
714 | & 0x1010100) ? RHD_SENSED_VGA : RHD_SENSED_NONE; |
||
715 | case RHD_CONNECTOR_TV: |
||
716 | switch (DACSenseRV620(Output, RV620_REG_DACB_OFFSET, TRUE) |
||
717 | & 0x1010100) { |
||
718 | case 0x1000000: |
||
719 | return RHD_SENSED_TV_COMPONENT; |
||
720 | case 0x1010100: |
||
721 | return RHD_SENSED_TV_SVIDEO; |
||
722 | case 0x10100: |
||
723 | return RHD_SENSED_TV_COMPOSITE; |
||
724 | default: |
||
725 | return RHD_SENSED_NONE; |
||
726 | } |
||
727 | default: |
||
728 | xf86DrvMsg(Output->scrnIndex, X_WARNING, |
||
729 | "%s: connector type %d is not supported.\n", |
||
730 | __func__, Type); |
||
731 | return RHD_SENSED_NONE; |
||
732 | } |
||
733 | } |
||
734 | |||
735 | /* |
||
736 | * |
||
737 | */ |
||
738 | static inline void |
||
739 | DACSetRV620(struct rhdOutput *Output, CARD16 offset) |
||
740 | { |
||
741 | RHDPtr rhdPtr = RHDPTRI(Output); |
||
742 | CARD32 Source; |
||
743 | CARD32 Mode; |
||
744 | CARD32 TV; |
||
745 | CARD8 WhiteFine, Bandgap; |
||
746 | CARD32 Mask = 0; |
||
747 | |||
748 | switch (Output->SensedType) { |
||
749 | case RHD_SENSED_TV_SVIDEO: |
||
750 | case RHD_SENSED_TV_COMPOSITE: |
||
751 | TV = 0x1; |
||
752 | Source = 0x2; /* tv encoder */ |
||
753 | switch (rhdPtr->tvMode) { |
||
754 | case RHD_TV_NTSC: |
||
755 | case RHD_TV_NTSCJ: |
||
756 | DACGetElectrical(rhdPtr, TvNTSC, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
757 | Mode = 1; |
||
758 | break; |
||
759 | case RHD_TV_PAL: |
||
760 | case RHD_TV_PALN: |
||
761 | case RHD_TV_PALCN: |
||
762 | case RHD_TV_PAL60: |
||
763 | default: |
||
764 | DACGetElectrical(rhdPtr, TvPAL, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
765 | Mode = 0; |
||
766 | break; |
||
767 | } |
||
768 | break; |
||
769 | case RHD_SENSED_TV_COMPONENT: |
||
770 | DACGetElectrical(rhdPtr, TvCV, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
771 | Mode = 3; /* HDTV */ |
||
772 | TV = 0x1; /* tv on?? */ |
||
773 | Source = 0x2; /* tv encoder ?? */ |
||
774 | break; |
||
775 | case RHD_SENSED_VGA: |
||
776 | default: |
||
777 | DACGetElectrical(rhdPtr, VGA, offset ? 1 : 0, &Bandgap, &WhiteFine); |
||
778 | Mode = 2; |
||
779 | TV = 0; |
||
780 | Source = Output->Crtc->Id; |
||
781 | break; |
||
782 | } |
||
783 | if (Bandgap) Mask |= 0xFF << 16; |
||
784 | if (WhiteFine) Mask |= 0xFF << 8; |
||
785 | |||
786 | RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL, Mode, 0xFF); /* no fine control yet */ |
||
787 | RHDRegMask(Output, offset + RV620_DACA_SOURCE_SELECT, Source, 0x00000003); |
||
788 | if (offset) /* TV mux only present on DACB */ |
||
789 | RHDRegMask(Output, offset + RV620_DACA_CONTROL2, TV << 8, 0x0100); /* tv enable/disable */ |
||
790 | /* use fine control from white_fine control register */ |
||
791 | RHDRegMask(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL, 0x0, 0x4); |
||
792 | RHDRegMask(Output, offset + RV620_DACA_BGADJ_SRC, 0x0, 0x30); |
||
793 | RHDRegMask(Output, offset + RV620_DACA_MACRO_CNTL, (Bandgap << 16) | (WhiteFine << 8), Mask); |
||
794 | /* Reset the FMT register on CRTC leading to this output */ |
||
795 | Output->Crtc->FMTModeSet(Output->Crtc, NULL); |
||
796 | } |
||
797 | |||
798 | /* |
||
799 | * |
||
800 | */ |
||
801 | static void |
||
802 | DACASetRV620(struct rhdOutput *Output, DisplayModePtr unused) |
||
803 | { |
||
804 | RHDFUNC(Output); |
||
805 | |||
806 | DACSetRV620(Output, RV620_REG_DACA_OFFSET); |
||
807 | } |
||
808 | |||
809 | /* |
||
810 | * |
||
811 | */ |
||
812 | static void |
||
813 | DACBSetRV620(struct rhdOutput *Output, DisplayModePtr unused) |
||
814 | { |
||
815 | RHDFUNC(Output); |
||
816 | |||
817 | DACSetRV620(Output, RV620_REG_DACB_OFFSET); |
||
818 | } |
||
819 | |||
820 | /* |
||
821 | * |
||
822 | */ |
||
823 | static inline void |
||
824 | DACPowerRV620(struct rhdOutput *Output, CARD16 offset, int Power) |
||
825 | { |
||
826 | CARD32 powerdown; |
||
827 | |||
828 | switch (Power) { |
||
829 | case RHD_POWER_ON: |
||
830 | switch (Output->SensedType) { |
||
831 | case RHD_SENSED_TV_SVIDEO: |
||
832 | powerdown = 0 /* 0x100 */; |
||
833 | break; |
||
834 | case RHD_SENSED_TV_COMPOSITE: |
||
835 | powerdown = 0 /* 0x1010000 */; |
||
836 | break; |
||
837 | case RHD_SENSED_TV_COMPONENT: |
||
838 | powerdown = 0; |
||
839 | break; |
||
840 | case RHD_SENSED_VGA: |
||
841 | default: |
||
842 | powerdown = 0; |
||
843 | break; |
||
844 | } |
||
845 | |||
846 | if (!(RHDRegRead(Output, offset + RV620_DACA_ENABLE) & 0x01)) |
||
847 | RHDRegMask(Output, offset + RV620_DACA_ENABLE, 0x1, 0xff); |
||
848 | RHDRegMask(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x01, 0x01); |
||
849 | RHDRegMask(Output, offset + RV620_DACA_POWERDOWN, 0x0, 0xff); |
||
850 | usleep (0x14); |
||
851 | RHDRegMask(Output, offset + RV620_DACA_POWERDOWN, powerdown, 0xffffff00); |
||
852 | usleep(2); |
||
853 | RHDRegMask(Output, offset + RV620_DACA_FORCE_DATA, 0, 0x0000ffff); |
||
854 | RHDRegWrite(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x0); |
||
855 | RHDRegWrite(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL, 0); |
||
856 | return; |
||
857 | case RHD_POWER_RESET: /* don't bother */ |
||
858 | return; |
||
859 | case RHD_POWER_SHUTDOWN: |
||
860 | default: |
||
861 | RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, 0x01010100); |
||
862 | RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, 0x01010101); |
||
863 | RHDRegWrite(Output, offset + RV620_DACA_ENABLE, 0); |
||
864 | RHDRegMask(Output, offset + RV620_DACA_FORCE_DATA, 0, 0xffff); |
||
865 | RHDRegMask(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, 0x701, 0x701); |
||
866 | return; |
||
867 | } |
||
868 | } |
||
869 | |||
870 | /* |
||
871 | * |
||
872 | */ |
||
873 | static void |
||
874 | DACAPowerRV620(struct rhdOutput *Output, int Power) |
||
875 | { |
||
876 | RHDFUNC(Output); |
||
877 | |||
878 | DACPowerRV620(Output, RV620_REG_DACA_OFFSET, Power); |
||
879 | } |
||
880 | |||
881 | /* |
||
882 | * |
||
883 | */ |
||
884 | static void |
||
885 | DACBPowerRV620(struct rhdOutput *Output, int Power) |
||
886 | { |
||
887 | RHDFUNC(Output); |
||
888 | |||
889 | DACPowerRV620(Output, RV620_REG_DACB_OFFSET, Power); |
||
890 | } |
||
891 | |||
892 | /* |
||
893 | * |
||
894 | */ |
||
895 | static inline void |
||
896 | DACSaveRV620(struct rhdOutput *Output, CARD16 offset) |
||
897 | { |
||
898 | struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private; |
||
899 | |||
900 | Private->Store_Powerdown = RHDRegRead(Output, offset + RV620_DACA_POWERDOWN); |
||
901 | Private->Store_Force_Output_Control = RHDRegRead(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL); |
||
902 | Private->Store_Force_Data = RHDRegRead(Output, offset + RV620_DACA_FORCE_DATA); |
||
903 | Private->Store_Source_Select = RHDRegRead(Output, offset + RV620_DACA_SOURCE_SELECT); |
||
904 | Private->Store_Enable = RHDRegRead(Output, offset + RV620_DACA_ENABLE); |
||
905 | Private->Store_Control1 = RHDRegRead(Output, offset + RV620_DACA_MACRO_CNTL); |
||
906 | Private->Store_Control2 = RHDRegRead(Output, offset + RV620_DACA_CONTROL2); |
||
907 | Private->Store_Tristate_Control = RHDRegRead(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL); |
||
908 | Private->Store_Auto_Calib_Control = RHDRegRead(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL); |
||
909 | Private->Store_Dac_Bgadj_Src = RHDRegRead(Output, offset + RV620_DACA_BGADJ_SRC); |
||
910 | |||
911 | Private->Stored = TRUE; |
||
912 | } |
||
913 | |||
914 | /* |
||
915 | * |
||
916 | */ |
||
917 | static void |
||
918 | DACASaveRV620(struct rhdOutput *Output) |
||
919 | { |
||
920 | RHDFUNC(Output); |
||
921 | |||
922 | DACSaveRV620(Output, RV620_REG_DACA_OFFSET); |
||
923 | } |
||
924 | |||
925 | /* |
||
926 | * |
||
927 | */ |
||
928 | static void |
||
929 | DACBSaveRV620(struct rhdOutput *Output) |
||
930 | { |
||
931 | RHDFUNC(Output); |
||
932 | |||
933 | DACSaveRV620(Output, RV620_REG_DACB_OFFSET); |
||
934 | } |
||
935 | |||
936 | /* |
||
937 | * |
||
938 | */ |
||
939 | static inline void |
||
940 | DACRestoreRV620(struct rhdOutput *Output, CARD16 offset) |
||
941 | { |
||
942 | struct rhdDACPrivate *Private = (struct rhdDACPrivate *) Output->Private; |
||
943 | |||
944 | RHDRegWrite(Output, offset + RV620_DACA_BGADJ_SRC, Private->Store_Dac_Bgadj_Src); |
||
945 | RHDRegWrite(Output, offset + RV620_DACA_AUTO_CALIB_CONTROL, Private->Store_Auto_Calib_Control); |
||
946 | RHDRegWrite(Output, offset + RV620_DACA_POWERDOWN, Private->Store_Powerdown); |
||
947 | RHDRegWrite(Output, offset + RV620_DACA_FORCE_OUTPUT_CNTL, Private->Store_Force_Output_Control); |
||
948 | RHDRegWrite(Output, offset + RV620_DACA_FORCE_DATA, Private->Store_Force_Data); |
||
949 | RHDRegWrite(Output, offset + RV620_DACA_SOURCE_SELECT, Private->Store_Source_Select); |
||
950 | RHDRegWrite(Output, offset + RV620_DACA_ENABLE, Private->Store_Enable); |
||
951 | RHDRegWrite(Output, offset + RV620_DACA_MACRO_CNTL, Private->Store_Control1); |
||
952 | RHDRegWrite(Output, offset + RV620_DACA_CONTROL2, Private->Store_Control2); |
||
953 | RHDRegWrite(Output, offset + RV620_DACA_SYNC_TRISTATE_CONTROL, Private->Store_Tristate_Control); |
||
954 | |||
955 | } |
||
956 | |||
957 | /* |
||
958 | * |
||
959 | */ |
||
960 | static void |
||
961 | DACARestoreRV620(struct rhdOutput *Output) |
||
962 | { |
||
963 | RHDFUNC(Output); |
||
964 | |||
965 | if (!((struct rhdDACPrivate *) Output->Private)->Stored) { |
||
966 | xf86DrvMsg(Output->scrnIndex, X_ERROR, |
||
967 | "%s: No registers stored.\n", __func__); |
||
968 | return; |
||
969 | } |
||
970 | DACRestoreRV620(Output, RV620_REG_DACA_OFFSET); |
||
971 | } |
||
972 | |||
973 | /* |
||
974 | * |
||
975 | */ |
||
976 | static void |
||
977 | DACBRestoreRV620(struct rhdOutput *Output) |
||
978 | { |
||
979 | RHDFUNC(Output); |
||
980 | |||
981 | if (!((struct rhdDACPrivate *) Output->Private)->Stored) { |
||
982 | xf86DrvMsg(Output->scrnIndex, X_ERROR, |
||
983 | "%s: No registers stored.\n", __func__); |
||
984 | return; |
||
985 | } |
||
986 | |||
987 | DACRestoreRV620(Output, RV620_REG_DACB_OFFSET); |
||
988 | } |
||
989 | |||
990 | /* ----------------------------------------------------------- */ |
||
991 | |||
992 | /* |
||
993 | * |
||
994 | */ |
||
995 | static ModeStatus |
||
996 | DACModeValid(struct rhdOutput *Output, DisplayModePtr Mode) |
||
997 | { |
||
998 | RHDFUNC(Output); |
||
999 | |||
1000 | if (Mode->Clock < 20000) |
||
1001 | return MODE_CLOCK_LOW; |
||
1002 | |||
1003 | if (Mode->Clock > 400000) |
||
1004 | return MODE_CLOCK_HIGH; |
||
1005 | |||
1006 | return MODE_OK; |
||
1007 | } |
||
1008 | |||
1009 | /* |
||
1010 | * |
||
1011 | */ |
||
1012 | static void |
||
1013 | DACDestroy(struct rhdOutput *Output) |
||
1014 | { |
||
1015 | RHDFUNC(Output); |
||
1016 | |||
1017 | if (!Output->Private) |
||
1018 | return; |
||
1019 | |||
1020 | xfree(Output->Private); |
||
1021 | Output->Private = NULL; |
||
1022 | } |
||
1023 | |||
1024 | /* |
||
1025 | * |
||
1026 | */ |
||
1027 | struct rhdOutput * |
||
1028 | RHDDACAInit(RHDPtr rhdPtr) |
||
1029 | { |
||
1030 | struct rhdOutput *Output; |
||
1031 | struct rhdDACPrivate *Private; |
||
1032 | |||
1033 | RHDFUNC(rhdPtr); |
||
1034 | |||
1035 | Output = xnfcalloc(sizeof(struct rhdOutput), 1); |
||
1036 | |||
1037 | Output->scrnIndex = rhdPtr->scrnIndex; |
||
1038 | Output->Name = "DAC A"; |
||
1039 | Output->Id = RHD_OUTPUT_DACA; |
||
1040 | |||
1041 | if (rhdPtr->ChipSet < RHD_RV620) { |
||
1042 | Output->Sense = DACASense; |
||
1043 | Output->Mode = DACASet; |
||
1044 | Output->Power = DACAPower; |
||
1045 | Output->Save = DACASave; |
||
1046 | Output->Restore = DACARestore; |
||
1047 | } else { |
||
1048 | Output->Sense = DACASenseRV620; |
||
1049 | Output->Mode = DACASetRV620; |
||
1050 | Output->Power = DACAPowerRV620; |
||
1051 | Output->Save = DACASaveRV620; |
||
1052 | Output->Restore = DACARestoreRV620; |
||
1053 | } |
||
1054 | Output->ModeValid = DACModeValid; |
||
1055 | Output->Destroy = DACDestroy; |
||
1056 | Private = xnfcalloc(sizeof(struct rhdDACPrivate), 1); |
||
1057 | Output->Private = Private; |
||
1058 | |||
1059 | return Output; |
||
1060 | } |
||
1061 | |||
1062 | /* |
||
1063 | * |
||
1064 | */ |
||
1065 | struct rhdOutput * |
||
1066 | RHDDACBInit(RHDPtr rhdPtr) |
||
1067 | { |
||
1068 | struct rhdOutput *Output; |
||
1069 | struct rhdDACPrivate *Private; |
||
1070 | |||
1071 | RHDFUNC(rhdPtr); |
||
1072 | |||
1073 | Output = xnfcalloc(sizeof(struct rhdOutput), 1); |
||
1074 | |||
1075 | Output->scrnIndex = rhdPtr->scrnIndex; |
||
1076 | Output->Name = "DAC B"; |
||
1077 | Output->Id = RHD_OUTPUT_DACB; |
||
1078 | |||
1079 | if (rhdPtr->ChipSet < RHD_RV620) { |
||
1080 | Output->Sense = DACBSense; |
||
1081 | Output->Mode = DACBSet; |
||
1082 | Output->Power = DACBPower; |
||
1083 | Output->Save = DACBSave; |
||
1084 | Output->Restore = DACBRestore; |
||
1085 | } else { |
||
1086 | Output->Sense = DACBSenseRV620; |
||
1087 | Output->Mode = DACBSetRV620; |
||
1088 | Output->Power = DACBPowerRV620; |
||
1089 | Output->Save = DACBSaveRV620; |
||
1090 | Output->Restore = DACBRestoreRV620; |
||
1091 | } |
||
1092 | Output->ModeValid = DACModeValid; |
||
1093 | Output->Destroy = DACDestroy; |
||
1094 | |||
1095 | Private = xnfcalloc(sizeof(struct rhdDACPrivate), 1); |
||
1096 | Output->Private = Private; |
||
1097 | |||
1098 | return Output; |
||
1099 | }>>>><>><>><>><>><>><>><>><>><>=>> |