registers.c revision 90b17f1b
1249c3046Smrg/* 2 * Copyright 2009 VIA Technologies, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public 6 * License as published by the Free Software Foundation; 7 * either version 2, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTIES OR REPRESENTATIONS; without even 11 * the implied warranty of MERCHANTABILITY or FITNESS FOR 12 * A PARTICULAR PURPOSE.See the GNU General Public License 13 * for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21#include <stdlib.h> 22#include <stdio.h> 23#include <unistd.h> 24#include <string.h> 25#include <errno.h> 26#include <getopt.h> 27 28#include <sys/types.h> 29#include <sys/io.h> 30 31#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 32 33struct bit_desc { 34 u_int8_t mask; 35 char *name; 36}; 37 38struct io_index { 39 char *name; 40 struct bit_desc *bit_desc; 41}; 42 43struct io_reg { 44 u_int16_t io_port_addr; /* port for address */ 45 u_int16_t io_port_data; /* port for address */ 46 char * name; 47 struct io_index index[0xff]; 48}; 49 50struct io_reg attr_regs = { 51 .io_port_addr = 0x3c0, 52 .io_port_data = 0x3c1, 53 .name = "Attribute Controller", 54 .index = { 55 [0x00] = { "Palette 0", }, 56 [0x01] = { "Palette 1", }, 57 [0x02] = { "Palette 2", }, 58 [0x03] = { "Palette 3", }, 59 [0x04] = { "Palette 4", }, 60 [0x05] = { "Palette 5", }, 61 [0x06] = { "Palette 6", }, 62 [0x07] = { "Palette 7", }, 63 [0x08] = { "Palette 8", }, 64 [0x09] = { "Palette 9", }, 65 [0x0a] = { "Palette a", }, 66 [0x0b] = { "Palette b", }, 67 [0x0c] = { "Palette c", }, 68 [0x0d] = { "Palette d", }, 69 [0x0e] = { "Palette e", }, 70 [0x0f] = { "Palette f", }, 71 [0x10] = { "Mode Control", }, 72 [0x11] = { "Overscan Color", }, 73 [0x12] = { "Color Plane Enable", }, 74 [0x13] = { "Horizontal Pixel Panning", }, 75 [0x14] = { "Color Select", }, 76 }, 77}; 78 79struct io_reg graphic_regs = { 80 .io_port_addr = 0x3ce, 81 .io_port_data = 0x3cf, 82 .name = "Graphic Controller", 83 .index = { 84 [0x00] = { "Set / Reset", }, 85 [0x01] = { "Enable Set / Reset", }, 86 [0x02] = { "Color Compare", }, 87 [0x03] = { "Data Rotate", }, 88 [0x04] = { "Read Map Select", }, 89 [0x05] = { "Mode", }, 90 [0x06] = { "Miscellaneous", }, 91 [0x07] = { "Color Don't Care", }, 92 [0x08] = { "Bit Mask", }, 93 /* Extended */ 94 [0x20] = { "Offset Register Control", }, 95 [0x21] = { "Offset Register A", }, 96 [0x22] = { "Offset Register B", }, 97 }, 98}; 99 100 101static struct bit_desc crtc_32_desc[] = { 102 { 0x01, "Real-Time Flipping", }, 103 { 0x02, "Digital Video Port (DVP) Grammar Correction", }, 104 { 0x04, "Display End Blanking Enable", }, 105 { 0x08, "CRT SYNC Driving Selection (0: Low, 1: High)", }, 106 { 0xE0, "HSYNC Delay Number by VCLK", }, 107 { 0 }, 108}; 109 110struct io_reg crtc_regs = { 111 .io_port_addr = 0x3d4, 112 .io_port_data = 0x3d5, 113 .name = "CRT controller", 114 .index = { 115 /* CRT Controller registers */ 116 [0x00] = { "Horizontal Total", }, 117 [0x01] = { "Horizontal Display End", }, 118 [0x02] = { "Start Horizontal Blank", }, 119 [0x03] = { "End Horizontal Blank", }, 120 [0x04] = { "Start Horizontal Retrace", }, 121 [0x05] = { "End Horizontal Retrace", }, 122 [0x06] = { "Vertical Total", }, 123 [0x07] = { "Overflow", }, 124 [0x08] = { "Preset Row Scan", }, 125 [0x09] = { "Max Scan Line", }, 126 [0x0a] = { "Cursor Start", }, 127 [0x0b] = { "Cursor End", }, 128 [0x0c] = { "Start Address High", }, 129 [0x0d] = { "Start Address Low", }, 130 [0x0e] = { "Cursor Location High", }, 131 [0x0f] = { "Cursor Location Low", }, 132 [0x10] = { "Vertical Retrace Start", }, 133 [0x11] = { "Vertical Retrace End", }, 134 [0x12] = { "Vertical Display End", }, 135 [0x13] = { "Offset", }, 136 [0x14] = { "Underline Location", }, 137 [0x15] = { "Start Vertical Blank", }, 138 [0x16] = { "End Vertical Blank", }, 139 [0x17] = { "CRTC Mode Control", }, 140 [0x18] = { "Line Compare", }, 141 /* CRT Controller Extended Register */ 142 [0x30] = { "Display Fetch Blocking Control", }, 143 [0x31] = { "Half Line Position", }, 144 [0x32] = { "Mode Control", crtc_32_desc, }, 145 [0x33] = { "Hsync Adjuster", }, 146 [0x34] = { "Starting Address Overflow, Bits [23:16]", }, 147 [0x35] = { "Extended Overflow", }, 148 [0x36] = { "Power Management Control 3", }, 149 [0x37] = { "DAC Control", }, 150 [0x38] = { "Signature Data B0", }, 151 [0x39] = { "Signature Data B1", }, 152 [0x3a] = { "Signature Data B2", }, 153 [0x3b] = { "Scratch Pad 2", }, 154 [0x3c] = { "Scratch Pad 3", }, 155 [0x3d] = { "Scratch Pad 4", }, 156 [0x3e] = { "Scratch Pad 5", }, 157 [0x3f] = { "Scratch Pad 6", }, 158 [0x40] = { "Test Mode Control 0", }, 159 [0x43] = { "IGA1 Display Control", }, 160 [0x45] = { "Power Now Indicator Control 3", }, 161 [0x46] = { "Test Mode Control 1", }, 162 [0x47] = { "Test Mode Control 2", }, 163 [0x48] = { "Starting Address Overflow", }, 164 /* Sequencer Extended Registers */ 165 [0x50] = { "Second CRTC Horizontal Total Period", }, 166 [0x51] = { "Second CRTC Horizontal Active Data Period", }, 167 [0x52] = { "Second CRTC Horizontal Blanking Start", }, 168 [0x53] = { "Second CRTC Horizontal Blanking End", }, 169 [0x54] = { "Second CRTC Horizontal Blanking Overflow", }, 170 [0x55] = { "Second CRTC Horizontal Period Overflow", }, 171 [0x56] = { "Second CRTC Horizontal Retrace Start", }, 172 [0x57] = { "Second CRTC Horizontal Retrace End", }, 173 [0x58] = { "Second CRTC Vertical Total Period", }, 174 [0x59] = { "Second CRTC Vertical Active Data Period", }, 175 [0x5a] = { "Second CRTC Vertical Blanking Start", }, 176 [0x5b] = { "Second CRTC Vertical Blanking End", }, 177 [0x5c] = { "Second CRTC Vertical Blanking Overflow", }, 178 [0x5d] = { "Second CRTC Vertical Period Overflow", }, 179 [0x5e] = { "Second CRTC Vertical Retrace Start", }, 180 [0x5f] = { "Second CRTC Vertical Retrace End", }, 181 [0x60] = { "Second CRTC Vertical Status 1", }, 182 [0x61] = { "Second CRTC Vertical Status 2", }, 183 [0x62] = { "Second Display Starting Address Low", }, 184 [0x63] = { "Second Display Starting Address Middle", }, 185 [0x64] = { "Second Display Starting Address High", }, 186 [0x65] = { "Second Display Horizontal Quadword Count", }, 187 [0x66] = { "Second Display Horizontal Offset", }, 188 [0x67] = { "Second Display Color Depth and Horizontal Overflow", }, 189 [0x68] = { "Second Display Queue Depth and Read Threshold", }, 190 [0x69] = { "Second Display Interrupt Enable and Status", }, 191 [0x6a] = { "Second Display Channel and LCD Enable", }, 192 [0x6b] = { "Channel 1 and 2 Clock Mode Selection", }, 193 [0x6c] = { "TV Clock Control", }, 194 [0x6d] = { "Horizontal Total Shadow", }, 195 [0x6e] = { "End Horizontal Blanking Shadow", }, 196 [0x6f] = { "Vertical Total Shadow", }, 197 [0x70] = { "Vertical Display Enable End Shadow", }, 198 [0x71] = { "Vertical Display Overflow Shadow", }, 199 [0x72] = { "Start Vertical Blank Shadow", }, 200 [0x73] = { "End Vertical Blank Shadow", }, 201 [0x74] = { "Vertical Blank Overflow Shadow", }, 202 [0x75] = { "Vertical Retrace Start Shadow", }, 203 [0x76] = { "Vertical Retrace End Shadow", }, 204 [0x77] = { "LCD Horizontal Scaling Factor", }, 205 [0x78] = { "LCD Vertical Scaling Factor", }, 206 [0x79] = { "LCD Scaling Control", }, 207 [0x7a] = { "LCD Scaling Parameter 1", }, 208 [0x7b] = { "LCD Scaling Parameter 2", }, 209 [0x7c] = { "LCD Scaling Parameter 3", }, 210 [0x7d] = { "LCD Scaling Parameter 4", }, 211 [0x7e] = { "LCD Scaling Parameter 5", }, 212 [0x7f] = { "LCD Scaling Parameter 6", }, 213 [0x80] = { "LCD Scaling Parameter 7", }, 214 [0x81] = { "LCD Scaling Parameter 8", }, 215 [0x82] = { "LCD Scaling Parameter 9", }, 216 [0x83] = { "LCD Scaling Parameter 10", }, 217 [0x84] = { "LCD Scaling Parameter 11", }, 218 [0x85] = { "LCD Scaling Parameter 12", }, 219 [0x86] = { "LCD Scaling Parameter 13", }, 220 [0x87] = { "LCD Scaling Parameter 14", }, 221 [0x88] = { "LCD Panel Type", }, 222 [0x8a] = { "LCD Timing Control 1", }, 223 [0x8b] = { "LCD Power Sequence Control 0", }, 224 [0x8c] = { "LCD Power Sequence Control 1", }, 225 [0x8d] = { "LCD Power Sequence Control 2", }, 226 [0x8e] = { "LCD Power Sequence Control 3", }, 227 [0x8f] = { "LCD Power Sequence Control 4", }, 228 [0x90] = { "LCD Power Sequence Control 5", }, 229 [0x91] = { "Software Control Power Sequence", }, 230 [0x92] = { "Read Threshold 2", }, 231 [0x94] = { "Expire Number and Display Queue Extend", }, 232 [0x95] = { "Extend Threshold Bit", }, 233 [0x97] = { "LVDS Channel 2 Function Select 0", }, 234 [0x98] = { "LVDS Channel 2 Function Select 1", }, 235 [0x99] = { "LVDS Channel 1 Function Select 0", }, 236 [0x9a] = { "LVDS Channel 1 Function Select 1", }, 237 [0x9b] = { "Digital Video Port 1 Function Select 0", }, 238 [0x9c] = { "Digital Video Port 1 Function Select 1", }, 239 [0x9d] = { "Power Now Control 2", }, 240 [0x9e] = { "Power Now Control 3", }, 241 [0x9f] = { "Power Now Control 4", }, 242 [0xa0] = { "Horizontal Scaling Initial Value", }, 243 [0xa1] = { "Vertical Scaling Initial Value", }, 244 [0xa2] = { "Horizontal and Vertical Scaling Enable", }, 245 [0xa3] = { "Second Display Starting Address Extended", }, 246 [0xa5] = { "Second LCD Vertical Scaling Factor", }, 247 [0xa6] = { "Second LCD Vertical Scaling Factor", }, 248 [0xa7] = { "Expected IGA1 Vertical Display End", }, 249 [0xa8] = { "Expected IGA1 Vertical Display End", }, 250 [0xa9] = { "Hardware Gamma Control", }, 251 [0xaa] = { "FIFO Depth + Threshold Overflow", }, 252 [0xab] = { "IGA2 Interlace Half Line", }, 253 [0xac] = { "IGA2 Interlace Half Line", }, 254 [0xaf] = { "P-Arbiter Write Expired Number", }, 255 [0xb0] = { "IGA2 Pack Circuit Request Threshold", }, 256 [0xb1] = { "IGA2 Pack Circuit Request High Threshold", }, 257 [0xb2] = { "IGA2 Pack Circuit Request Expire Threshold", }, 258 [0xb3] = { "IGA2 Pack Circuit Control", }, 259 [0xb4] = { "IGA2 Pack Circuit Target Base Address 0", }, 260 [0xb5] = { "IGA2 Pack Circuit Target Base Address 0", }, 261 [0xb6] = { "IGA2 Pack Circuit Target Base Address 0", }, 262 [0xb7] = { "IGA2 Pack Circuit Target Base Address 0", }, 263 [0xb8] = { "IGA2 Pack Circuit Target Line Pitch", }, 264 [0xb9] = { "IGA2 Pack Circuit Target Line Pitch", }, 265 [0xba] = { "V Counter Set Pointer", }, 266 [0xbb] = { "V Counter Set Pointer", }, 267 [0xbc] = { "V Counter Reset Value", }, 268 [0xbd] = { "V Counter Reset Value", }, 269 [0xbe] = { "Frame Buffer Limit Value", }, 270 [0xbf] = { "Frame Buffer Limit Value", }, 271 [0xc0] = { "Expected IGA1 Vertical Display End 1", }, 272 [0xc1] = { "Expected IGA1 Vertical Display End 1", }, 273 [0xc2] = { "Third LCD Vertical Scaling Factor", }, 274 [0xc3] = { "Third LCD Vertical Scaling Factor", }, 275 [0xc4] = { "Expected IGA1 Vertical Display End 2", }, 276 [0xc5] = { "Expected IGA1 Vertical Display End 2", }, 277 [0xc7] = { "Fourth LCD Vertical Scaling Factor", }, 278 [0xc8] = { "IGA2 Pack Circuit Target Base Address 1", }, 279 [0xc9] = { "IGA2 Pack Circuit Target Base Address 1", }, 280 [0xca] = { "IGA2 Pack Circuit Target Base Address 1", }, 281 [0xcb] = { "IGA2 Pack Circuit Target Base Address 1", }, 282 [0xd0] = { "LVDS PLL1 Control", }, 283 [0xd1] = { "LVDS PLL2 Control", }, 284 [0xd2] = { "LVDS Control", }, 285 [0xd3] = { "LVDS Second Power Sequence Control 0", }, 286 [0xd4] = { "LVDS Second Power Sequence Control 1", }, 287 [0xd5] = { "LVDS Texting Mode Control", }, 288 [0xd6] = { "DCVI Control Register 0", }, 289 [0xd7] = { "DCVI Control Register 1", }, 290 [0xd9] = { "Scaling Down Source Data Offset Control", }, 291 [0xda] = { "Scaling Down Source Data Offset Control", }, 292 [0xdb] = { "Scaling Down Source Data Offset Control", }, 293 [0xdc] = { "Scaling Down Vertical Scale Control", }, 294 [0xdd] = { "Scaling Down Vertical Scale Control", }, 295 [0xde] = { "Scaling Down Vertical Scale Control", }, 296 [0xdf] = { "Scaling Down Vertical Scale Control", }, 297 [0xe0] = { "Scaling Down Destination FB Starting Addr 0", }, 298 [0xe1] = { "Scaling Down Destination FB Starting Addr 0", }, 299 [0xe2] = { "Scaling Down Destination FB Starting Addr 0", }, 300 [0xe3] = { "Scaling Down Destination FB Starting Addr 0", }, 301 [0xe4] = { "Scaling Down SW Source FB Stride", }, 302 [0xe5] = { "Scaling Down Destination FB Starting Addr 1", }, 303 [0xe6] = { "Scaling Down Destination FB Starting Addr 1", }, 304 [0xe7] = { "Scaling Down Destination FB Starting Addr 1", }, 305 [0xe8] = { "Scaling Down Destination FB Starting Addr 1", }, 306 [0xe9] = { "Scaling Down Destination FB Starting Addr 2", }, 307 [0xea] = { "Scaling Down Destination FB Starting Addr 2", }, 308 [0xeb] = { "Scaling Down Destination FB Starting Addr 2", }, 309 [0xec] = { "IGA1 Down Scaling Destination Control", }, 310 [0xf0] = { "Snapshot Mode - Starting Address of Disp Data", }, 311 [0xf1] = { "Snapshot Mode - Starting Address of Disp Data", }, 312 [0xf2] = { "Snapshot Mode - Starting Address of Disp Data", }, 313 [0xf3] = { "Snapshot Mode Control", }, 314 [0xf4] = { "Snapshot Mode Control", }, 315 [0xf5] = { "Snapshot Mode Control", }, 316 [0xf6] = { "Snapshot Mode Control", }, 317 }, 318}; 319 320static struct bit_desc seq_19_desc[] = { 321 { 0x01, "CPU Interface Clock Control", }, 322 { 0x02, "Display Interface Clock Control", }, 323 { 0x04, "MC Interface Clock Control", }, 324 { 0x08, "Typical Arbiter Interface Clock Control", }, 325 { 0x10, "AGP Interface Clock Control", }, 326 { 0x20, "P-Arbiter Interface Clock Control", }, 327 { 0x40, "MIU/AGP Interface Clock Control", }, 328 { 0 }, 329}; 330 331 332static struct bit_desc seq_1a_desc[] = { 333 { 0x01, "LUT Shadow Access", }, 334 { 0x04, "PCI Burst Write Wait State Select (0: 0 Wait state, 1: 1 Wait state)", }, 335 { 0x08, "Extended Mode Memory Access Enable (0: Disable, 1: Enable)", }, 336 { 0x40, "Software Reset (0: Default value, 1: Reset)", }, 337 { 0x80, "Read Cache Enable (0: Disable, 1: Enable)", }, 338 { 0 }, 339}; 340 341static struct bit_desc seq_1b_desc[] = { 342 { 0x01, "Primary Display's LUT Off", }, 343 { 0x18, "Primary Display Engine VCK Gating", }, 344 { 0x60, "Secondary Display Engine LCK Gating", }, 345 { 0 }, 346}; 347 348static struct bit_desc seq_1e_desc[] = { 349 { 0x01, "ROC ECK", }, 350 { 0x02, "Replace ECK by MCK", }, 351 { 0x08, "Spread Spectrum", }, 352 { 0x30, "DVP1 Power Control", }, 353 { 0xc0, "VCP Power Control", }, 354 { 0 }, 355}; 356 357static struct bit_desc seq_2a_desc[] = { 358 { 0x03, "LVDS Channel 1 Pad Control" }, 359 { 0x0c, "LVDS Channel 2 Pad Control" }, 360 { 0x40, "Spread Spectrum Type FIFO" }, 361 { 0 }, 362}; 363 364static struct bit_desc seq_2b_desc[] = { 365 { 0x01, "MSI Pending IRQ Re-trigger", }, 366 { 0x02, "CRT Hot Plug Detect Enable", }, 367 { 0x04, "CRT Sense IRQ status", }, 368 { 0x08, "CRT Sense IRQ enable", }, 369 { 0x10, "LVDS Sense IRQ status", }, 370 { 0x20, "LVDS Sense IRQ enable", }, 371 { 0 }, 372}; 373 374static struct bit_desc seq_2d_desc[] = { 375 { 0x03, "ECK Pll Power Control", }, 376 { 0x0c, "LCK PLL Power Control", }, 377 { 0x30, "VCK PLL Power Control", }, 378 { 0xc0, "E3_ECK_N Selection", }, 379 { 0 }, 380}; 381 382static struct bit_desc seq_2e_desc[] = { 383 { 0x03, "Video Playback Engine V3/V4 Gated Clock VCK", }, 384 { 0x0c, "PCI Master / DMA Gated Clock ECK/CPUCK", }, 385 { 0x30, "Video Processor Gated Clock ECK", }, 386 { 0xc0, "Capturer Gated Clock ECK", }, 387 { 0 }, 388}; 389 390static struct bit_desc seq_3c_desc[] = { 391 { 0x01, "AGP Bus Pack Door AGP3 Enable", }, 392 { 0x02, "Switch 3 PLLs to Prime Output", }, 393 { 0x04, "LCDCK PLL Locked Detect", }, 394 { 0x08, "VCK PLL Locked Detect", }, 395 { 0x10, "ECL PLL Locked Detect", }, 396 { 0x60, "PLL Frequency Division Select for Testing", }, 397 { 0 }, 398}; 399 400static struct bit_desc seq_3f_desc[] = { 401 { 0x03, "Video Clock Control (Gated ECK)", }, 402 { 0x0c, "2D Clock Control (Gated ECK/CPUCK)", }, 403 { 0x30, "3D Clock Control (Gated ECK)", }, 404 { 0xc0, "CR Clock Control (Gated ECK)", }, 405 { 0 }, 406}; 407 408static struct bit_desc seq_40_desc[] = { 409 { 0x01, "Reset ECK PLL", }, 410 { 0x02, "Reset VCK PLL", }, 411 { 0x04, "Reset LCDCK PLL", }, 412 { 0x08, "LVDS Interrupt Method", }, 413 { 0x30, "Free Run ECK Frequency within Idle Mode", }, 414 { 0x80, "CRT Sense Enable", }, 415 { 0 }, 416}; 417 418static struct bit_desc seq_43_desc[] = { 419 { 0x01, "Notebook Used Flag", }, 420 { 0x04, "Typical Channel 1 Arbiter Read Back Data Overwrite Flag", }, 421 { 0x08, "Typical Channel 0 Arbiter Read Back Data Overwrite Flag", }, 422 { 0x10, "IGA1 Display FIFO Underflow Flag", }, 423 { 0x20, "IGA2 Display FIFO Underflow Flag", }, 424 { 0x40, "Windows Media Video Enable Flag", }, 425 { 0x80, "Advance Video Enable Flag", }, 426 { 0 }, 427}; 428 429static struct bit_desc seq_4e_desc[] = { 430 { 0x01, "HQV/Video/Capture Engine Reset", }, 431 { 0x02, "HQV/Video/Capture Register Reset", }, 432 { 0x04, "2D Engine Reset", }, 433 { 0x08, "2D Register Reset", }, 434 { 0x10, "3D Engine Reset", }, 435 { 0x20, "3D Register Reset", }, 436 { 0x40, "CR Engine Reset", }, 437 { 0x80, "CR Register Reset", }, 438 { 0 }, 439}; 440 441static struct bit_desc seq_59_desc[] = { 442 { 0x01, "GFX-NM AGP Dynamic Clock Enable", }, 443 { 0x02, "GFX-NM GMINT Channel 0 Dynamic Clock Enable", }, 444 { 0x04, "GFX-NM GMINT Channel 1 Dynamic Clock Enable", }, 445 { 0x08, "GFX-NM PCIC Dynamic Clock Enable", }, 446 { 0x10, "GFX-NM IGA Dynamic Clock Enable", }, 447 { 0x20, "IGA Low Threshold Enable", }, 448 { 0x80, "IGA1 Enable", }, 449 { 0 }, 450}; 451 452static struct bit_desc seq_5b_desc[] = { 453 { 0x01, "LVDS1 Used IGA2 Source", }, 454 { 0x02, "LBDS1 Used IGA1 Source", }, 455 { 0x04, "LVDS0 Used IGA2 Source", }, 456 { 0x08, "LVDS1 Used IGA1 Source", }, 457 { 0x10, "DAC0 Used IGA2 Source", }, 458 { 0x20, "DAC0 Used IGA1 Source", }, 459 { 0x40, "DAC0 User is TV", }, 460 { 0x80, "DCVI Source Selection is TV", }, 461 { 0 }, 462}; 463 464static struct bit_desc seq_5c_desc[] = { 465 { 0x01, "DVP1 Used IGA2 Source", }, 466 { 0x02, "DVP1 Used IGA1 Source", }, 467 { 0x10, "DAC1 Used IGA2 Source", }, 468 { 0x20, "DAC1 Used IGA1 Source", }, 469 { 0x40, "DAC1 User is TV", }, 470 { 0 }, 471}; 472 473static struct bit_desc seq_76_desc[] = { 474 { 0x01, "Backlight Control Enable", }, 475 { 0 }, 476}; 477 478struct io_reg sequencer_regs = { 479 .io_port_addr = 0x3c4, 480 .io_port_data = 0x3c5, 481 .name = "Sequencer", 482 .index = { 483 /* Sequencer Registers */ 484 [0x00] = { "Reset", }, 485 [0x01] = { "Clocking Mode", }, 486 [0x02] = { "Map Mask", }, 487 [0x03] = { "Character Map Select", }, 488 [0x04] = { "Memory Mode", }, 489 /* Extended Sequencer Registers */ 490 [0x10] = { "Extended Register Unlock", }, 491 [0x11] = { "Configuration 0", }, 492 [0x12] = { "Configuration 1", }, 493 [0x13] = { "Configuration 2 (DVP1 strapping)", }, 494 [0x14] = { "Frame Buffer Size Control", }, 495 [0x15] = { "Display Mode Control", }, 496 [0x16] = { "Display FIFO Threshold Control", }, 497 [0x17] = { "Display FIFO Control", }, 498 [0x18] = { "Display Arbiter Control 0", }, 499 [0x19] = { "Power Management", seq_19_desc, }, 500 [0x1a] = { "PCI Bus Control", seq_1a_desc, }, 501 [0x1b] = { "Power Management Control 0", seq_1b_desc, }, 502 [0x1c] = { "Horizontal Display Fetch Count Data", }, 503 [0x1d] = { "Horizontal Display Fetch Count Control", }, 504 [0x1e] = { "Power Management Control", seq_1e_desc, }, 505 /* 1f: reserved */ 506 [0x20] = { "Typical Arbiter Control 0", }, 507 [0x21] = { "Typical Arbiter Control 1", }, 508 [0x22] = { "Display Arbiter Control 1", }, 509 [0x26] = { "IIC Serial Port Control 0", }, 510 [0x2a] = { "Power Management Control 5", seq_2a_desc, }, 511 [0x2b] = { "LVDS Interrupt Control", seq_2b_desc, }, 512 [0x2c] = { "General Purpose I/O Port", }, 513 [0x2d] = { "Power Management Control 1", seq_2d_desc, }, 514 [0x2e] = { "Power Management Control 2", seq_2e_desc, }, 515 [0x31] = { "IIC Serial Port Control 1", }, 516 [0x35] = { "Subsystem Vendor ID Low", }, 517 [0x36] = { "Subsystem Vendor ID High", }, 518 [0x37] = { "Subsystem ID Low", }, 519 [0x38] = { "Subsystem ID High", }, 520 [0x39] = { "BIOS Reserved Register 0", }, 521 [0x3a] = { "BIOS Reserved Register 1", }, 522 [0x3b] = { "PCI Revision ID Back Door", }, 523 [0x3c] = { "Miscellaneous", seq_3c_desc, }, 524 [0x3d] = { "General Purpose I/O Port", }, 525 [0x3e] = { "Miscellaneous Register for AGP Mux", }, 526 [0x3f] = { "Power Management Control 2", seq_3f_desc, }, 527 [0x40] = { "PLL Control", seq_40_desc, }, 528 [0x41] = { "Typical Arbiter Control 1", }, 529 [0x42] = { "Typical Arbiter Control 2", }, 530 [0x43] = { "Graphics Bonding Option", seq_43_desc, }, 531 [0x44] = { "VCK Clock Synthesizer Value 0", }, 532 [0x45] = { "VCK Clock Synthesizer Value 1", }, 533 [0x46] = { "VCK Clock Synthesizer Value 2", }, 534 [0x47] = { "ECK Clock Synthesizer Value 0", }, 535 [0x48] = { "ECK Clock Synthesizer Value 1", }, 536 [0x49] = { "ECK Clock Synthesizer Value 2", }, 537 [0x4a] = { "LDCK Clock Synthesizer Value 0", }, 538 [0x4b] = { "LDCK Clock Synthesizer Value 1", }, 539 [0x4c] = { "LDCK Clock Synthesizer Value 2", }, 540 [0x4d] = { "Preemptive Arbiter Control", }, 541 [0x4e] = { "Software Reset Control", seq_4e_desc, }, 542 [0x4f] = { "CR Gating Clock Control", }, 543 [0x50] = { "AGP Control", }, 544 [0x51] = { "Display FIFO Control 1", }, 545 [0x52] = { "Integrated TV Shadow Register Control", }, 546 [0x53] = { "DAC Sense Control 1", }, 547 [0x54] = { "DAC Sense Control 2", }, 548 [0x55] = { "DAC Sense Control 3", }, 549 [0x56] = { "DAC Sense Control 4", }, 550 [0x57] = { "Display FIFO Control 2", }, 551 [0x58] = { "GFX Power Control 1", }, 552 [0x59] = { "GFX Power Control 2", seq_59_desc, }, 553 [0x5a] = { "PCI Bus Control 2", }, 554 [0x5b] = { "Device Used Status 0", seq_5b_desc, }, 555 [0x5c] = { "Device Used Status 1", seq_5c_desc, }, 556 [0x5d] = { "Timer Control", }, 557 [0x5e] = { "DAC Control 2", }, 558 [0x60] = { "I2C Mode Control", }, 559 [0x61] = { "I2C Host Address", }, 560 [0x62] = { "I2C Host Data", }, 561 [0x63] = { "I2C Host Control", }, 562 [0x64] = { "I2C Status", }, 563 [0x65] = { "Power Management Control 6", }, 564 [0x66] = { "GTI Control 0", }, 565 [0x67] = { "GTI Control 1", }, 566 [0x68] = { "GTI Control 2", }, 567 [0x69] = { "GTI Control 3", }, 568 [0x6a] = { "GTI Control 4", }, 569 [0x6b] = { "GTI Control 5", }, 570 [0x6c] = { "GTI Control 6", }, 571 [0x6d] = { "GTI Control 7", }, 572 [0x6e] = { "GTI Control 8", }, 573 [0x6f] = { "GTI Control 9", }, 574 [0x70] = { "GARB Control 0", }, 575 [0x71] = { "Typical Arbiter Control 2", }, 576 [0x72] = { "Typical Arbiter Control 3", }, 577 [0x73] = { "Typical Arbiter Control 4", }, 578 [0x74] = { "Typical Arbiter Control 5", }, 579 [0x75] = { "Typical Arbiter Control 6", }, 580 [0x76] = { "Backlight Control 1", seq_76_desc, }, 581 [0x77] = { "Backlight Control 2", }, 582 [0x78] = { "Backlight Control 3", }, 583 }, 584}; 585 586static u_int8_t readb_idx_reg(u_int16_t port, u_int8_t index) 587{ 588 outb(index, port-1); 589 return inb(port); 590} 591 592static void writeb_idx_reg(u_int16_t port, u_int8_t index, 593 u_int8_t val) 594{ 595 outb(index, port-1); 596 outb(val, port); 597} 598 599static void writeb_idx_mask(u_int16_t reg, u_int8_t idx, u_int8_t val, 600 u_int8_t mask) 601{ 602 u_int8_t tmp; 603 604 tmp = readb_idx_reg(reg, idx); 605 tmp &= ~ mask; 606 tmp |= (val & mask); 607 writeb_idx_reg(reg, idx, tmp); 608} 609 610 611struct io_reg *io_regs[] = { 612 //&attr_regs, 613 &sequencer_regs, 614 &graphic_regs, 615 &crtc_regs, 616 NULL 617}; 618 619struct half_mode { 620 u_int16_t total; 621 u_int16_t active; 622 u_int16_t blank_start; 623 u_int16_t blank_end; 624 u_int16_t retr_start; 625 u_int16_t retr_end; 626 int n_sync; 627}; 628 629struct mode { 630 struct half_mode h; 631 struct half_mode v; 632 u_int32_t addr_start; 633 u_int8_t bpp; 634 u_int16_t horiz_quad_count; 635 u_int16_t horiz_offset; 636}; 637 638static int get_mode(struct mode *m, int secondary) 639{ 640 u_int8_t val; 641 642 memset(m, 0, sizeof(*m)); 643 644 if (!secondary) { 645 m->h.total = readb_idx_reg(0x3d5, 0x00); 646 m->h.active = readb_idx_reg(0x3d5, 0x01); 647 m->h.blank_start = readb_idx_reg(0x3d5, 0x02); 648 m->h.blank_end = readb_idx_reg(0x3d5, 0x03) & 0x1f; 649 m->h.retr_start = readb_idx_reg(0x3d5, 0x04); 650 m->h.retr_end = readb_idx_reg(0x3d5, 0x05) & 0x1f; 651 m->v.total = readb_idx_reg(0x3d5, 0x06) + 2; 652 653 m->addr_start = readb_idx_reg(0x3d5, 0x0d); 654 m->addr_start |= readb_idx_reg(0x3d5, 0x0c) << 8; 655 656 m->v.retr_start = readb_idx_reg(0x3d5, 0x10); 657 m->v.retr_end = readb_idx_reg(0x3d5, 0x11) & 0x0f; 658 m->v.active = readb_idx_reg(0x3d5, 0x12) + 1; 659 m->horiz_offset = readb_idx_reg(0x3d5, 0x13); 660 m->v.blank_start = readb_idx_reg(0x3d5, 0x15) + 1; 661 m->v.blank_end = readb_idx_reg(0x3d5, 0x16) + 1; 662 663 /* overflow register 0x07 */ 664 val = readb_idx_reg(0x3d5, 0x07); 665 m->v.total |= ((val >> 0) & 0x1) << 8; 666 m->v.active |= ((val >> 1) & 0x1) << 8; 667 m->v.retr_start |= ((val >> 2) & 0x1) << 8; 668 m->v.blank_start |= ((val >> 3) & 0x1) << 8; 669 /* line compare */ 670 m->v.total |= ((val >> 5) & 0x1) << 9; 671 m->v.active |= ((val >> 6) & 0x1) << 9; 672 m->v.retr_start |= ((val >> 7) & 0x1) << 9; 673 674 val = readb_idx_reg(0x3d5, 0x09); 675 m->v.blank_start |= ((val >> 5) & 0x1) << 9; 676 677 val = readb_idx_reg(0x3d5, 0x33); 678 m->h.retr_start |= ((val >> 4) & 0x1) << 8; 679 m->h.blank_end |= ((val >> 5) & 0x1) << 6; 680 681 val = readb_idx_reg(0x3d5, 0x34); 682 m->addr_start |= val << 16; 683 684 val = readb_idx_reg(0x3d5, 0x35); 685 m->v.total |= ((val >> 0) & 0x1) << 10; 686 m->v.retr_start |= ((val >> 1) & 0x1) << 10; 687 m->v.active |= ((val >> 2) & 0x1) << 10; 688 m->v.blank_start |= ((val >> 3) & 0x1) << 10; 689 //line_comp |= ((val >> 4) & 0x1) << 10; 690 m->horiz_offset |= ((val >> 5) & 0x7) << 8; 691 692 val = readb_idx_reg(0x3d5, 0x36); 693 m->h.total |= ((val >> 3) & 0x1) << 8; 694 695 val = readb_idx_reg(0x3d5, 0x48); 696 m->addr_start |= ((val >> 0) & 0x1f) << 24; 697 698 val = readb_idx_reg(0x3c5, 0x15); 699 switch ((val >> 2) & 0x3) { 700 case 0: 701 m->bpp = 8; 702 break; 703 case 1: 704 m->bpp = 16; 705 break; 706 case 2: 707 m->bpp = 30; 708 break; 709 case 3: 710 m->bpp = 32; 711 break; 712 } 713 714 val = inb(0x3cc); 715 if (val & 0x40) 716 m->h.n_sync; 717 if (val & 0x80) 718 m->v.n_sync; 719 720 /* add some weird multipliers and offsets */ 721 m->h.total = (m->h.total + 5) << 3; 722 m->h.active = (m->h.active + 1) << 3; 723 m->h.blank_start = (m->h.blank_start + 1) << 3; 724 m->h.blank_end = (m->h.blank_end + 1) << 3; 725 m->h.retr_start = (m->h.retr_start << 3); 726 m->h.retr_end = (m->h.retr_end << 3); 727 728 } else { 729 /* horizontal */ 730 m->h.total = readb_idx_reg(0x3d5, 0x50) + 1; 731 m->h.active = readb_idx_reg(0x3d5, 0x51) + 1; 732 m->h.blank_start = readb_idx_reg(0x3d5, 0x52) + 1; 733 m->h.blank_end = readb_idx_reg(0x3d5, 0x53) + 1; 734 m->h.retr_start = readb_idx_reg(0x3d5, 0x56); 735 m->h.retr_end = readb_idx_reg(0x3d5, 0x57); 736 /* add blanking overflow */ 737 val = readb_idx_reg(0x3d5, 0x54); 738 m->h.blank_start |= ((val >> 0) & 0x7) << 8; 739 m->h.blank_end |= ((val >> 3) & 0x7) << 8; 740 m->h.retr_start |= ((val >> 6) & 0x3) << 8; 741 /* add period overflow */ 742 val = readb_idx_reg(0x3d5, 0x55); 743 m->h.total |= ((val >> 0) & 0xf) << 8; 744 m->h.active |= ((val >> 4) & 0x7) << 8; 745 746 /* vertical */ 747 m->v.total = readb_idx_reg(0x3d5, 0x58) + 1; 748 m->v.active = readb_idx_reg(0x3d5, 0x59) + 1; 749 m->v.blank_start = readb_idx_reg(0x3d5, 0x5a) + 1; 750 m->v.blank_end = readb_idx_reg(0x3d5, 0x5b) + 1; 751 m->v.retr_start = readb_idx_reg(0x3d5, 0x5e); 752 val = readb_idx_reg(0x3d5, 0x5f); 753 m->v.retr_end = val & 0x1f; 754 m->v.retr_start |= (val >> 5) << 8; 755 /* add blanking overflow */ 756 val = readb_idx_reg(0x3d5, 0x5c); 757 m->v.blank_start |= ((val >> 0) & 0x7) << 8; 758 m->v.blank_end |= ((val >> 3) & 0x7) << 8; 759 m->h.retr_end |= ((val >> 6) & 0x1) << 8; 760 m->h.retr_start |= ((val >> 7) & 0x1) << 10; 761 /* add period overflow */ 762 val = readb_idx_reg(0x3d5, 0x5d); 763 m->v.total |= ((val >> 0) & 0x7) << 8; 764 m->v.active |= ((val >> 3) & 0x7) << 8; 765 m->h.blank_end |= ((val >> 6) & 0x7) << 11; 766 m->h.retr_start |= ((val >> 7) & 0x7) << 11; 767 768 /* puzzle together the start address */ 769 val = readb_idx_reg(0x3d5, 0x62); 770 m->addr_start = (val >> 1) << 3; 771 val = readb_idx_reg(0x3d5, 0x63); 772 m->addr_start |= (val << 10); 773 val = readb_idx_reg(0x3d5, 0x64); 774 m->addr_start |= (val << 18); 775 val = readb_idx_reg(0x3d5, 0xa3); 776 m->addr_start |= (val & 0x7) << 26; 777 778 m->horiz_quad_count = readb_idx_reg(0x3d5, 0x65); 779 m->horiz_offset = readb_idx_reg(0x3d5, 0x66) << 3; 780 781 val = readb_idx_reg(0x3d5, 0x67); 782 m->horiz_offset |= ((val >> 0) & 0x3) << 11; 783 m->horiz_quad_count |= ((val >> 2) & 0x3) << 8; 784 switch (val >> 6) { 785 case 0: 786 m->bpp = 8; 787 break; 788 case 1: 789 m->bpp = 16; 790 break; 791 case 2: 792 m->bpp = 30; 793 break; 794 case 3: 795 m->bpp = 32; 796 break; 797 } 798 } 799} 800 801static void dump_scaling(void) 802{ 803 u_int32_t h_scaling, v_scaling; 804 u_int8_t val; 805 806 val = readb_idx_reg(0x3d5, 0x79); 807 if (val & 0x01) { 808 printf("Panel Scaling enabled, mode %s\n", 809 val & 0x02 ? "Interpolation" : "Duplication"); 810 v_scaling = (val >> 3) & 0x1; 811 h_scaling = ((val >> 4) & 0x3) << 10; 812 v_scaling |= ((val >> 6) & 0x3) << 9; 813 814 val = readb_idx_reg(0x3d5, 0x77); 815 h_scaling |= val << 2; 816 817 val = readb_idx_reg(0x3d5, 0x78); 818 v_scaling |= val << 1; 819 820 val = readb_idx_reg(0x3d5, 0x9f); 821 h_scaling |= val & 0x3; 822 printf("Scaling Factors: horizontal=%u, vertical=%u\n", 823 h_scaling, v_scaling); 824 } else 825 printf("Panel Scaling disabled\n"); 826} 827 828static void dump_registers(struct io_reg *ior) 829{ 830 u_int8_t idx; 831 832 printf("%s register dump (IO Port address: 0x%03x): \n", ior->name, ior->io_port_addr); 833 for (idx = 0; idx < 0xff; idx++) { 834 u_int8_t val; 835 struct bit_desc *desc = ior->index[idx].bit_desc; 836 837 if (!ior->index[idx].name) 838 continue; 839 840 outb(idx, ior->io_port_addr); 841 val = inb(ior->io_port_data); 842 printf(" %03x.%02x = 0x%02x (%s)\n", ior->io_port_data, idx, val, 843 ior->index[idx].name); 844 845 if (!desc) 846 continue; 847 848 while (desc->mask) { 849 printf(" 0x%02x %s: 0x%02x\n", desc->mask, 850 desc->name, val & desc->mask); 851 desc++; 852 } 853 } 854 printf("\n"); 855} 856 857enum pll { 858 PLL_VCK, 859 PLL_ECK, 860 PLL_LDCK, 861}; 862 863#define REF_FREQ 14318 864 865static void get_vck_clock(enum pll pll, unsigned int f_ref_khz) 866{ 867 u_int8_t reg_ofs = 0; 868 u_int8_t val; 869 unsigned int dm, dtz, dr, dn; 870 unsigned long f_vco, f_out; 871 char *name; 872 873 switch (pll) { 874 case PLL_VCK: 875 reg_ofs = 0; 876 name = "VCK"; 877 break; 878 case PLL_ECK: 879 reg_ofs = 3; 880 name = "ECK"; 881 break; 882 case PLL_LDCK: 883 reg_ofs = 6; 884 name = "LDCK"; 885 break; 886 default: 887 return; 888 } 889 890 dm = readb_idx_reg(0x3c5, 0x44 + reg_ofs); 891 892 val = readb_idx_reg(0x3c5, 0x45 + reg_ofs); 893 dtz = val & 0x1; 894 dr = (val >> 3) & 0x7; 895 dm |= ((val >> 6) & 0x3) << 8; 896 897 val = readb_idx_reg(0x3c5, 0x46 + reg_ofs); 898 dtz |= (val & 0x1) << 1; 899 dn = val >> 1; 900 901 printf("%s PLL: dm=%d, dtx=%d, dr=%d, dn=%d ", name, dm, dtz, dr, dn); 902 903 f_vco = f_ref_khz * (dm + 2) / (dn + 2); 904 if (dr) 905 f_out = f_ref_khz * (dm + 2) / ( (dn + 2) * (2 * dr) ); 906 else 907 f_out = 0; 908 909 printf("%s Fvco=%lu kHz, Fout=%lu kHz\n", name, f_vco, f_out); 910} 911 912struct gpio_state { 913 u_int32_t mode_output; 914 u_int32_t pin_status; 915 u_int32_t output_bit; 916 u_int32_t alt_function; 917}; 918 919static int get_gpio_state(struct gpio_state *s) 920{ 921 u_int8_t val; 922 923 memset(s, 0, sizeof(*s)); 924 925 val = readb_idx_reg(0x3c5, 0x2c); 926 if (val & 0x01) 927 s->alt_function |= (3 << 2); 928 if (val & 0x04) 929 s->pin_status |= (1 << 3); 930 if (val & 0x08) 931 s->pin_status |= (1 << 2); 932 if (val & 0x10) 933 s->output_bit |= (1 << 3); 934 if (val & 0x20) 935 s->output_bit |= (1 << 2); 936 if (val & 0x40) 937 s->mode_output |= (1 << 3); 938 if (val & 0x80) 939 s->mode_output |= (1 << 2); 940 941 val = readb_idx_reg(0x3c5, 0x3d); 942 if (val & 0x01) 943 s->alt_function |= (3 << 4); 944 if (val & 0x04) 945 s->pin_status |= (1 << 5); 946 if (val & 0x08) 947 s->pin_status |= (1 << 4); 948 if (val & 0x10) 949 s->output_bit |= (1 << 5); 950 if (val & 0x20) 951 s->output_bit |= (1 << 4); 952 if (val & 0x40) 953 s->mode_output |= (1 << 5); 954 if (val & 0x80) 955 s->mode_output |= (1 << 4); 956 957} 958 959static void dump_gpio_state(const char *pfx, const struct gpio_state *gs) 960{ 961 int i; 962 963 for (i = 2; i < 6; i++) { 964 printf("%sGPIO %u: function=", pfx, i); 965 966 if (gs->alt_function & (1 << i)) 967 printf("alternate\n"); 968 else if (gs->mode_output & (1 << i)) 969 printf("output(%u)\n", gs->output_bit & (1 <<i) ? 1 : 0); 970 else 971 printf("input(%u)\n", gs->pin_status & (1 << i) ? 1 : 0); 972 } 973} 974 975static void dump_all_registers(void) 976{ 977 int i; 978 979 for (i = 0; i < ARRAY_SIZE(io_regs); i++) { 980 struct io_reg *reg = io_regs[i]; 981 if (!reg) 982 break; 983 dump_registers(reg); 984 } 985 986} 987 988static void dump_mode(const char *pfx, struct mode *m) 989{ 990 printf("%sH total=%u, active=%u, blank (%u-%u), sync(%u-%u)\n", 991 pfx, m->h.total, m->h.active, m->h.blank_start, m->h.blank_end, 992 m->h.retr_start, m->h.retr_end); 993 printf("%sV total=%u, active=%u, blank (%u-%u), sync(%u-%u)\n", 994 pfx, m->v.total, m->v.active, m->v.blank_start, m->v.blank_end, 995 m->v.retr_start, m->v.retr_end); 996 printf("base_addr=0x%08x, bpp=%d\n", m->addr_start, m->bpp); 997} 998 999static void dump_sl(const char *pfx) 1000{ 1001 u_int8_t val; 1002 unsigned int sl_size_mb; 1003 unsigned long rtsf_in_sl_addr; 1004 u_int64_t sl_in_mem_addr; 1005 1006 val = readb_idx_reg(0x3c5, 0x68); 1007 switch (val) { 1008 case 0: 1009 sl_size_mb = 512; 1010 break; 1011 case 0x80: 1012 sl_size_mb = 256; 1013 break; 1014 case 0xc0: 1015 sl_size_mb = 128; 1016 break; 1017 case 0xe0: 1018 sl_size_mb = 64; 1019 break; 1020 case 0xf0: 1021 sl_size_mb = 32; 1022 break; 1023 case 0xf8: 1024 sl_size_mb = 16; 1025 break; 1026 case 0xfc: 1027 sl_size_mb = 8; 1028 break; 1029 case 0xfe: 1030 sl_size_mb = 4; 1031 break; 1032 case 0xff: 1033 sl_size_mb = 2; 1034 break; 1035 } 1036 1037 rtsf_in_sl_addr = readb_idx_reg(0x3c5, 0x6a) << 12; 1038 rtsf_in_sl_addr |= readb_idx_reg(0x3c5, 0x6b) << 20; 1039 val = readb_idx_reg(0x3c5, 0x6c); 1040 rtsf_in_sl_addr |= (val & 0x1) << 28; 1041 1042 sl_in_mem_addr = readb_idx_reg(0x3c5, 0x6d) << 21; 1043 sl_in_mem_addr |= readb_idx_reg(0x3c5, 0x6d) << 29; 1044 sl_in_mem_addr |= (readb_idx_reg(0x3c5, 0x6d) & 0x7f) << 37; 1045 1046 printf("%sSL in System memory: 0x%llx, RTSF in SL: 0x%lx\n", 1047 pfx, sl_in_mem_addr, rtsf_in_sl_addr); 1048} 1049 1050static int dump_lvds(void) 1051{ 1052 u_int8_t val; 1053 char *mode; 1054 1055 writeb_idx_mask(0x3c5, 0x5a, 0x01, 0x01); 1056 1057 val = readb_idx_reg(0x3c5, 0x13); 1058 switch (val >> 6) { 1059 case 0: 1060 mode = "LVDS1 + LVDS2"; 1061 break; 1062 case 2: 1063 mode = "One Dual LVDS Channel"; 1064 break; 1065 default: 1066 mode = "RESERVED"; 1067 break; 1068 } 1069 printf("LVDS Seq Mode: %s\n", mode); 1070 1071 val = readb_idx_reg(0x3d5, 0xd2); 1072 switch ((val >> 4) & 3) { 1073 case 0: 1074 mode = "LVDS1 + LVDS2"; 1075 break; 1076 case 2: 1077 mode = "One Dual LVDS Channel"; 1078 break; 1079 default: 1080 mode = "RESERVED"; 1081 break; 1082 } 1083 printf("LVDS CRT Mode: %s\n", mode); 1084 printf("LVDS Channel 1 Format %s, Power %s\n", 1085 val & 2 ? "OpenLDI":"SPWG", val & 0x80 ? "Down" : "Up"); 1086 printf("LVDS Channel 2 Format %s, Power %s\n", 1087 val & 1 ? "OpenLDI":"SPWG", val & 0x40 ? "Down" : "Up"); 1088 1089} 1090static int parse_ioreg(u_int16_t *reg, u_int8_t *index, char *str) 1091{ 1092 char *dot; 1093 char buf[255]; 1094 1095 memset(buf, 0, sizeof(*buf)); 1096 strncpy(buf, str, sizeof(buf)-1); 1097 1098 dot = strchr(buf, '.'); 1099 if (!dot) 1100 return -EINVAL; 1101 *dot = '\0'; 1102 1103 *reg = strtoul(buf, NULL, 16); 1104 *index = strtoul(dot+1, NULL, 16); 1105 1106 return 0; 1107} 1108 1109static void reset_mode(int secondary) 1110{ 1111 if (!secondary) { 1112 writeb_idx_mask(0x3d5, 0x11, 0x00 , 0x80); 1113 writeb_idx_mask(0x3d5, 0x03, 0x80 , 0x80); 1114 } else { 1115 } 1116} 1117 1118static void unlock_registers(void) 1119{ 1120 writeb_idx_reg(0x3c5, 0x10, 0x01); /* unlock extended */ 1121 writeb_idx_mask(0x3d5, 0x47, 0x00, 0x01); /* unlock CRT */ 1122 writeb_idx_mask(0x3d5, 0x03, 0x80, 0x80); /* disable EGA lightpen */ 1123 writeb_idx_mask(0x3d5, 0x11, 0x00, 0x80); /* unlock 0..7 */ 1124} 1125 1126static void usage(void) 1127{ 1128 printf("Usage :\n"); 1129 printf("-h | --help : Display this usage message.\n"); 1130 printf("-d | --dump : Dump all registers.\n"); 1131 printf("-p | --pll : Display PLL.\n"); 1132 printf("-m | --mode : Display modes.\n"); 1133 printf("-r | --read : Read register. Example : $0 -r 3d5.17\n"); 1134 printf("-w | --write : Write register. Example : $0 -w 3d5.17 0xa3\n"); 1135 printf("-g | --gpio : Display GPIO state.\n"); 1136} 1137 1138int main(int argc, char **argv) 1139{ 1140 struct mode m; 1141 struct gpio_state gs; 1142 int rc, option_index = 0; 1143 1144 printf("via-chrome-tool (C) 2009 by VIA Technologies, Inc.\n"); 1145 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n"); 1146 1147 rc = iopl(3); 1148 if (rc < 0) { 1149 perror("iopl"); 1150 printf("Need root privileges.\n"); 1151 exit(1); 1152 } 1153 1154 if (argc <= 1) { 1155 usage(); 1156 exit(1); 1157 } 1158 1159 unlock_registers(); 1160 1161 while (1) { 1162 int c; 1163 u_int16_t reg; 1164 u_int8_t index; 1165 unsigned long val; 1166 static struct option long_options[] = { 1167 { "help", 0, 0, 'h' }, 1168 { "dump", 0, 0, 'd' }, 1169 { "pll", 0, 0, 'p' }, 1170 { "mode", 0, 0, 'm' }, 1171 { "read", 1, 0, 'r' }, 1172 { "write", 1, 0, 'w' }, 1173 { "gpio", 1, 0, 'g' }, 1174 }; 1175 1176 c = getopt_long(argc, argv, "hdpmr:w:g", long_options, 1177 &option_index); 1178 1179 if (c == -1) { 1180 break; 1181 } 1182 1183 switch (c) { 1184 case 'h': 1185 usage(); 1186 exit(1); 1187 case 'd': 1188 dump_all_registers(); 1189 break; 1190 case 'p': 1191 get_vck_clock(PLL_VCK, REF_FREQ); 1192 get_vck_clock(PLL_ECK, REF_FREQ); 1193 get_vck_clock(PLL_LDCK, REF_FREQ); 1194 break; 1195 case 'm': 1196 dump_sl(""); 1197 printf("Primary Display:\n"); 1198 get_mode(&m, 0); 1199 dump_mode(" ", &m); 1200 printf("\n"); 1201 printf("Secondary Display:\n"); 1202 get_mode(&m, 1); 1203 dump_mode(" ", &m); 1204 printf("\n"); 1205 dump_scaling(); 1206 printf("\n"); 1207 dump_lvds(); 1208 printf("\n"); 1209 break; 1210 case 'r': 1211 parse_ioreg(®, &index, optarg); 1212 printf("%03x.%02x = 0x%02x\n", reg, index, 1213 readb_idx_reg(reg, index)); 1214 break; 1215 case 'w': 1216 parse_ioreg(®, &index, optarg); 1217 /* we need one extra argument */ 1218 if (argc <= optind) 1219 exit(1); 1220 val = strtoul(argv[optind], NULL, 16); 1221 if (val > 0xff) 1222 exit(1); 1223 writeb_idx_reg(reg, index, val); 1224 printf("%03x.%02x = 0x%02x\n", reg, index, 1225 readb_idx_reg(reg, index)); 1226 break; 1227 case 'g': 1228 printf("GPIO State\n"); 1229 get_gpio_state(&gs); 1230 dump_gpio_state(" ", &gs); 1231 printf("\n"); 1232 break; 1233 default: 1234 usage(); 1235 exit(1); 1236 } 1237 } 1238 1239 exit(0); 1240} 1241