1 /*
2 * Copyright 2016 Kevin Brace
3 * Copyright 2005-2016 The OpenChrome Project
4 * [https://www.freedesktop.org/wiki/Openchrome]
5 * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net]
6 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
7 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sub license,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29 /*
30 * via_outputs.c
31 *
32 * Everything to do with setting and changing xf86Outputs.
33 *
34 */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "via_driver.h"
41 #include <unistd.h>
42
43 /*
44 * Modetable nonsense.
45 *
46 */
47 #include "via_mode.h"
48
49 /*
50 * Sets IGA1 or IGA2 as the display output source for DIP0
51 * (Digital Interface Port 0) interface for CLE266 only.
52 */
53 void
viaDIP0SetDisplaySource(ScrnInfoPtr pScrn,CARD8 displaySource)54 viaDIP0SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
55 {
56 vgaHWPtr hwp = VGAHWPTR(pScrn);
57 CARD8 temp = displaySource;
58
59 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
60 "Entered viaDIP0SetDisplaySource.\n"));
61
62 /* Set DIP0 display output source. */
63 /* 3X5.6C[7] - DIP0 (Digital Interface Port 0) Data Source Selection
64 * 0: Primary Display (IGA1)
65 * 1: Secondary Display (IGA2) */
66 ViaCrtcMask(hwp, 0x6C, temp << 7, 0x80);
67 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
68 "DIP0 Display Output Source: IGA%d\n",
69 (temp & 0x01) + 1);
70
71 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
72 "Exiting viaDIP0SetDisplaySource.\n"));
73 }
74
75 /*
76 * Sets DIP0 (Digital Interface Port 0) I/O pad state.
77 * This function is for CLE266 chipset only.
78 */
79 void
viaDIP0EnableIOPads(ScrnInfoPtr pScrn,CARD8 ioPadState)80 viaDIP0EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
81 {
82 vgaHWPtr hwp = VGAHWPTR(pScrn);
83
84 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
85 "Entered viaDIP0EnableIOPads.\n"));
86
87 /* Set DIP0 I/O pad state. */
88 /* 3C5.1E[7:6] - DIP0 Power Control
89 * 0x: Pad always off
90 * 10: Depend on the other control signal
91 * 11: Pad on/off according to the
92 * Power Management Status (PMS) */
93 ViaSeqMask(hwp, 0x1E, ioPadState << 6, 0xC0);
94 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
95 "DIP0 I/O Pad State: %s\n",
96 (ioPadState & 0x02) ?
97 (ioPadState & 0x01) ? "Automatic On / Off" : "Conditional"
98 : "Off");
99
100 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
101 "Exiting viaDIP0EnableIOPads.\n"));
102 }
103
104 /*
105 * Sets DIP0 (Digital Interface Port 0) clock I/O pad drive strength
106 * for CLE266 chipset only.
107 */
108 void
viaDIP0SetClockDriveStrength(ScrnInfoPtr pScrn,CARD8 clockDriveStrength)109 viaDIP0SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength)
110 {
111 vgaHWPtr hwp = VGAHWPTR(pScrn);
112
113 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
114 "Entered viaDIP0SetClockDriveStrength.\n"));
115
116 /* 3C5.1E[2] - DIP0 Clock Drive Strength Bit [0] */
117 ViaSeqMask(hwp, 0x1E, clockDriveStrength << 2, 0x04);
118
119 /* 3C5.2A[4] - DIP0 Clock Drive Strength Bit [1] */
120 ViaSeqMask(hwp, 0x2A, clockDriveStrength << 3, 0x10);
121
122 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
123 "DIP0 Clock I/O Pad Drive Strength: %u\n",
124 clockDriveStrength & 0x03);
125
126 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
127 "Exiting viaDIP0SetClockDriveStrength.\n"));
128 }
129
130 /*
131 * Sets DIP0 (Digital Interface Port 0) data I/O pads drive strength
132 * for CLE266 chipset only.
133 */
134 void
viaDIP0SetDataDriveStrength(ScrnInfoPtr pScrn,CARD8 dataDriveStrength)135 viaDIP0SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength)
136 {
137 vgaHWPtr hwp = VGAHWPTR(pScrn);
138
139 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
140 "Entered viaDIP0SetDataDriveStrength.\n"));
141
142 /* 3C5.1B[1] - DIP0 Data Drive Strength Bit [0] */
143 ViaSeqMask(hwp, 0x1B, dataDriveStrength << 1, 0x02);
144
145 /* 3C5.2A[5] - DIP0 Data Drive Strength Bit [1] */
146 ViaSeqMask(hwp, 0x2A, dataDriveStrength << 4, 0x20);
147
148 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
149 "DIP0 Data I/O Pads Drive Strength: %u\n",
150 dataDriveStrength);
151
152 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
153 "Exiting viaDIP0SetDataDriveStrength.\n"));
154 }
155
156 /*
157 * Sets IGA1 or IGA2 as the display output source for DVP0
158 * (Digital Video Port) interface.
159 */
160 void
viaDVP0SetDisplaySource(ScrnInfoPtr pScrn,CARD8 displaySource)161 viaDVP0SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
162 {
163 vgaHWPtr hwp = VGAHWPTR(pScrn);
164 CARD8 temp = displaySource;
165
166 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
167 "Entered viaDVP0SetDisplaySource.\n"));
168
169 /* Set DVP0 display output source. */
170 /* 3X5.96[4] - DVP0 Data Source Selection
171 * 0: Primary Display
172 * 1: Secondary Display */
173 ViaCrtcMask(hwp, 0x96, temp << 4, 0x10);
174 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
175 "DVP0 Display Output Source: IGA%d\n",
176 (temp & 0x01) + 1);
177
178 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
179 "Exiting viaDVP0SetDisplaySource.\n"));
180 }
181
182 /*
183 * Sets DVP0 (Digital Video Port 0) I/O pad state.
184 */
185 void
viaDVP0EnableIOPads(ScrnInfoPtr pScrn,CARD8 ioPadState)186 viaDVP0EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
187 {
188 vgaHWPtr hwp = VGAHWPTR(pScrn);
189
190 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
191 "Entered viaDVP0EnableIOPads.\n"));
192
193 /* Set DVP0 I/O pad state. */
194 /* 3C5.1E[7:6] - DVP0 Power Control
195 * 0x: Pad always off
196 * 10: Depend on the other control signal
197 * 11: Pad on/off according to the
198 * Power Management Status (PMS) */
199 ViaSeqMask(hwp, 0x1E, ioPadState << 6, 0xC0);
200 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
201 "DVP0 I/O Pad State: %s\n",
202 (ioPadState & 0x02) ?
203 (ioPadState & 0x01) ? "Automatic On / Off" : "Conditional"
204 : "Off");
205
206 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
207 "Exiting viaDVP0EnableIOPads.\n"));
208 }
209
210 /*
211 * Sets DVP0 (Digital Video Port 0) clock I/O pad drive strength.
212 */
213 void
viaDVP0SetClockDriveStrength(ScrnInfoPtr pScrn,CARD8 clockDriveStrength)214 viaDVP0SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength)
215 {
216 vgaHWPtr hwp = VGAHWPTR(pScrn);
217
218 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
219 "Entered viaDVP0SetClockDriveStrength.\n"));
220
221 /* 3C5.1E[2] - DVP0 Clock Drive Strength Bit [0] */
222 ViaSeqMask(hwp, 0x1E, clockDriveStrength << 2, 0x04);
223
224 /* 3C5.2A[4] - DVP0 Clock Drive Strength Bit [1] */
225 ViaSeqMask(hwp, 0x2A, clockDriveStrength << 3, 0x10);
226
227 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
228 "DVP0 Clock I/O Pad Drive Strength: %u\n",
229 clockDriveStrength & 0x03);
230
231 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
232 "Exiting viaDVP0SetClockDriveStrength.\n"));
233 }
234
235 /*
236 * Sets DVP0 (Digital Video Port 0) data I/O pads drive strength.
237 */
238 void
viaDVP0SetDataDriveStrength(ScrnInfoPtr pScrn,CARD8 dataDriveStrength)239 viaDVP0SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength)
240 {
241 vgaHWPtr hwp = VGAHWPTR(pScrn);
242
243 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
244 "Entered viaDVP0SetDataDriveStrength.\n"));
245
246 /* 3C5.1B[1] - DVP0 Data Drive Strength Bit [0] */
247 ViaSeqMask(hwp, 0x1B, dataDriveStrength << 1, 0x02);
248
249 /* 3C5.2A[5] - DVP0 Data Drive Strength Bit [1] */
250 ViaSeqMask(hwp, 0x2A, dataDriveStrength << 4, 0x20);
251
252 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
253 "DVP0 Data I/O Pads Drive Strength: %u\n",
254 dataDriveStrength);
255
256 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
257 "Exiting viaDVP0SetDataDriveStrength.\n"));
258 }
259
260 /*
261 * Sets IGA1 or IGA2 as the display output source for DVP1
262 * (Digital Video Port) interface.
263 */
264 void
viaDVP1SetDisplaySource(ScrnInfoPtr pScrn,CARD8 displaySource)265 viaDVP1SetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
266 {
267 vgaHWPtr hwp = VGAHWPTR(pScrn);
268 CARD8 temp = displaySource;
269
270 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
271 "Entered viaDVP1SetDisplaySource.\n"));
272
273 /* Set DVP1 display output source. */
274 /* 3X5.9B[4] - DVP1 Data Source Selection
275 * 0: Primary Display
276 * 1: Secondary Display */
277 ViaCrtcMask(hwp, 0x9B, temp << 4, 0x10);
278 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
279 "DVP1 Display Output Source: IGA%d\n",
280 (temp & 0x01) + 1);
281
282 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
283 "Exiting viaDVP1SetDisplaySource.\n"));
284 }
285
286 /*
287 * Sets DVP1 (Digital Video Port 1) I/O pad state.
288 */
289 void
viaDVP1EnableIOPads(ScrnInfoPtr pScrn,CARD8 ioPadState)290 viaDVP1EnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
291 {
292 vgaHWPtr hwp = VGAHWPTR(pScrn);
293
294 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
295 "Entered viaDVP1EnableIOPads.\n"));
296
297 /* Set DVP1 I/O pad state. */
298 /* 3C5.1E[5:4] - DVP1 Power Control
299 * 0x: Pad always off
300 * 10: Depend on the other control signal
301 * 11: Pad on/off according to the
302 * Power Management Status (PMS) */
303 ViaSeqMask(hwp, 0x1E, ioPadState << 4, 0x30);
304 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
305 "DVP1 I/O Pad State: %s\n",
306 (ioPadState & 0x02) ?
307 (ioPadState & 0x01) ? "Automatic On / Off": "Conditional"
308 : "Off");
309
310 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
311 "Exiting viaDVP1EnableIOPads.\n"));
312 }
313
314 /*
315 * Sets DVP1 (Digital Video Port 1) clock I/O pad drive strength.
316 */
317 void
viaDVP1SetClockDriveStrength(ScrnInfoPtr pScrn,CARD8 clockDriveStrength)318 viaDVP1SetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength)
319 {
320 vgaHWPtr hwp = VGAHWPTR(pScrn);
321
322 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
323 "Entered viaDVP1SetClockDriveStrength.\n"));
324
325 /* 3C5.65[3:2] - DVP1 Clock Pads Driving Select
326 * 00: lowest
327 * 01: low
328 * 10: high
329 * 11: highest */
330 ViaSeqMask(hwp, 0x65, clockDriveStrength << 2, 0x0C);
331
332 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
333 "DVP1 Clock I/O Pad Drive Strength: %u\n",
334 clockDriveStrength & 0x03);
335
336 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
337 "Exiting viaDVP1SetClockDriveStrength.\n"));
338 }
339
340 /*
341 * Sets DVP1 (Digital Video Port 1) data I/O pads drive strength.
342 */
343 void
viaDVP1SetDataDriveStrength(ScrnInfoPtr pScrn,CARD8 dataDriveStrength)344 viaDVP1SetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength)
345 {
346 vgaHWPtr hwp = VGAHWPTR(pScrn);
347
348 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
349 "Entered viaDVP1SetDataDriveStrength.\n"));
350
351 /* 3C5.65[1:0] - DVP1 Data Pads Driving Select
352 * 00: lowest
353 * 01: low
354 * 10: high
355 * 11: highest */
356 ViaSeqMask(hwp, 0x65, dataDriveStrength, 0x03);
357
358 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
359 "DVP1 Data I/O Pads Drive Strength: %u\n",
360 dataDriveStrength & 0x03);
361
362 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
363 "Exiting viaDVP1SetDataDriveStrength.\n"));
364 }
365
366 /*
367 * Sets IGA1 or IGA2 as the display output source for VIA Technologies
368 * Chrome IGP DFP (Digital Flat Panel) Low interface.
369 */
370 void
viaDFPLowSetDisplaySource(ScrnInfoPtr pScrn,CARD8 displaySource)371 viaDFPLowSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
372 {
373 vgaHWPtr hwp = VGAHWPTR(pScrn);
374 CARD8 temp = displaySource;
375
376 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
377 "Entered viaDFPLowSetDisplaySource.\n"));
378
379 /* Set DFP Low display output source. */
380 /* 3X5.99[4] - DFP Low Data Source Selection
381 * 0: Primary Display
382 * 1: Secondary Display */
383 ViaCrtcMask(hwp, 0x99, temp << 4, 0x10);
384 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
385 "DFP Low Display Output Source: IGA%d\n",
386 (temp & 0x01) + 1);
387
388 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
389 "Exiting viaDFPLowSetDisplaySource.\n"));
390 }
391
392 /*
393 * Sets DFP (Digital Flat Panel) Low I/O pad state.
394 */
395 void
viaDFPLowEnableIOPads(ScrnInfoPtr pScrn,CARD8 ioPadState)396 viaDFPLowEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
397 {
398 vgaHWPtr hwp = VGAHWPTR(pScrn);
399
400 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
401 "Entered viaDFPLowEnableIOPads.\n"));
402
403 /* Set DFP Low I/O pad state. */
404 /* 3C5.2A[1:0] - DFP Low Power Control
405 * 0x: Pad always off
406 * 10: Depend on the other control signal
407 * 11: Pad on/off according to the
408 * Power Management Status (PMS) */
409 ViaSeqMask(hwp, 0x2A, ioPadState, 0x03);
410 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
411 "DFP Low I/O Pad State: %s\n",
412 (ioPadState & 0x02) ?
413 (ioPadState & 0x01) ? "Automatic On / Off": "Conditional"
414 : "Off");
415
416 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
417 "Exiting viaDFPLowEnableIOPads.\n"));
418 }
419
420 /*
421 * Reads off the VIA Technologies IGP pin strapping for
422 * display detection purposes.
423 */
424 void
viaProbePinStrapping(ScrnInfoPtr pScrn)425 viaProbePinStrapping(ScrnInfoPtr pScrn)
426 {
427 vgaHWPtr hwp = VGAHWPTR(pScrn);
428 VIAPtr pVia = VIAPTR(pScrn);
429 CARD8 sr12, sr13, sr5a;
430
431 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
432 "Entered viaProbePinStrapping.\n"));
433
434 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
435 "Probing VIA Technologies IGP pin strapping . . .\n");
436
437 if ((pVia->Chipset == VIA_CX700)
438 || (pVia->Chipset == VIA_VX800)
439 || (pVia->Chipset == VIA_VX855)
440 || (pVia->Chipset == VIA_VX900)) {
441
442 sr5a = hwp->readSeq(hwp, 0x5A);
443 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
444 "SR5A: 0x%02X\n", sr5a));
445 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
446 "Setting 3C5.5A[0] to 0.\n");
447 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
448 }
449
450 sr12 = hwp->readSeq(hwp, 0x12);
451 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
452 "SR12: 0x%02X\n", sr12));
453 sr13 = hwp->readSeq(hwp, 0x13);
454 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
455 "SR13: 0x%02X\n", sr13));
456
457 switch (pVia->Chipset) {
458 case VIA_CLE266:
459
460 /* 3C5.12[4] - FPD17 pin strapping
461 * 0: TMDS transmitter (DVI) / capture device
462 * 1: Flat panel */
463 if (sr12 & 0x10) {
464 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
465 "A flat panel is connected to "
466 "flat panel interface.\n");
467
468 /* 3C5.12[3:0] - FPD16-13 pin strapping
469 * 0 ~ 15: Flat panel code defined
470 * by VIA Technologies */
471 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
472 "Detected Flat Panel Type from "
473 "Strapping Pins: %d\n", sr12 & 0x0F);
474 } else {
475 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
476 "A TMDS transmitter (DVI) / capture device is "
477 "connected to DIP0.\n");
478 }
479
480 /* 3C5.12[5] - FPD18 pin strapping
481 * 0: TMDS transmitter (DVI)
482 * 1: TV encoder */
483 if (sr12 & 0x20) {
484 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
485 "A TV encoder is connected to "
486 "DIP0.\n");
487
488 /* 3C5.13[4:3] - FPD21-20 pin strapping
489 * 00: PAL
490 * 01: NTSC
491 * 10: PAL-N
492 * 11: PAL-NC */
493 if ((!(sr13 & 0x08)) && (sr13 & 0x04)) {
494 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
495 "NTSC for the TV encoder.\n");
496 } else {
497 if (!(sr13 & 0x08)) {
498 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
499 "PAL for the TV encoder.\n");
500 } else {
501 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
502 "PAL%s for the TV encoder.\n",
503 (sr13 & 0x04) ? "-NC" : "-N");
504 }
505 }
506
507 /* 3C5.12[6] - FPD19 pin strapping
508 * 0: 525 lines (NTSC)
509 * 1: 625 lines (PAL) */
510 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
511 "%s lines for the TV encoder.\n",
512 (sr12 & 0x40) ? "625" : "525");
513 } else {
514 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
515 "A TMDS transmitter (DVI) is connected to "
516 "DIP0.\n");
517 }
518
519 break;
520
521 case VIA_KM400:
522 case VIA_K8M800:
523 case VIA_PM800:
524 case VIA_P4M800PRO:
525
526 /* 3C5.12[6] - DVP0D6 pin strapping
527 * 0: Disable DVP0 (Digital Video Port 0) for
528 * DVI or TV out use
529 * 1: Enable DVP0 (Digital Video Port 0) for
530 * DVI or TV out use */
531 if (sr12 & 0x40) {
532
533 /* 3C5.12[5] - DVP0D5 pin strapping
534 * 0: TMDS transmitter (DVI)
535 * 1: TV encoder */
536 if (sr12 & 0x20) {
537 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
538 "A TV encoder is detected on "
539 "DVP0 (Digital Video Port 0).\n");
540 } else {
541 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
542 "A TMDS transmitter (DVI) is detected on "
543 "DVP0 (Digital Video Port 0).\n");
544 }
545 }
546
547
548 /* 3C5.13[3] - DVP0D8 pin strapping
549 * 0: AGP pins are used for AGP
550 * 1: AGP pins are used by FPDP
551 * (Flat Panel Display Port) */
552 if (sr13 & 0x08) {
553
554 /* 3C5.12[4] - DVP0D4 pin strapping
555 * 0: Dual 12-bit FPDP (Flat Panel Display Port)
556 * 1: 24-bit FPDP (Flat Panel Display Port) */
557 if (sr12 & 0x10) {
558 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
559 "24-bit FPDP (Flat Panel Display Port) "
560 "detected.\n");
561
562 /* 3C5.12[3:0] - DVP0D3-0 pin strapping
563 * 0 ~ 15: Flat panel code defined
564 * by VIA Technologies */
565 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
566 "Detected Flat Panel Type from "
567 "Strapping Pins: %d\n", sr12 & 0x0F);
568 } else {
569
570 /* 3C5.12[6] - DVP0D6 pin strapping
571 * 0: Disable DVP0 (Digital Video Port 0) for
572 * DVI or TV out use
573 * 1: Enable DVP0 (Digital Video Port 0) for
574 * DVI or TV out use
575 * 3C5.12[5] - DVP0D5 pin strapping
576 * 0: TMDS transmitter (DVI)
577 * 1: TV encoder */
578 if ((!(sr12 & 0x40)) && (!(sr12 & 0x20))) {
579 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
580 "A TV encoder is connected to "
581 "FPDP (Flat Panel Display Port).\n");
582 } else {
583 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
584 "Dual 12-bit FPDP (Flat Panel Display Port) "
585 "detected.\n");
586
587 /* 3C5.12[3:0] - DVP0D3-0 pin strapping
588 * 0 ~ 15: Flat panel code defined
589 * by VIA Technologies */
590 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
591 "Detected Flat Panel Type from "
592 "Strapping Pins: %d\n", sr12 & 0x0F);
593 }
594 }
595 }
596
597 break;
598
599 default:
600 break;
601 }
602
603 if ((pVia->Chipset == VIA_CX700)
604 || (pVia->Chipset == VIA_VX800)
605 || (pVia->Chipset == VIA_VX855)
606 || (pVia->Chipset == VIA_VX900)) {
607
608 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
609 "Setting 3C5.5A[0] to 1.\n");
610 ViaSeqMask(hwp, 0x5A, sr5a | 0x01, 0x01);
611
612 sr12 = hwp->readSeq(hwp, 0x12);
613 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
614 "SR12: 0x%02X\n", sr12));
615 sr13 = hwp->readSeq(hwp, 0x13);
616 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
617 "SR13: 0x%02X\n", sr13));
618
619 /* 3C5.13[7:6] - Integrated LVDS / DVI Mode Select
620 * (DVP1D15-14 pin strapping)
621 * 00: LVDS1 + LVDS2
622 * 01: DVI + LVDS2
623 * 10: Dual LVDS Channel (High Resolution Panel)
624 * 11: One DVI only (decrease the clock jitter) */
625 switch (sr13 & 0xC0) {
626 case 0x00:
627 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
628 "LVDS1 + LVDS2 detected.\n");
629 break;
630 case 0x40:
631 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
632 "Single Link DVI + LVDS2 detected.\n");
633 break;
634 case 0x80:
635 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
636 "Dual Channel LVDS detected.\n");
637 break;
638 case 0xC0:
639 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
640 "Single Link DVI detected.\n");
641 break;
642 default:
643 break;
644 }
645
646 hwp->writeSeq(hwp, 0x5A, sr5a);
647
648 }
649
650 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
651 "Exiting viaProbePinStrapping.\n"));
652 }
653
654 void
viaOutputDetect(ScrnInfoPtr pScrn)655 viaOutputDetect(ScrnInfoPtr pScrn)
656 {
657 VIAPtr pVia = VIAPTR(pScrn);
658 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
659
660 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
661 "Entered viaOutputDetect.\n"));
662
663 pBIOSInfo->analog = NULL;
664
665 /* Initialize the number of VGA connectors. */
666 pVia->numberVGA = 0;
667
668 /* Initialize the number of DVI connectors. */
669 pVia->numberDVI = 0;
670
671 /* Initialize the number of FP connectors. */
672 pVia->numberFP = 0;
673
674 /* Read off the VIA Technologies IGP pin strapping for
675 display detection purposes. */
676 viaProbePinStrapping(pScrn);
677
678 /* VGA */
679 via_analog_init(pScrn);
680
681 /* TV */
682 via_tv_init(pScrn);
683
684 /* DVI */
685 via_dvi_init(pScrn);
686
687 /* LVDS */
688 via_lvds_init(pScrn);
689
690 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
691 "Exiting viaOutputDetect.\n"));
692 }
693
694 #ifdef HAVE_DEBUG
695 /*
696 * Returns:
697 * Bit[7] 2nd Path
698 * Bit[6] 1/0 MHS Enable/Disable
699 * Bit[5] 0 = Bypass Callback, 1 = Enable Callback
700 * Bit[4] 0 = Hot-Key Sequence Control (OEM Specific)
701 * Bit[3] LCD
702 * Bit[2] TV
703 * Bit[1] CRT
704 * Bit[0] DVI
705 */
706 static CARD8
VIAGetActiveDisplay(ScrnInfoPtr pScrn)707 VIAGetActiveDisplay(ScrnInfoPtr pScrn)
708 {
709 vgaHWPtr hwp = VGAHWPTR(pScrn);
710 CARD8 tmp;
711
712 tmp = (hwp->readCrtc(hwp, 0x3E) >> 4);
713 tmp |= ((hwp->readCrtc(hwp, 0x3B) & 0x18) << 3);
714
715 return tmp;
716 }
717 #endif /* HAVE_DEBUG */
718
719 /*
720 *
721 */
722 CARD32
ViaGetMemoryBandwidth(ScrnInfoPtr pScrn)723 ViaGetMemoryBandwidth(ScrnInfoPtr pScrn)
724 {
725 VIAPtr pVia = VIAPTR(pScrn);
726
727 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
728 "ViaGetMemoryBandwidth. Memory type: %d\n",
729 pVia->MemClk));
730
731 switch (pVia->MemClk) {
732 case VIA_MEM_SDR66:
733 case VIA_MEM_SDR100:
734 case VIA_MEM_SDR133:
735 return VIA_BW_MIN;
736 case VIA_MEM_DDR200:
737 return VIA_BW_DDR200;
738 case VIA_MEM_DDR266:
739 case VIA_MEM_DDR333:
740 case VIA_MEM_DDR400:
741 return VIA_BW_DDR400;
742 case VIA_MEM_DDR533:
743 case VIA_MEM_DDR667:
744 return VIA_BW_DDR667;
745 case VIA_MEM_DDR800:
746 case VIA_MEM_DDR1066:
747 return VIA_BW_DDR1066;
748 default:
749 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
750 "ViaBandwidthAllowed: Unknown memory type: %d\n",
751 pVia->MemClk);
752 return VIA_BW_MIN;
753 }
754 }
755
756 /*
757 *
758 * Some very common abstractions.
759 *
760 */
761
762 /*
763 * Standard vga call really.
764 * Needs to be called to reset the dotclock (after SR40:2/1 reset)
765 */
766 void
ViaSetUseExternalClock(vgaHWPtr hwp)767 ViaSetUseExternalClock(vgaHWPtr hwp)
768 {
769 CARD8 data;
770
771 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO,
772 "ViaSetUseExternalClock\n"));
773
774 data = hwp->readMiscOut(hwp);
775 hwp->writeMiscOut(hwp, data | 0x0C);
776 }
777
778 /*
779 *
780 */
781 static void
ViaSetDotclock(ScrnInfoPtr pScrn,CARD32 clock,int base,int probase)782 ViaSetDotclock(ScrnInfoPtr pScrn, CARD32 clock, int base, int probase)
783 {
784 vgaHWPtr hwp = VGAHWPTR(pScrn);
785 VIAPtr pVia = VIAPTR(pScrn);
786
787 DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO,
788 "ViaSetDotclock to 0x%06x\n", (unsigned)clock));
789
790 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) {
791 hwp->writeSeq(hwp, base, clock >> 8);
792 hwp->writeSeq(hwp, base+1, clock & 0xFF);
793 } else { /* unichrome pro */
794 union pllparams pll;
795 int dtz, dr, dn, dm;
796 pll.packed = clock;
797 dtz = pll.params.dtz;
798 dr = pll.params.dr;
799 dn = pll.params.dn;
800 dm = pll.params.dm;
801
802 /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */
803 if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) {
804 dm -= 2;
805 dn -= 2;
806 }
807
808 hwp->writeSeq(hwp, probase, dm & 0xff);
809 hwp->writeSeq(hwp, probase+1,
810 ((dm >> 8) & 0x03) | (dr << 2) | ((dtz & 1) << 7));
811 hwp->writeSeq(hwp, probase+2, (dn & 0x7f) | ((dtz & 2) << 6));
812 }
813 }
814
815 /*
816 *
817 */
818 void
ViaSetPrimaryDotclock(ScrnInfoPtr pScrn,CARD32 clock)819 ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock)
820 {
821 vgaHWPtr hwp = VGAHWPTR(pScrn);
822
823 ViaSetDotclock(pScrn, clock, 0x46, 0x44);
824
825 ViaSeqMask(hwp, 0x40, 0x02, 0x02);
826 ViaSeqMask(hwp, 0x40, 0x00, 0x02);
827 }
828
829 /*
830 *
831 */
832 void
ViaSetSecondaryDotclock(ScrnInfoPtr pScrn,CARD32 clock)833 ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock)
834 {
835 vgaHWPtr hwp = VGAHWPTR(pScrn);
836
837 ViaSetDotclock(pScrn, clock, 0x44, 0x4A);
838
839 ViaSeqMask(hwp, 0x40, 0x04, 0x04);
840 ViaSeqMask(hwp, 0x40, 0x00, 0x04);
841 }
842
843 /*
844 *
845 */
846 static void
ViaSetECKDotclock(ScrnInfoPtr pScrn,CARD32 clock)847 ViaSetECKDotclock(ScrnInfoPtr pScrn, CARD32 clock)
848 {
849 /* Does the non-pro chip have an ECK clock ? */
850 ViaSetDotclock(pScrn, clock, 0, 0x47);
851 }
852
853 static CARD32
ViaComputeDotClock(unsigned clock)854 ViaComputeDotClock(unsigned clock)
855 {
856 double fout, fref, err, minErr;
857 CARD32 dr, dn, dm, maxdm, maxdn;
858 CARD32 factual, best;
859
860 fref = 14.31818e6;
861 fout = (double)clock * 1.e3;
862
863 factual = ~0;
864 maxdm = 127;
865 maxdn = 7;
866 minErr = 1e10;
867 best = 0;
868
869 for (dr = 0; dr < 4; ++dr) {
870 for (dn = (dr == 0) ? 2 : 1; dn <= maxdn; ++dn) {
871 for (dm = 1; dm <= maxdm; ++dm) {
872 factual = fref * dm;
873 factual /= (dn << dr);
874 err = fabs((double)factual / fout - 1.);
875 if (err < minErr) {
876 minErr = err;
877 best = (dm & 127) | ((dn & 31) << 8) | (dr << 14);
878 }
879 }
880 }
881 }
882 return best;
883 }
884
885 static CARD32
ViaComputeProDotClock(unsigned clock)886 ViaComputeProDotClock(unsigned clock)
887 {
888 double fvco, fout, err, minErr;
889 CARD32 dr = 0, dn, dm, maxdm, maxdn;
890 CARD32 factual;
891 union pllparams bestClock;
892
893 fout = (double)clock * 1.e3;
894
895 factual = ~0;
896 maxdm = factual / 14318000U;
897 minErr = 1.e10;
898 bestClock.packed = 0U;
899
900 do {
901 fvco = fout * (1 << dr);
902 } while (fvco < 300.e6 && dr++ < 8);
903
904 if (dr == 8) {
905 return 0;
906 }
907
908 if (clock < 30000)
909 maxdn = 8;
910 else if (clock < 45000)
911 maxdn = 7;
912 else if (clock < 170000)
913 maxdn = 6;
914 else
915 maxdn = 5;
916
917 for (dn = 2; dn < maxdn; ++dn) {
918 for (dm = 2; dm < maxdm; ++dm) {
919 factual = 14318000U * dm;
920 factual /= dn << dr;
921 if ((err = fabs((double)factual / fout - 1.)) < 0.005) {
922 if (err < minErr) {
923 minErr = err;
924 bestClock.params.dtz = 1;
925 bestClock.params.dr = dr;
926 bestClock.params.dn = dn;
927 bestClock.params.dm = dm;
928 }
929 }
930 }
931 }
932
933 return bestClock.packed;
934 }
935
936 /*
937 *
938 */
939 CARD32
ViaModeDotClockTranslate(ScrnInfoPtr pScrn,DisplayModePtr mode)940 ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode)
941 {
942 VIAPtr pVia = VIAPTR(pScrn);
943 int i;
944
945 if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) {
946 CARD32 best1 = 0, best2;
947
948 for (i = 0; ViaDotClocks[i].DotClock; i++)
949 if (ViaDotClocks[i].DotClock == mode->Clock) {
950 best1 = ViaDotClocks[i].UniChrome;
951 break;
952 }
953
954 best2 = ViaComputeDotClock(mode->Clock);
955
956 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
957 "ViaComputeDotClock %d : %04x : %04x\n",
958 mode->Clock, (unsigned int)best1,
959 (unsigned int)best2));
960
961 return best2;
962 } else {
963 for (i = 0; ViaDotClocks[i].DotClock; i++)
964 if (ViaDotClocks[i].DotClock == mode->Clock)
965 return ViaDotClocks[i].UniChromePro.packed;
966 return ViaComputeProDotClock(mode->Clock);
967 }
968
969 return 0;
970 }
971