Home | History | Annotate | Line # | Download | only in src
      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 #ifdef HAVE_DEV_WSCONS_WSCONSIO_H
     37 #include <sys/time.h>
     38 #include <sys/ioctl.h>
     39 #include <dev/wscons/wsconsio.h>
     40 #endif
     41 
     42 #include "xf86.h"
     43 #include "xf86Modes.h"
     44 #include "xf86Priv.h"
     45 #include "xf86Privstr.h"
     46 
     47 #ifdef HAVE_XEXTPROTO_71
     48 #include "X11/extensions/dpmsconst.h"
     49 #else
     50 #define DPMS_SERVER
     51 #include "X11/extensions/dpms.h"
     52 #endif
     53 
     54 #include "r128.h"
     55 #include "r128_probe.h"
     56 #include "r128_reg.h"
     57 
     58 static void R128ConnectorFindMonitor(ScrnInfoPtr pScrn, xf86OutputPtr output);
     59 
     60 /* Define DAC registers for the requested video mode. */
     61 static void
     62 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 */
     75 void 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 
     84 static 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 
     98 static void r128_save(xf86OutputPtr output)
     99 {
    100 }
    101 
    102 static void r128_restore(xf86OutputPtr output)
    103 {
    104 }
    105 
    106 static int r128_mode_valid(xf86OutputPtr output, DisplayModePtr mode)
    107 {
    108     return MODE_OK;
    109 }
    110 
    111 static Bool r128_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
    112 {
    113     return TRUE;
    114 }
    115 
    116 static void r128_mode_prepare(xf86OutputPtr output)
    117 {
    118     r128_dpms(output, DPMSModeOff);
    119 }
    120 
    121 static 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 
    150 static void r128_mode_commit(xf86OutputPtr output)
    151 {
    152     r128_dpms(output, DPMSModeOn);
    153 }
    154 
    155 static 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 
    184 static DisplayModePtr r128_get_modes(xf86OutputPtr output)
    185 {
    186     DisplayModePtr modes;
    187     modes = R128ProbeOutputModes(output);
    188     return modes;
    189 }
    190 
    191 static void r128_destroy(xf86OutputPtr output)
    192 {
    193     if (output->driver_private)
    194         free(output->driver_private);
    195 }
    196 
    197 static 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 
    211 void 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 WSDISPLAYIO_PARAM_BACKLIGHT
    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 
    251 void 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 WSDISPLAYIO_PARAM_BACKLIGHT
    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 
    289 static 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 WSDISPLAYIO_GET_EDID
    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(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 
    357 static 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 
    367 DisplayModePtr 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 
    408 static 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 
    415 static 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 
    429 static 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 
    444 static 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 
    467 static void
    468 R128GetConnectorInfoFromBIOS(ScrnInfoPtr pScrn, R128OutputType *otypes)
    469 {
    470     R128InfoPtr info = R128PTR(pScrn);
    471     uint16_t bios_header, offset;
    472     uint32_t i;
    473 
    474     for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) {
    475         otypes[i] = OUTPUT_NONE;
    476     }
    477 
    478     /* non-x86 platform */
    479     if (!info->VBIOS) {
    480         if (info->isDFP) {
    481             /* XXX assume LVDS on mobility chips */
    482             otypes[0] = OUTPUT_LVDS;
    483             otypes[1] = OUTPUT_VGA;
    484         } else {
    485             otypes[0] = OUTPUT_VGA;
    486         }
    487         return;
    488     }
    489 
    490     bios_header = R128_BIOS16(0x48);
    491     offset = R128_BIOS16(bios_header + 0x40);
    492     if (offset) {
    493         otypes[0] = OUTPUT_LVDS;
    494         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    495                     "Found FP table, assuming FP connector.\n");
    496     } else {
    497         bios_header = R128_BIOS16(0x48);
    498         offset = R128_BIOS16(bios_header + 0x34);
    499         if (offset) {
    500             otypes[0] = OUTPUT_DVI;
    501             xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    502                         "Found DVI table, assuming DVI connector.\n");
    503         }
    504     }
    505 
    506     offset = R128_BIOS16(bios_header + 0x2e);
    507     if (offset) {
    508         if (otypes[0] == OUTPUT_NONE) {
    509             otypes[0] = OUTPUT_VGA;
    510         } else {
    511             otypes[1] = OUTPUT_VGA;
    512         }
    513 
    514         xf86DrvMsg(pScrn->scrnIndex, X_INFO,
    515                     "Found CRT table, assuming VGA connector.\n");
    516     }
    517 }
    518 
    519 Bool R128SetupConnectors(ScrnInfoPtr pScrn)
    520 {
    521     R128InfoPtr info    = R128PTR(pScrn);
    522     R128EntPtr pR128Ent = R128EntPriv(pScrn);
    523 
    524     R128OutputType otypes[R128_MAX_BIOS_CONNECTOR];
    525     xf86OutputPtr  output;
    526     int num_vga = 0;
    527     int num_dvi = 0;
    528     int i;
    529 
    530     R128GetConnectorInfoFromBIOS(pScrn, otypes);
    531 
    532     for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) {
    533         if (otypes[i] == OUTPUT_VGA)
    534             num_vga++;
    535         else if (otypes[i] == OUTPUT_DVI)
    536             num_dvi++;
    537     }
    538 
    539     for (i = 0; i < R128_MAX_BIOS_CONNECTOR; i++) {
    540         if (otypes[i] == OUTPUT_NONE) continue;
    541 
    542         R128I2CBusRec i2c;
    543         R128OutputPrivatePtr r128_output;
    544 
    545         r128_output = XNFcallocarray(1, sizeof(R128OutputPrivateRec));
    546         if (!r128_output) return FALSE;
    547 
    548         r128_output->MonType = MT_UNKNOWN;
    549         r128_output->type = otypes[i];
    550         r128_output->num = i;
    551 
    552         if (otypes[i] == OUTPUT_LVDS) {
    553             output = R128OutputCreate(pScrn, "LVDS", 0);
    554         } else if (otypes[i] == OUTPUT_VGA) {
    555             output = R128OutputCreate(pScrn, "VGA-%d", --num_vga);
    556         } else {
    557             output = R128OutputCreate(pScrn, "DVI-%d", --num_dvi);
    558         }
    559 
    560         if (!output) return FALSE;
    561         output->interlaceAllowed = TRUE;
    562         output->doubleScanAllowed = TRUE;
    563         output->driver_private = r128_output;
    564         output->possible_clones = 0;
    565         if (otypes[i] == OUTPUT_LVDS || !pR128Ent->HasCRTC2)
    566             output->possible_crtcs = 1;
    567         else
    568             output->possible_crtcs = 2;
    569 
    570         if (otypes[i] != OUTPUT_LVDS && info->DDC) {
    571             i2c.ddc_reg      = R128_GPIO_MONID;
    572             if (otypes[i] == OUTPUT_VGA && !pR128Ent->HasCRTC2) {
    573                 i2c.put_clk_mask = R128_GPIO_MONID_EN_2;
    574                 i2c.get_clk_mask = R128_GPIO_MONID_Y_2;
    575             } else {
    576                 i2c.put_clk_mask = R128_GPIO_MONID_EN_3;
    577                 i2c.get_clk_mask = R128_GPIO_MONID_Y_3;
    578             }
    579             if (otypes[i] == OUTPUT_VGA) {
    580                 i2c.put_data_mask = R128_GPIO_MONID_EN_1;
    581                 i2c.get_data_mask = R128_GPIO_MONID_Y_1;
    582             } else {
    583                 i2c.put_data_mask = R128_GPIO_MONID_EN_0;
    584                 i2c.get_data_mask = R128_GPIO_MONID_Y_0;
    585             }
    586             r128_output->ddc_i2c = i2c;
    587             R128I2CInit(output, &r128_output->pI2CBus, output->name);
    588         }
    589 
    590         if (otypes[i] == OUTPUT_LVDS)
    591             R128GetPanelInfoFromBIOS(output);
    592     }
    593 
    594     return TRUE;
    595 }
    596