Home | History | Annotate | Download | only in base
      1 /*
      2 // Copyright(c)2014 IntelCorporation
      3 //
      4 // LicensedundertheApacheLicense,Version2.0(the"License");
      5 // youmaynotusethisfileexceptincompliancewiththeLicense.
      6 // YoumayobtainacopyoftheLicenseat
      7 //
      8 // http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software
     11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS,
     12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
     13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand
     14 // limitationsundertheLicense.
     15 */
     16 #include <fcntl.h>
     17 #include <errno.h>
     18 #include <common/utils/HwcTrace.h>
     19 #include <IDisplayDevice.h>
     20 #include <DrmConfig.h>
     21 #include <common/base/Drm.h>
     22 #include <Hwcomposer.h>
     23 
     24 namespace android {
     25 namespace intel {
     26 
     27 Drm::Drm()
     28     : mDrmFd(0),
     29       mLock(),
     30       mInitialized(false)
     31 {
     32     memset(&mOutputs, 0, sizeof(mOutputs));
     33 }
     34 
     35 Drm::~Drm()
     36 {
     37     WARN_IF_NOT_DEINIT();
     38 }
     39 
     40 bool Drm::initialize()
     41 {
     42     if (mInitialized) {
     43         WLOGTRACE("Drm object has been initialized");
     44         return true;
     45     }
     46 
     47     const char *path = DrmConfig::getDrmPath();
     48     mDrmFd = open(path, O_RDWR, 0);
     49     if (mDrmFd < 0) {
     50         ELOGTRACE("failed to open Drm, error: %s", strerror(errno));
     51         return false;
     52     }
     53     DLOGTRACE("mDrmFd = %d", mDrmFd);
     54 
     55     memset(&mOutputs, 0, sizeof(mOutputs));
     56     mInitialized = true;
     57     return true;
     58 }
     59 
     60 void Drm::deinitialize()
     61 {
     62     for (int i = 0; i < OUTPUT_MAX; i++) {
     63         resetOutput(i);
     64     }
     65 
     66     if (mDrmFd) {
     67         close(mDrmFd);
     68         mDrmFd = 0;
     69     }
     70     mInitialized = false;
     71 }
     72 
     73 bool Drm::detect(int device)
     74 {
     75     RETURN_FALSE_IF_NOT_INIT();
     76 
     77     Mutex::Autolock _l(mLock);
     78     int outputIndex = getOutputIndex(device);
     79     if (outputIndex < 0 ) {
     80         return false;
     81     }
     82 
     83     resetOutput(outputIndex);
     84 
     85     // get drm resources
     86     drmModeResPtr resources = drmModeGetResources(mDrmFd);
     87     if (!resources) {
     88         ELOGTRACE("fail to get drm resources, error: %s", strerror(errno));
     89         return false;
     90     }
     91 
     92     drmModeConnectorPtr connector = NULL;
     93     DrmOutput *output = &mOutputs[outputIndex];
     94     bool ret = false;
     95 
     96     // find connector for the given device
     97     for (int i = 0; i < resources->count_connectors; i++) {
     98         if (!resources->connectors || !resources->connectors[i]) {
     99             ELOGTRACE("fail to get drm resources connectors, error: %s", strerror(errno));
    100             continue;
    101         }
    102 
    103         connector = drmModeGetConnector(mDrmFd, resources->connectors[i]);
    104         if (!connector) {
    105             ELOGTRACE("drmModeGetConnector failed");
    106             continue;
    107         }
    108 
    109         if (connector->connector_type != DrmConfig::getDrmConnector(device)) {
    110             drmModeFreeConnector(connector);
    111             continue;
    112         }
    113 
    114         if (connector->connection != DRM_MODE_CONNECTED) {
    115             ILOGTRACE("device %d is not connected", device);
    116             drmModeFreeConnector(connector);
    117             ret = true;
    118             break;
    119         }
    120 
    121         output->connector = connector;
    122         output->connected = true;
    123 
    124         // get proper encoder for the given connector
    125         if (connector->encoder_id) {
    126             ILOGTRACE("Drm connector has encoder attached on device %d", device);
    127             output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id);
    128             if (!output->encoder) {
    129                 ELOGTRACE("failed to get encoder from a known encoder id");
    130                 // fall through to get an encoder
    131             }
    132         }
    133         if (!output->encoder) {
    134             ILOGTRACE("getting encoder for device %d", device);
    135             drmModeEncoderPtr encoder;
    136             for (int j = 0; j < resources->count_encoders; j++) {
    137                 if (!resources->encoders || !resources->encoders[j]) {
    138                     ELOGTRACE("fail to get drm resources encoders, error: %s", strerror(errno));
    139                     continue;
    140                 }
    141 
    142                 encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]);
    143                 if (!encoder) {
    144                     ELOGTRACE("drmModeGetEncoder failed");
    145                     continue;
    146                 }
    147                 if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) {
    148                     output->encoder = encoder;
    149                     break;
    150                 }
    151                 drmModeFreeEncoder(encoder);
    152                 encoder = NULL;
    153             }
    154         }
    155         if (!output->encoder) {
    156             ELOGTRACE("failed to get drm encoder");
    157             break;
    158         }
    159 
    160         // get an attached crtc or spare crtc
    161         if (output->encoder->crtc_id) {
    162             ILOGTRACE("Drm encoder has crtc attached on device %d", device);
    163             output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id);
    164             if (!output->crtc) {
    165                 ELOGTRACE("failed to get crtc from a known crtc id");
    166                 // fall through to get a spare crtc
    167             }
    168         }
    169         if (!output->crtc) {
    170             ILOGTRACE("getting crtc for device %d", device);
    171             drmModeCrtcPtr crtc;
    172             for (int j = 0; j < resources->count_crtcs; j++) {
    173                 if (!resources->crtcs || !resources->crtcs[j]) {
    174                     ELOGTRACE("fail to get drm resources crtcs, error: %s", strerror(errno));
    175                     continue;
    176                 }
    177 
    178                 crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]);
    179                 if (!crtc) {
    180                     ELOGTRACE("drmModeGetCrtc failed");
    181                     continue;
    182                 }
    183                 // check if legal crtc to the encoder
    184                 if (output->encoder->possible_crtcs & (1<<j)) {
    185                     if (crtc->buffer_id == 0) {
    186                         output->crtc = crtc;
    187                         break;
    188                     }
    189                 }
    190                 drmModeFreeCrtc(crtc);
    191             }
    192         }
    193         if (!output->crtc) {
    194             ELOGTRACE("failed to get drm crtc");
    195             break;
    196         }
    197 
    198         // current mode
    199         if (output->crtc->mode_valid) {
    200             ILOGTRACE("mode is valid, kernel mode settings");
    201             memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo));
    202             //output->fbId = output->crtc->buffer_id;
    203             ret = true;
    204         } else {
    205             ELOGTRACE("mode is invalid. Kernel mode setting is not completed");
    206             ret = false;
    207         }
    208 
    209         if (outputIndex == OUTPUT_PRIMARY) {
    210             if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) {
    211                 ELOGTRACE("failed to get device %d orientation", device);
    212                 output->panelOrientation = PANEL_ORIENTATION_0;
    213             }
    214         } else {
    215             output->panelOrientation = PANEL_ORIENTATION_0;
    216         }
    217         break;
    218     }
    219 
    220     if (!ret) {
    221         if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) {
    222             // a fatal failure on primary device
    223             // non fatal on secondary device
    224             WLOGTRACE("device %d is disabled?", device);
    225             ret = true;
    226         }
    227          resetOutput(outputIndex);
    228     } else if (output->connected) {
    229         ILOGTRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh);
    230     }
    231 
    232     drmModeFreeResources(resources);
    233     return ret;
    234 }
    235 
    236 bool Drm::isSameDrmMode(drmModeModeInfoPtr value,
    237         drmModeModeInfoPtr base) const
    238 {
    239     if (base->hdisplay == value->hdisplay &&
    240         base->vdisplay == value->vdisplay &&
    241         base->vrefresh == value->vrefresh &&
    242         (base->flags & value->flags) == value->flags) {
    243         VLOGTRACE("Drm mode is not changed");
    244         return true;
    245     }
    246 
    247     return false;
    248 }
    249 
    250 bool Drm::setDrmMode(int device, drmModeModeInfo& value)
    251 {
    252     RETURN_FALSE_IF_NOT_INIT();
    253     Mutex::Autolock _l(mLock);
    254 
    255     if (device != IDisplayDevice::DEVICE_EXTERNAL) {
    256         WLOGTRACE("Setting mode on invalid device %d", device);
    257         return false;
    258     }
    259 
    260     int outputIndex = getOutputIndex(device);
    261     if (outputIndex < 0 ) {
    262         ELOGTRACE("invalid device");
    263         return false;
    264     }
    265 
    266     DrmOutput *output= &mOutputs[outputIndex];
    267     if (!output->connected) {
    268         ELOGTRACE("device is not connected");
    269         return false;
    270     }
    271 
    272     if (output->connector->count_modes <= 0) {
    273         ELOGTRACE("invalid count of modes");
    274         return false;
    275     }
    276 
    277     drmModeModeInfoPtr mode;
    278     int index = 0;
    279     for (int i = 0; i < output->connector->count_modes; i++) {
    280         mode = &output->connector->modes[i];
    281         if (mode->type & DRM_MODE_TYPE_PREFERRED) {
    282             index = i;
    283         }
    284         if (isSameDrmMode(&value, mode)) {
    285             index = i;
    286             break;
    287         }
    288     }
    289 
    290     mode = &output->connector->modes[index];
    291     return setDrmMode(outputIndex, mode);
    292 }
    293 
    294 bool Drm::setRefreshRate(int device, int hz)
    295 {
    296     RETURN_FALSE_IF_NOT_INIT();
    297     Mutex::Autolock _l(mLock);
    298 
    299     if (device != IDisplayDevice::DEVICE_EXTERNAL) {
    300         WLOGTRACE("Setting mode on invalid device %d", device);
    301         return false;
    302     }
    303 
    304     int outputIndex = getOutputIndex(device);
    305     if (outputIndex < 0 ) {
    306         ELOGTRACE("invalid device");
    307         return false;
    308     }
    309 
    310     DrmOutput *output= &mOutputs[outputIndex];
    311     if (!output->connected) {
    312         ELOGTRACE("device is not connected");
    313         return false;
    314     }
    315 
    316     if (output->connector->count_modes <= 0) {
    317         ELOGTRACE("invalid count of modes");
    318         return false;
    319     }
    320 
    321     drmModeModeInfoPtr mode;
    322     int index = 0;
    323     for (int i = 0; i < output->connector->count_modes; i++) {
    324         mode = &output->connector->modes[i];
    325         if (mode->type & DRM_MODE_TYPE_PREFERRED) {
    326             index = i;
    327         }
    328         if (mode->hdisplay == output->mode.hdisplay &&
    329             mode->vdisplay == output->mode.vdisplay &&
    330             mode->vrefresh == (uint32_t)hz) {
    331             index = i;
    332             break;
    333         }
    334     }
    335 
    336     mode = &output->connector->modes[index];
    337     return setDrmMode(outputIndex, mode);
    338 }
    339 
    340 bool Drm::writeReadIoctl(unsigned long cmd, void *data,
    341                            unsigned long size)
    342 {
    343     int err;
    344 
    345     if (mDrmFd <= 0) {
    346         ELOGTRACE("drm is not initialized");
    347         return false;
    348     }
    349 
    350     if (!data || !size) {
    351         ELOGTRACE("invalid parameters");
    352         return false;
    353     }
    354 
    355     err = drmCommandWriteRead(mDrmFd, cmd, data, size);
    356     if (err) {
    357         WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
    358         return false;
    359     }
    360 
    361     return true;
    362 }
    363 
    364 bool Drm::writeIoctl(unsigned long cmd, void *data,
    365                        unsigned long size)
    366 {
    367     int err;
    368 
    369     if (mDrmFd <= 0) {
    370         ELOGTRACE("drm is not initialized");
    371         return false;
    372     }
    373 
    374     if (!data || !size) {
    375         ELOGTRACE("invalid parameters");
    376         return false;
    377     }
    378 
    379     err = drmCommandWrite(mDrmFd, cmd, data, size);
    380     if (err) {
    381         WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
    382         return false;
    383     }
    384 
    385     return true;
    386 }
    387 
    388 
    389 bool Drm::readIoctl(unsigned long cmd, void *data,
    390                        unsigned long size)
    391 {
    392     int err;
    393 
    394     if (mDrmFd <= 0) {
    395         ELOGTRACE("drm is not initialized");
    396         return false;
    397     }
    398 
    399     if (!data || !size) {
    400         ELOGTRACE("invalid parameters");
    401         return false;
    402     }
    403 
    404     err = drmCommandRead(mDrmFd, cmd, data, size);
    405     if (err) {
    406         WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
    407         return false;
    408     }
    409 
    410     return true;
    411 }
    412 
    413 
    414 int Drm::getDrmFd() const
    415 {
    416     return mDrmFd;
    417 }
    418 
    419 bool Drm::getModeInfo(int device, drmModeModeInfo& mode)
    420 {
    421     Mutex::Autolock _l(mLock);
    422 
    423     int outputIndex = getOutputIndex(device);
    424     if (outputIndex < 0 ) {
    425         return false;
    426     }
    427 
    428     DrmOutput *output= &mOutputs[outputIndex];
    429     if (output->connected == false) {
    430         ELOGTRACE("device is not connected");
    431         return false;
    432     }
    433 
    434     if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) {
    435         ELOGTRACE("invalid width or height");
    436         return false;
    437     }
    438 
    439     memcpy(&mode, &output->mode, sizeof(drmModeModeInfo));
    440 
    441 #ifdef INTEL_SUPPORT_HDMI_PRIMARY
    442     // FIXME: use default fb size instead of hdmi mode, because to
    443     // support hdmi primary, we cannot report dynamic mode to SF.
    444     mode.hdisplay = DEFAULT_DRM_FB_WIDTH;
    445     mode.vdisplay = DEFAULT_DRM_FB_HEIGHT;
    446 #endif
    447 
    448     return true;
    449 }
    450 
    451 bool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height)
    452 {
    453     Mutex::Autolock _l(mLock);
    454 
    455     int outputIndex = getOutputIndex(device);
    456     if (outputIndex < 0 ) {
    457         return false;
    458     }
    459 
    460     DrmOutput *output= &mOutputs[outputIndex];
    461     if (output->connected == false) {
    462         ELOGTRACE("device is not connected");
    463         return false;
    464     }
    465 
    466     width = output->connector->mmWidth;
    467     height = output->connector->mmHeight;
    468     return true;
    469 }
    470 
    471 bool Drm::getDisplayResolution(int device, uint32_t& width, uint32_t& height)
    472 {
    473     Mutex::Autolock _l(mLock);
    474 
    475     int outputIndex = getOutputIndex(device);
    476     if (outputIndex < 0) {
    477         return false;
    478     }
    479 
    480     DrmOutput *output= &mOutputs[outputIndex];
    481     if (output->connected == false) {
    482         ELOGTRACE("device is not connected");
    483         return false;
    484     }
    485 
    486     width = output->mode.hdisplay;
    487     height = output->mode.vdisplay;
    488 
    489     if (!width || !height) {
    490         ELOGTRACE("invalid width or height");
    491         return false;
    492     }
    493     return true;
    494 }
    495 
    496 bool Drm::isConnected(int device)
    497 {
    498     Mutex::Autolock _l(mLock);
    499 
    500     int output = getOutputIndex(device);
    501     if (output < 0 ) {
    502         return false;
    503     }
    504 
    505     return mOutputs[output].connected;
    506 }
    507 
    508 bool Drm::setDpmsMode(int device, int mode)
    509 {
    510     Mutex::Autolock _l(mLock);
    511 
    512     int output = getOutputIndex(device);
    513     if (output < 0 ) {
    514         return false;
    515     }
    516 
    517     if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF &&
    518             mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY &&
    519             mode != IDisplayDevice::DEVICE_DISPLAY_ON) {
    520         ELOGTRACE("invalid mode %d", mode);
    521         return false;
    522     }
    523 
    524     DrmOutput *out = &mOutputs[output];
    525     if (!out->connected) {
    526         ELOGTRACE("device is not connected");
    527         return false;
    528     }
    529 
    530     drmModePropertyPtr props;
    531     for (int i = 0; i < out->connector->count_props; i++) {
    532         props = drmModeGetProperty(mDrmFd, out->connector->props[i]);
    533         if (!props) {
    534             continue;
    535         }
    536 
    537         if (strcmp(props->name, "DPMS") == 0) {
    538             int ret = drmModeConnectorSetProperty(
    539                 mDrmFd,
    540                 out->connector->connector_id,
    541                 props->prop_id,
    542                 (mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON :
    543                         IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ?
    544                         DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF);
    545             drmModeFreeProperty(props);
    546             if (ret != 0) {
    547                 ELOGTRACE("unable to set DPMS %d", mode);
    548                 return false;
    549             } else {
    550                 return true;
    551             }
    552         }
    553         drmModeFreeProperty(props);
    554     }
    555     return false;
    556 }
    557 
    558 void Drm::resetOutput(int index)
    559 {
    560     DrmOutput *output = &mOutputs[index];
    561 
    562     output->connected = false;
    563     memset(&output->mode, 0, sizeof(drmModeModeInfo));
    564 
    565     if (output->connector) {
    566         drmModeFreeConnector(output->connector);
    567         output->connector = 0;
    568     }
    569     if (output->encoder) {
    570         drmModeFreeEncoder(output->encoder);
    571         output->encoder = 0;
    572     }
    573     if (output->crtc) {
    574         drmModeFreeCrtc(output->crtc);
    575         output->crtc = 0;
    576     }
    577     if (output->fbId) {
    578         drmModeRmFB(mDrmFd, output->fbId);
    579         output->fbId = 0;
    580     }
    581     if (output->fbHandle) {
    582         Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(output->fbHandle);
    583         output->fbHandle = 0;
    584     }
    585 }
    586 
    587 bool Drm::initDrmMode(int outputIndex)
    588 {
    589     DrmOutput *output= &mOutputs[outputIndex];
    590     if (output->connector->count_modes <= 0) {
    591         ELOGTRACE("invalid count of modes");
    592         return false;
    593     }
    594 
    595     drmModeModeInfoPtr mode;
    596     int index = 0;
    597     for (int i = 0; i < output->connector->count_modes; i++) {
    598         mode = &output->connector->modes[i];
    599         if (mode->type & DRM_MODE_TYPE_PREFERRED) {
    600             index = i;
    601             break;
    602         }
    603     }
    604 
    605     return setDrmMode(outputIndex, &output->connector->modes[index]);
    606 }
    607 
    608 bool Drm::setDrmMode(int index, drmModeModeInfoPtr mode)
    609 {
    610     DrmOutput *output = &mOutputs[index];
    611 
    612     int oldFbId = 0;
    613     int oldFbHandle = 0;
    614     // reuse current frame buffer if there is no resolution change
    615     int fbId = -1;
    616 
    617     drmModeModeInfo currentMode;
    618     memcpy(&currentMode, &output->mode, sizeof(drmModeModeInfo));
    619 
    620     if (isSameDrmMode(mode, &currentMode))
    621         return true;
    622 
    623     if (currentMode.hdisplay != mode->hdisplay ||
    624         currentMode.vdisplay != mode->vdisplay) {
    625 
    626         oldFbId = output->fbId;
    627         oldFbHandle = output->fbHandle;
    628 
    629         // allocate frame buffer
    630         int stride = 0;
    631 #ifdef INTEL_SUPPORT_HDMI_PRIMARY
    632         output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
    633             DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, &stride);
    634 #else
    635         output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
    636             mode->hdisplay, mode->vdisplay, &stride);
    637 #endif
    638         if (output->fbHandle == 0) {
    639             ELOGTRACE("failed to allocate frame buffer");
    640             return false;
    641         }
    642 
    643         int ret = 0;
    644         ret = drmModeAddFB(
    645             mDrmFd,
    646 #ifdef INTEL_SUPPORT_HDMI_PRIMARY
    647             DEFAULT_DRM_FB_WIDTH,
    648             DEFAULT_DRM_FB_HEIGHT,
    649 #else
    650             mode->hdisplay,
    651             mode->vdisplay,
    652 #endif
    653             DrmConfig::getFrameBufferDepth(),
    654             DrmConfig::getFrameBufferBpp(),
    655             stride,
    656             output->fbHandle,
    657             &output->fbId);
    658         if (ret != 0) {
    659             ELOGTRACE("drmModeAddFB failed, error: %d", ret);
    660             return false;
    661         }
    662         fbId = output->fbId;
    663     }
    664 
    665     ILOGTRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh);
    666 
    667     int ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, fbId, 0, 0,
    668                    &output->connector->connector_id, 1, mode);
    669 
    670     if (ret == 0) {
    671         //save mode
    672         memcpy(&output->mode, mode, sizeof(drmModeModeInfo));
    673     } else {
    674         ELOGTRACE("drmModeSetCrtc failed. error: %d", ret);
    675     }
    676 
    677     if (oldFbId) {
    678         drmModeRmFB(mDrmFd, oldFbId);
    679     }
    680 
    681     if (oldFbHandle) {
    682         Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(oldFbHandle);
    683     }
    684 
    685     return ret == 0;
    686 }
    687 
    688 int Drm::getOutputIndex(int device)
    689 {
    690     switch (device) {
    691     case IDisplayDevice::DEVICE_PRIMARY:
    692         return OUTPUT_PRIMARY;
    693     case IDisplayDevice::DEVICE_EXTERNAL:
    694         return OUTPUT_EXTERNAL;
    695     default:
    696         ELOGTRACE("invalid display device");
    697         break;
    698     }
    699 
    700     return -1;
    701 }
    702 
    703 int Drm::getPanelOrientation(int device)
    704 {
    705     int outputIndex = getOutputIndex(device);
    706     if (outputIndex < 0) {
    707         ELOGTRACE("invalid device");
    708         return PANEL_ORIENTATION_0;
    709     }
    710 
    711     DrmOutput *output= &mOutputs[outputIndex];
    712     if (output->connected == false) {
    713         ELOGTRACE("device is not connected");
    714         return PANEL_ORIENTATION_0;
    715     }
    716 
    717     return output->panelOrientation;
    718 }
    719 
    720 // HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs
    721 // this is needed so getActiveConfig/setActiveConfig work correctly.  It is up to the
    722 // user space to decide what speed to send.
    723 drmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount)
    724 {
    725     RETURN_NULL_IF_NOT_INIT();
    726     Mutex::Autolock _l(mLock);
    727 
    728     if (modeCount != NULL)
    729         *modeCount = 0;
    730     else
    731         return NULL;
    732 
    733     int outputIndex = getOutputIndex(device);
    734     if (outputIndex < 0) {
    735         ELOGTRACE("invalid device");
    736         return NULL;
    737     }
    738 
    739     DrmOutput *output= &mOutputs[outputIndex];
    740     if (!output->connected) {
    741         ELOGTRACE("device is not connected");
    742         return NULL;
    743     }
    744 
    745     if (output->connector->count_modes <= 0) {
    746         ELOGTRACE("invalid count of modes");
    747         return NULL;
    748     }
    749 
    750     *modeCount = output->connector->count_modes;
    751     return output->connector->modes;
    752 }
    753 
    754 } // namespace intel
    755 } // namespace android
    756 
    757