r128_output.c revision 4303943b
1/* 2 * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and 3 * VA Linux Systems Inc., Fremont, California. 4 * 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation on the rights to use, copy, modify, merge, 11 * publish, distribute, sublicense, and/or sell copies of the Software, 12 * and to permit persons to whom the Software is furnished to do so, 13 * subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR 23 * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include <string.h> 34#include <stdio.h> 35 36#include "xf86.h" 37#include "xf86Modes.h" 38 39#ifdef HAVE_XEXTPROTO_71 40#include "X11/extensions/dpmsconst.h" 41#else 42#define DPMS_SERVER 43#include "X11/extensions/dpms.h" 44#endif 45 46#include "r128.h" 47#include "r128_probe.h" 48#include "r128_reg.h" 49#include "xf86Priv.h" 50#include "xf86Privstr.h" 51 52#ifdef __NetBSD__ 53#include <sys/time.h> 54#include <sys/ioctl.h> 55#include <dev/wscons/wsconsio.h> 56#endif 57 58 59static void R128ConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output); 60 61/* Define DAC registers for the requested video mode. */ 62void R128InitDACRegisters(R128SavePtr orig, R128SavePtr save, xf86OutputPtr output) 63{ 64 ScrnInfoPtr pScrn = output->scrn; 65 R128InfoPtr info = R128PTR(pScrn); 66 xf86CrtcPtr crtc = output->crtc; 67 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 68 69 save->dac_cntl = (R128_DAC_MASK_ALL | R128_DAC_VGA_ADR_EN | 70 (!r128_crtc->crtc_id ? 0 : R128_DAC_CRT_SEL_CRTC2) | 71 (info->dac6bits ? 0 : R128_DAC_8BIT_EN)); 72} 73 74/* Write DAC registers */ 75void R128RestoreDACRegisters(ScrnInfoPtr pScrn, R128SavePtr restore) 76{ 77 R128InfoPtr info = R128PTR(pScrn); 78 unsigned char *R128MMIO = info->MMIO; 79 80 OUTREGP(R128_DAC_CNTL, restore->dac_cntl, 81 R128_DAC_RANGE_CNTL | R128_DAC_BLANKING); 82} 83 84static void r128_dpms(xf86OutputPtr output, int mode) 85{ 86 switch(mode) { 87 case DPMSModeOn: 88 R128DPMSSetOn(output); 89 break; 90 case DPMSModeStandby: 91 case DPMSModeSuspend: 92 case DPMSModeOff: 93 R128DPMSSetOff(output); 94 break; 95 } 96} 97 98static void r128_save(xf86OutputPtr output) 99{ 100} 101 102static void r128_restore(xf86OutputPtr output) 103{ 104} 105 106static int r128_mode_valid(xf86OutputPtr output, DisplayModePtr mode) 107{ 108 return MODE_OK; 109} 110 111static Bool r128_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 112{ 113 return TRUE; 114} 115 116static void r128_mode_prepare(xf86OutputPtr output) 117{ 118 r128_dpms(output, DPMSModeOff); 119} 120 121static void r128_mode_set(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode) 122{ 123 ScrnInfoPtr pScrn = output->scrn; 124 R128InfoPtr info = R128PTR(pScrn); 125 R128OutputPrivatePtr r128_output = output->driver_private; 126 xf86CrtcPtr crtc = output->crtc; 127 R128CrtcPrivatePtr r128_crtc = crtc->driver_private; 128 129 if (r128_crtc->crtc_id == 0 && !info->isPro2) 130 R128InitRMXRegisters(&info->SavedReg, &info->ModeReg, output, adjusted_mode); 131 132 if (r128_output->MonType == MT_DFP) 133 R128InitFPRegisters(&info->SavedReg, &info->ModeReg, output); 134 else if (r128_output->MonType == MT_LCD) 135 R128InitLVDSRegisters(&info->SavedReg, &info->ModeReg, output); 136 else if (r128_output->MonType == MT_CRT) 137 R128InitDACRegisters(&info->SavedReg, &info->ModeReg, output); 138 139 if (r128_crtc->crtc_id == 0 && !info->isPro2) 140 R128RestoreRMXRegisters(pScrn, &info->ModeReg); 141 142 if (r128_output->MonType == MT_DFP) 143 R128RestoreFPRegisters(pScrn, &info->ModeReg); 144 else if (r128_output->MonType == MT_LCD) 145 R128RestoreLVDSRegisters(pScrn, &info->ModeReg); 146 else if (r128_output->MonType == MT_CRT) 147 R128RestoreDACRegisters(pScrn, &info->ModeReg); 148} 149 150static void r128_mode_commit(xf86OutputPtr output) 151{ 152 r128_dpms(output, DPMSModeOn); 153} 154 155static xf86OutputStatus r128_detect(xf86OutputPtr output) 156{ 157 ScrnInfoPtr pScrn = output->scrn; 158 R128OutputPrivatePtr r128_output = output->driver_private; 159 160 r128_output->MonType = MT_UNKNOWN; 161 R128ConnectorFindMonitor(pScrn, output); 162 163 if (r128_output->MonType == MT_UNKNOWN) { 164 output->subpixel_order = SubPixelUnknown; 165 return XF86OutputStatusUnknown; 166 } else if (r128_output->MonType == MT_NONE) { 167 output->subpixel_order = SubPixelUnknown; 168 return XF86OutputStatusDisconnected; 169 } else { 170 switch(r128_output->MonType) { 171 case MT_LCD: 172 case MT_DFP: 173 output->subpixel_order = SubPixelHorizontalRGB; 174 break; 175 default: 176 output->subpixel_order = SubPixelNone; 177 break; 178 } 179 180 return XF86OutputStatusConnected; 181 } 182} 183 184static DisplayModePtr r128_get_modes(xf86OutputPtr output) 185{ 186 DisplayModePtr modes; 187 modes = R128ProbeOutputModes(output); 188 return modes; 189} 190 191static void r128_destroy(xf86OutputPtr output) 192{ 193 if (output->driver_private) 194 free(output->driver_private); 195} 196 197static const xf86OutputFuncsRec r128_output_funcs = { 198 .dpms = r128_dpms, 199 .save = r128_save, 200 .restore = r128_restore, 201 .mode_valid = r128_mode_valid, 202 .mode_fixup = r128_mode_fixup, 203 .prepare = r128_mode_prepare, 204 .mode_set = r128_mode_set, 205 .commit = r128_mode_commit, 206 .detect = r128_detect, 207 .get_modes = r128_get_modes, 208 .destroy = r128_destroy, 209}; 210 211void R128DPMSSetOn(xf86OutputPtr output) 212{ 213 ScrnInfoPtr pScrn = output->scrn; 214 R128InfoPtr info = R128PTR(pScrn); 215 unsigned char *R128MMIO = info->MMIO; 216 R128OutputPrivatePtr r128_output = output->driver_private; 217 R128MonitorType MonType = r128_output->MonType; 218 R128SavePtr save = &info->ModeReg; 219 220 switch(MonType) { 221 case MT_LCD: 222#ifdef __NetBSD__ 223 if (info->HaveBacklightControl) { 224 struct wsdisplay_param p; 225 226 p.param = WSDISPLAYIO_PARAM_BACKLIGHT; 227 p.curval = 1; 228 ioctl(xf86Info.consoleFd, WSDISPLAYIO_SETPARAM, &p); 229 } else 230#endif 231 { 232 OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_BLON, ~R128_LVDS_BLON); 233 usleep(r128_output->PanelPwrDly * 1000); 234 OUTREGP(R128_LVDS_GEN_CNTL, R128_LVDS_ON, ~R128_LVDS_ON); 235 } 236 save->lvds_gen_cntl |= (R128_LVDS_ON | R128_LVDS_BLON); 237 break; 238 case MT_DFP: 239 OUTREGP(R128_FP_GEN_CNTL, (R128_FP_FPON | R128_FP_TMDS_EN), ~(R128_FP_FPON | R128_FP_TMDS_EN)); 240 save->fp_gen_cntl |= (R128_FP_FPON | R128_FP_TMDS_EN); 241 break; 242 case MT_CRT: 243 OUTREGP(R128_CRTC_EXT_CNTL, R128_CRTC_CRT_ON, ~R128_CRTC_CRT_ON); 244 save->crtc_ext_cntl |= R128_CRTC_CRT_ON; 245 break; 246 default: 247 break; 248 } 249} 250 251void R128DPMSSetOff(xf86OutputPtr output) 252{ 253 ScrnInfoPtr pScrn = output->scrn; 254 R128InfoPtr info = R128PTR(pScrn); 255 unsigned char *R128MMIO = info->MMIO; 256 R128OutputPrivatePtr r128_output = output->driver_private; 257 R128MonitorType MonType = r128_output->MonType; 258 R128SavePtr save = &info->ModeReg; 259 260 switch(MonType) { 261 case MT_LCD: 262#ifdef __NetBSD__ 263 if (info->HaveBacklightControl) { 264 struct wsdisplay_param p; 265 266 p.param = WSDISPLAYIO_PARAM_BACKLIGHT; 267 p.curval = 0; 268 ioctl(xf86Info.consoleFd, WSDISPLAYIO_SETPARAM, &p); 269 } else 270#endif 271 { 272 OUTREGP(R128_LVDS_GEN_CNTL, 0, ~(R128_LVDS_BLON | R128_LVDS_ON)); 273 } 274 save->lvds_gen_cntl &= ~(R128_LVDS_BLON | R128_LVDS_ON); 275 break; 276 case MT_DFP: 277 OUTREGP(R128_FP_GEN_CNTL, 0, ~(R128_FP_FPON | R128_FP_TMDS_EN)); 278 save->fp_gen_cntl &= ~(R128_FP_FPON | R128_FP_TMDS_EN); 279 break; 280 case MT_CRT: 281 OUTREGP(R128_CRTC_EXT_CNTL, 0, ~(R128_CRTC_CRT_ON)); 282 save->crtc_ext_cntl &= ~(R128_CRTC_CRT_ON); 283 break; 284 default: 285 break; 286 } 287} 288 289static R128MonitorType R128DisplayDDCConnected(xf86OutputPtr output) 290{ 291 ScrnInfoPtr pScrn = output->scrn; 292 R128InfoPtr info = R128PTR(pScrn); 293 R128EntPtr pR128Ent = R128EntPriv(pScrn); 294 unsigned char *R128MMIO = info->MMIO; 295 R128OutputPrivatePtr r128_output = output->driver_private; 296 297 R128MonitorType MonType = MT_NONE; 298 xf86MonPtr *MonInfo = &output->MonInfo; 299 uint32_t mask1, mask2; 300 301 if (r128_output->type == OUTPUT_LVDS) { 302#ifdef __NetBSD__ 303 if (info->HaveWSDisplay) { 304 struct wsdisplayio_edid_info ei; 305 char *buffer; 306 xf86MonPtr tmp; 307 308 buffer = malloc(1024); 309 ei.edid_data = buffer; 310 ei.buffer_size = 1024; 311 if (ioctl(xf86Info.consoleFd, WSDISPLAYIO_GET_EDID, &ei) != -1) { 312 xf86Msg(X_INFO, "got %d bytes worth of EDID from wsdisplay\n", 313 ei.data_size); 314 tmp = xf86InterpretEEDID(pScrn->scrnIndex, buffer); 315 tmp->flags |= MONITOR_EDID_COMPLETE_RAWDATA; 316 *MonInfo = tmp; 317 xf86OutputSetEDID(output, tmp); 318 } else 319 free(buffer); 320 } 321#endif 322 return MT_LCD; 323 } else if (r128_output->type == OUTPUT_VGA) { 324 mask1 = R128_GPIO_MONID_MASK_1 | (pR128Ent->HasCRTC2 ? R128_GPIO_MONID_MASK_3 : R128_GPIO_MONID_MASK_2); 325 mask2 = R128_GPIO_MONID_A_1 | (pR128Ent->HasCRTC2 ? R128_GPIO_MONID_A_3 : R128_GPIO_MONID_A_2); 326 } else { 327 mask1 = R128_GPIO_MONID_MASK_0 | R128_GPIO_MONID_MASK_3; 328 mask2 = R128_GPIO_MONID_A_0 | R128_GPIO_MONID_A_3; 329 } 330 331 if (r128_output->pI2CBus) { 332 R128I2CBusPtr pR128I2CBus = &(r128_output->ddc_i2c); 333 334 /* XXX: Radeon does something here to appease old monitors. */ 335 OUTREG(pR128I2CBus->ddc_reg, INREG(pR128I2CBus->ddc_reg) | mask1); 336 OUTREG(pR128I2CBus->ddc_reg, INREG(pR128I2CBus->ddc_reg) & ~mask2); 337 *MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), r128_output->pI2CBus); 338 } else { 339 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DDC2/I2C is not properly initialized\n"); 340 return MT_NONE; 341 } 342 343 if (*MonInfo) { 344 if (r128_output->type == OUTPUT_VGA) { 345 MonType = MT_CRT; 346 } else { 347 if ((*MonInfo)->rawData[0x14] & 0x80) 348 MonType = MT_DFP; 349 else 350 MonType = MT_CRT; 351 } 352 } 353 354 return MonType; 355} 356 357static void R128ConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output) 358{ 359 R128OutputPrivatePtr r128_output = output->driver_private; 360 361 /* XXX: We should figure out how the DAC and BIOS scratch registers work 362 * to handle the non-DDC case. */ 363 if (r128_output->MonType == MT_UNKNOWN) 364 r128_output->MonType = R128DisplayDDCConnected(output); 365} 366 367DisplayModePtr R128ProbeOutputModes(xf86OutputPtr output) 368{ 369 ScrnInfoPtr pScrn = output->scrn; 370 R128OutputPrivatePtr r128_output = output->driver_private; 371 DisplayModePtr modes = NULL; 372 DisplayModePtr mode; 373 xf86MonPtr edid_mon; 374 375 if (r128_output->pI2CBus) { 376 edid_mon = xf86OutputGetEDID(output, r128_output->pI2CBus); 377 xf86OutputSetEDID(output, edid_mon); 378 } 379 modes = xf86OutputGetEDIDModes(output); 380 381 /* Letting this function return NULL would be a bad idea. With old cards 382 * like r128, users often specify a small resolution in order to get DRI. 383 * If the X server has to guess modes, the list it comes up with includes 384 * high resolutions. 385 */ 386 if (!modes) 387 modes = xf86GetDefaultModes(); 388 389 for (mode = modes; mode != NULL; mode = mode->next) { 390 if (r128_output->type == OUTPUT_DVI) { 391 if (mode->type & (M_T_DRIVER | M_T_PREFERRED)) { 392 r128_output->PanelXRes = mode->HDisplay; 393 r128_output->PanelYRes = mode->VDisplay; 394 } 395 } 396 397 xf86SetModeCrtc(mode, INTERLACE_HALVE_V); 398 if (mode->status == MODE_OK) 399 mode->status = R128DoValidMode(output, mode, MODECHECK_FINAL); 400 } 401 402 xf86ValidateModesUserConfig(pScrn, modes); 403 xf86PruneInvalidModes(pScrn, &modes, FALSE); 404 405 return modes; 406} 407 408static xf86OutputPtr R128OutputCreate(ScrnInfoPtr pScrn, const char *name, int i) 409{ 410 char buf[32]; 411 sprintf(buf, name, i); 412 return xf86OutputCreate(pScrn, &r128_output_funcs, buf); 413} 414 415static void R128I2CGetBits(I2CBusPtr b, int *Clock, int *data) 416{ 417 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 418 R128InfoPtr info = R128PTR(pScrn); 419 unsigned long val; 420 unsigned char *R128MMIO = info->MMIO; 421 R128I2CBusPtr pR128I2CBus = b->DriverPrivate.ptr; 422 423 /* Get the result. */ 424 val = INREG(pR128I2CBus->ddc_reg); 425 *Clock = (val & pR128I2CBus->get_clk_mask) != 0; 426 *data = (val & pR128I2CBus->get_data_mask) != 0; 427} 428 429static void R128I2CPutBits(I2CBusPtr b, int Clock, int data) 430{ 431 ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex]; 432 R128InfoPtr info = R128PTR(pScrn); 433 unsigned long val; 434 unsigned char *R128MMIO = info->MMIO; 435 R128I2CBusPtr pR128I2CBus = b->DriverPrivate.ptr; 436 437 val = INREG(pR128I2CBus->ddc_reg) 438 & ~(uint32_t)(pR128I2CBus->put_clk_mask | pR128I2CBus->put_data_mask); 439 val |= (Clock ? 0 : pR128I2CBus->put_clk_mask); 440 val |= (data ? 0 : pR128I2CBus->put_data_mask); 441 OUTREG(pR128I2CBus->ddc_reg, val); 442} 443 444static Bool R128I2CInit(xf86OutputPtr output, I2CBusPtr *bus_ptr, char *name) 445{ 446 ScrnInfoPtr pScrn = output->scrn; 447 R128OutputPrivatePtr r128_output = output->driver_private; 448 R128I2CBusPtr pR128I2CBus = &(r128_output->ddc_i2c); 449 I2CBusPtr pI2CBus; 450 451 pI2CBus = xf86CreateI2CBusRec(); 452 if(!pI2CBus) return FALSE; 453 454 pI2CBus->BusName = name; 455 pI2CBus->scrnIndex = pScrn->scrnIndex; 456 pI2CBus->I2CPutBits = R128I2CPutBits; 457 pI2CBus->I2CGetBits = R128I2CGetBits; 458 pI2CBus->AcknTimeout = 5; 459 460 pI2CBus->DriverPrivate.ptr = (pointer)pR128I2CBus; 461 if (!xf86I2CBusInit(pI2CBus)) return FALSE; 462 463 *bus_ptr = pI2CBus; 464 return TRUE; 465} 466 467void R128GetConnectorInfoFromBIOS(ScrnInfoPtr pScrn, R128OutputType *otypes) 468{ 469 R128InfoPtr info = R128PTR(pScrn); 470 uint16_t bios_header, offset; 471 uint32_t i; 472 473 for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { 474 otypes[i] = OUTPUT_NONE; 475 } 476 477 /* non-x86 platform */ 478 if (!info->VBIOS) { 479 if (info->isDFP) { 480 /* XXX assume LVDS on chips that can have them */ 481 otypes[0] = OUTPUT_LVDS; 482 otypes[1] = OUTPUT_VGA; 483 } else { 484 otypes[0] = OUTPUT_VGA; 485 } 486 return; 487 } 488 489 bios_header = R128_BIOS16(0x48); 490 offset = R128_BIOS16(bios_header + 0x40); 491 if (offset) { 492 otypes[0] = OUTPUT_LVDS; 493 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 494 "Found FP table, assuming FP connector.\n"); 495 } else { 496 bios_header = R128_BIOS16(0x48); 497 offset = R128_BIOS16(bios_header + 0x34); 498 if (offset) { 499 otypes[0] = OUTPUT_DVI; 500 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 501 "Found DVI table, assuming DVI connector.\n"); 502 } 503 } 504 505 offset = R128_BIOS16(bios_header + 0x2e); 506 if (offset) { 507 if (otypes[0] == OUTPUT_NONE) { 508 otypes[0] = OUTPUT_VGA; 509 } else { 510 otypes[1] = OUTPUT_VGA; 511 } 512 513 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 514 "Found CRT table, assuming VGA connector.\n"); 515 } 516} 517 518Bool R128SetupConnectors(ScrnInfoPtr pScrn) 519{ 520 R128InfoPtr info = R128PTR(pScrn); 521 R128EntPtr pR128Ent = R128EntPriv(pScrn); 522 523 R128OutputType otypes[R128_MAX_BIOS_CONNECTOR]; 524 xf86OutputPtr output; 525 int num_vga = 0; 526 int num_dvi = 0; 527 int i; 528 529 R128GetConnectorInfoFromBIOS(pScrn, otypes); 530 531 for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { 532 if (otypes[i] == OUTPUT_VGA) 533 num_vga++; 534 else if (otypes[i] == OUTPUT_DVI) 535 num_dvi++; 536 } 537 538 for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) { 539 if (otypes[i] == OUTPUT_NONE) continue; 540 541 R128I2CBusRec i2c; 542 R128OutputPrivatePtr r128_output; 543 544 r128_output = xnfcalloc(sizeof(R128OutputPrivateRec), 1); 545 if (!r128_output) return FALSE; 546 547 r128_output->MonType = MT_UNKNOWN; 548 r128_output->type = otypes[i]; 549 r128_output->num = i; 550 551 if (otypes[i] == OUTPUT_LVDS) { 552 output = R128OutputCreate(pScrn, "LVDS", 0); 553 } else if (otypes[i] == OUTPUT_VGA) { 554 output = R128OutputCreate(pScrn, "VGA-%d", --num_vga); 555 } else { 556 output = R128OutputCreate(pScrn, "DVI-%d", --num_dvi); 557 } 558 559 if (!output) return FALSE; 560 output->interlaceAllowed = TRUE; 561 output->doubleScanAllowed = TRUE; 562 output->driver_private = r128_output; 563 output->possible_clones = 0; 564 if (otypes[i] == OUTPUT_LVDS || !pR128Ent->HasCRTC2) 565 output->possible_crtcs = 1; 566 else 567 output->possible_crtcs = 2; 568 569 if (otypes[i] != OUTPUT_LVDS && info->DDC) { 570 i2c.ddc_reg = R128_GPIO_MONID; 571 if (otypes[i] == OUTPUT_VGA && !pR128Ent->HasCRTC2) { 572 i2c.put_clk_mask = R128_GPIO_MONID_EN_2; 573 i2c.get_clk_mask = R128_GPIO_MONID_Y_2; 574 } else { 575 i2c.put_clk_mask = R128_GPIO_MONID_EN_3; 576 i2c.get_clk_mask = R128_GPIO_MONID_Y_3; 577 } 578 if (otypes[i] == OUTPUT_VGA) { 579 i2c.put_data_mask = R128_GPIO_MONID_EN_1; 580 i2c.get_data_mask = R128_GPIO_MONID_Y_1; 581 } else { 582 i2c.put_data_mask = R128_GPIO_MONID_EN_0; 583 i2c.get_data_mask = R128_GPIO_MONID_Y_0; 584 } 585 r128_output->ddc_i2c = i2c; 586 R128I2CInit(output, &r128_output->pI2CBus, output->name); 587 } 588 589 if (otypes[i] == OUTPUT_LVDS) 590 R128GetPanelInfoFromBIOS(output); 591 } 592 593 return TRUE; 594} 595