16a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu/*
2cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Copyright (c) 2014 Intel Corporation 
3cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika//
4cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Licensed under the Apache License, Version 2.0 (the "License");
5cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// you may not use this file except in compliance with the License.
6cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// You may obtain a copy of the License at
7cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika//
8cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika//      http://www.apache.org/licenses/LICENSE-2.0
9cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika//
10cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// Unless required by applicable law or agreed to in writing, software
11cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// distributed under the License is distributed on an "AS IS" BASIS,
12cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// See the License for the specific language governing permissions and
14cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika// limitations under the License.
15cd727f537d5085eec7f1b8f9c1d33922d4de75d4Prodyut Hazarika*/
166a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <fcntl.h>
176a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu#include <errno.h>
180594c42af26255fd8d3d7d39c0cb0e2da5b8841bThierry Strudel#include <common/utils/HwcTrace.h>
1965efc253a628175c7afa95c431b746ea20052794Andy Qiu#include <IDisplayDevice.h>
20877d4ac27c6fde0b89b68e7c6e352edf879b3dedAndy Qiu#include <DrmConfig.h>
210594c42af26255fd8d3d7d39c0cb0e2da5b8841bThierry Strudel#include <common/base/Drm.h>
2230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu#include <Hwcomposer.h>
236a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
246a6081a46a83da606cf21548879b37695adc7e1fAndy Qiunamespace android {
256a6081a46a83da606cf21548879b37695adc7e1fAndy Qiunamespace intel {
266a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
276a6081a46a83da606cf21548879b37695adc7e1fAndy QiuDrm::Drm()
28e2ad4c047651d4442f6a0e002290016d45e9201afu jin    : mDrmFd(0),
29e2ad4c047651d4442f6a0e002290016d45e9201afu jin      mLock(),
30e2ad4c047651d4442f6a0e002290016d45e9201afu jin      mInitialized(false)
316a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
32e2ad4c047651d4442f6a0e002290016d45e9201afu jin    memset(&mOutputs, 0, sizeof(mOutputs));
33e2ad4c047651d4442f6a0e002290016d45e9201afu jin}
34e2ad4c047651d4442f6a0e002290016d45e9201afu jin
35e2ad4c047651d4442f6a0e002290016d45e9201afu jinDrm::~Drm()
36e2ad4c047651d4442f6a0e002290016d45e9201afu jin{
37e2ad4c047651d4442f6a0e002290016d45e9201afu jin    WARN_IF_NOT_DEINIT();
38e2ad4c047651d4442f6a0e002290016d45e9201afu jin}
39e2ad4c047651d4442f6a0e002290016d45e9201afu jin
40e2ad4c047651d4442f6a0e002290016d45e9201afu jinbool Drm::initialize()
41e2ad4c047651d4442f6a0e002290016d45e9201afu jin{
42e2ad4c047651d4442f6a0e002290016d45e9201afu jin    if (mInitialized) {
434157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("Drm object has been initialized");
44e2ad4c047651d4442f6a0e002290016d45e9201afu jin        return true;
45e2ad4c047651d4442f6a0e002290016d45e9201afu jin    }
46e2ad4c047651d4442f6a0e002290016d45e9201afu jin
47877d4ac27c6fde0b89b68e7c6e352edf879b3dedAndy Qiu    const char *path = DrmConfig::getDrmPath();
48e2ad4c047651d4442f6a0e002290016d45e9201afu jin    mDrmFd = open(path, O_RDWR, 0);
49e2ad4c047651d4442f6a0e002290016d45e9201afu jin    if (mDrmFd < 0) {
504157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("failed to open Drm, error: %s", strerror(errno));
51e2ad4c047651d4442f6a0e002290016d45e9201afu jin        return false;
526a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
534157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev    DLOGTRACE("mDrmFd = %d", mDrmFd);
546a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
556a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    memset(&mOutputs, 0, sizeof(mOutputs));
56e2ad4c047651d4442f6a0e002290016d45e9201afu jin    mInitialized = true;
57e2ad4c047651d4442f6a0e002290016d45e9201afu jin    return true;
58e2ad4c047651d4442f6a0e002290016d45e9201afu jin}
596a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
60e2ad4c047651d4442f6a0e002290016d45e9201afu jinvoid Drm::deinitialize()
61e2ad4c047651d4442f6a0e002290016d45e9201afu jin{
6230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    for (int i = 0; i < OUTPUT_MAX; i++) {
6330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        resetOutput(i);
6430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
6530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
66e2ad4c047651d4442f6a0e002290016d45e9201afu jin    if (mDrmFd) {
67e2ad4c047651d4442f6a0e002290016d45e9201afu jin        close(mDrmFd);
68e2ad4c047651d4442f6a0e002290016d45e9201afu jin        mDrmFd = 0;
69e2ad4c047651d4442f6a0e002290016d45e9201afu jin    }
70e2ad4c047651d4442f6a0e002290016d45e9201afu jin    mInitialized = false;
716a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
726a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
7330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::detect(int device)
746a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
7530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    RETURN_FALSE_IF_NOT_INIT();
766a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
7730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    Mutex::Autolock _l(mLock);
7830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int outputIndex = getOutputIndex(device);
7930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (outputIndex < 0 ) {
806a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
816a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
826a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
8330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    resetOutput(outputIndex);
8430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
8530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    // get drm resources
866a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    drmModeResPtr resources = drmModeGetResources(mDrmFd);
876a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (!resources) {
884157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("fail to get drm resources, error: %s", strerror(errno));
896a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
906a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
916a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
926a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    drmModeConnectorPtr connector = NULL;
9330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output = &mOutputs[outputIndex];
9430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    bool ret = false;
956a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
9630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    // find connector for the given device
976a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    for (int i = 0; i < resources->count_connectors; i++) {
98bc1f26891639e31ef419360724e1c0af3954ae51wli        if (!resources->connectors || !resources->connectors[i]) {
994157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ELOGTRACE("fail to get drm resources connectors, error: %s", strerror(errno));
1000f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell            continue;
1010f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell        }
1020f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell
1036a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        connector = drmModeGetConnector(mDrmFd, resources->connectors[i]);
1046a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        if (!connector) {
1054157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ELOGTRACE("drmModeGetConnector failed");
1066a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu            continue;
1076a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
1086a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
10930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (connector->connector_type != DrmConfig::getDrmConnector(device)) {
11030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            drmModeFreeConnector(connector);
11130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            continue;
1126a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
1136a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
11430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (connector->connection != DRM_MODE_CONNECTED) {
1154157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("device %d is not connected", device);
116eb726af21649d79ed720bdf329e0849270995c45Andy Qiu            drmModeFreeConnector(connector);
11730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            ret = true;
11830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            break;
11930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
1206a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
121eb726af21649d79ed720bdf329e0849270995c45Andy Qiu        output->connector = connector;
12230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->connected = true;
1236a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
12430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        // get proper encoder for the given connector
12530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (connector->encoder_id) {
1264157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("Drm connector has encoder attached on device %d", device);
12730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id);
12830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            if (!output->encoder) {
1294157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                ELOGTRACE("failed to get encoder from a known encoder id");
13030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                // fall through to get an encoder
13130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            }
1326a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
13330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (!output->encoder) {
1344157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("getting encoder for device %d", device);
13530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            drmModeEncoderPtr encoder;
13630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            for (int j = 0; j < resources->count_encoders; j++) {
137bc1f26891639e31ef419360724e1c0af3954ae51wli                if (!resources->encoders || !resources->encoders[j]) {
1384157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                    ELOGTRACE("fail to get drm resources encoders, error: %s", strerror(errno));
1390f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell                    continue;
1400f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell                }
1410f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell
14230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]);
14330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                if (!encoder) {
1444157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                    ELOGTRACE("drmModeGetEncoder failed");
14530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                    continue;
14630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                }
14730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) {
14830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                    output->encoder = encoder;
14930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                    break;
15030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                }
15130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                drmModeFreeEncoder(encoder);
15230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                encoder = NULL;
15330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            }
1546a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
15530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (!output->encoder) {
1564157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ELOGTRACE("failed to get drm encoder");
15730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            break;
1586a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
1596a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
16030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        // get an attached crtc or spare crtc
16130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (output->encoder->crtc_id) {
1624157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("Drm encoder has crtc attached on device %d", device);
16330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id);
16430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            if (!output->crtc) {
1654157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                ELOGTRACE("failed to get crtc from a known crtc id");
16630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                // fall through to get a spare crtc
16730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            }
16830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
16930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (!output->crtc) {
1704157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("getting crtc for device %d", device);
17130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            drmModeCrtcPtr crtc;
17230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            for (int j = 0; j < resources->count_crtcs; j++) {
173bc1f26891639e31ef419360724e1c0af3954ae51wli                if (!resources->crtcs || !resources->crtcs[j]) {
1744157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                    ELOGTRACE("fail to get drm resources crtcs, error: %s", strerror(errno));
1750f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell                    continue;
1760f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell                }
1770f3087a3fcd76560a54aa167d2fb8b67129730baGreg Cantrell
17830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]);
17930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                if (!crtc) {
1804157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                    ELOGTRACE("drmModeGetCrtc failed");
18130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                    continue;
18230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                }
183b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                // check if legal crtc to the encoder
184b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                if (output->encoder->possible_crtcs & (1<<j)) {
185b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                    if (crtc->buffer_id == 0) {
186b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                        output->crtc = crtc;
187b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                        break;
188b55fbe96ff6c2b98374d2137c8e91c0ca357fdb2Lei Zhang                    }
18930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                }
19030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu                drmModeFreeCrtc(crtc);
19130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            }
19230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
19330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (!output->crtc) {
1944157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ELOGTRACE("failed to get drm crtc");
19530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            break;
1966a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
1976a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
19830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        // current mode
19930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (output->crtc->mode_valid) {
2004157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            ILOGTRACE("mode is valid, kernel mode settings");
20130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo));
20297ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            //output->fbId = output->crtc->buffer_id;
20330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            ret = true;
20430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        } else {
2057b871c6aa5fae82dfe062e3de5822d0b7ccb76bbAndy Qiu            ELOGTRACE("mode is invalid. Kernel mode setting is not completed");
2067b871c6aa5fae82dfe062e3de5822d0b7ccb76bbAndy Qiu            ret = false;
2076a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        }
208ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley
209ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley        if (outputIndex == OUTPUT_PRIMARY) {
210ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley            if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) {
2114157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                ELOGTRACE("failed to get device %d orientation", device);
212ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley                output->panelOrientation = PANEL_ORIENTATION_0;
213ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley            }
214ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley        } else {
215ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley            output->panelOrientation = PANEL_ORIENTATION_0;
216ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley        }
21730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        break;
21830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
2196a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
22030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (!ret) {
221486ba9a29ca00369f7f160701f3395f10e611d98Andy Qiu        if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) {
222486ba9a29ca00369f7f160701f3395f10e611d98Andy Qiu            // a fatal failure on primary device
223486ba9a29ca00369f7f160701f3395f10e611d98Andy Qiu            // non fatal on secondary device
2244157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev            WLOGTRACE("device %d is disabled?", device);
225486ba9a29ca00369f7f160701f3395f10e611d98Andy Qiu            ret = true;
226486ba9a29ca00369f7f160701f3395f10e611d98Andy Qiu        }
22730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu         resetOutput(outputIndex);
22830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    } else if (output->connected) {
2294157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ILOGTRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh);
23030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
2316a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
23230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    drmModeFreeResources(resources);
23330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return ret;
23430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu}
2356a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
23612eefae3196eaadfcef7a543878fe816c4329a49Lin Xiebool Drm::isSameDrmMode(drmModeModeInfoPtr value,
23712eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        drmModeModeInfoPtr base) const
23812eefae3196eaadfcef7a543878fe816c4329a49Lin Xie{
23912eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    if (base->hdisplay == value->hdisplay &&
24012eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        base->vdisplay == value->vdisplay &&
24112eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        base->vrefresh == value->vrefresh &&
24212eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        (base->flags & value->flags) == value->flags) {
2434157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        VLOGTRACE("Drm mode is not changed");
24412eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        return true;
24512eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    }
24612eefae3196eaadfcef7a543878fe816c4329a49Lin Xie
24712eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    return false;
24812eefae3196eaadfcef7a543878fe816c4329a49Lin Xie}
24912eefae3196eaadfcef7a543878fe816c4329a49Lin Xie
2503f1974031c88750a14adc8f2f49538837238abf9Lin Xiebool Drm::setDrmMode(int device, drmModeModeInfo& value)
25130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu{
25230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    RETURN_FALSE_IF_NOT_INIT();
25330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    Mutex::Autolock _l(mLock);
2546a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
25530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (device != IDisplayDevice::DEVICE_EXTERNAL) {
2564157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("Setting mode on invalid device %d", device);
25730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
25830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
2596a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
26030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int outputIndex = getOutputIndex(device);
26130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (outputIndex < 0 ) {
2624157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid device");
26330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
26430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
2656a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
26630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output= &mOutputs[outputIndex];
26730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (!output->connected) {
2684157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
26930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
2706a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
2716a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
27230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->connector->count_modes <= 0) {
2734157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid count of modes");
27430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
27530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
2766a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
27730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    drmModeModeInfoPtr mode;
27830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int index = 0;
27930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    for (int i = 0; i < output->connector->count_modes; i++) {
28030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        mode = &output->connector->modes[i];
28130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
28230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            index = i;
28330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
28412eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        if (isSameDrmMode(&value, mode)) {
28530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            index = i;
28630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            break;
28730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
28830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
28930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
29030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    mode = &output->connector->modes[index];
29130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return setDrmMode(outputIndex, mode);
2926a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
2936a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
294b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xiebool Drm::setRefreshRate(int device, int hz)
295b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie{
296b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    RETURN_FALSE_IF_NOT_INIT();
297b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    Mutex::Autolock _l(mLock);
298b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
299b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    if (device != IDisplayDevice::DEVICE_EXTERNAL) {
3004157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("Setting mode on invalid device %d", device);
301b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        return false;
302b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    }
303b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
304b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    int outputIndex = getOutputIndex(device);
305b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    if (outputIndex < 0 ) {
3064157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid device");
307b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        return false;
308b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    }
309b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
310b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    DrmOutput *output= &mOutputs[outputIndex];
311b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    if (!output->connected) {
3124157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
313b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        return false;
314b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    }
315b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
316b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    if (output->connector->count_modes <= 0) {
3174157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid count of modes");
318b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        return false;
319b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    }
320b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
321b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    drmModeModeInfoPtr mode;
322b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    int index = 0;
323b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    for (int i = 0; i < output->connector->count_modes; i++) {
324b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        mode = &output->connector->modes[i];
325b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
326b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie            index = i;
327b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        }
328b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        if (mode->hdisplay == output->mode.hdisplay &&
329b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie            mode->vdisplay == output->mode.vdisplay &&
330b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie            mode->vrefresh == (uint32_t)hz) {
331b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie            index = i;
332b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie            break;
333b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie        }
334b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    }
335b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie
336b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    mode = &output->connector->modes[index];
337b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie    return setDrmMode(outputIndex, mode);
338b58f29390918c0df3bd6d0731bf98daf57511b9fLin Xie}
33930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
3406a6081a46a83da606cf21548879b37695adc7e1fAndy Qiubool Drm::writeReadIoctl(unsigned long cmd, void *data,
3416a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu                           unsigned long size)
3426a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
3436a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    int err;
3446a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3456a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (mDrmFd <= 0) {
3464157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("drm is not initialized");
3476a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3486a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3496a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3506a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (!data || !size) {
3514157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid parameters");
3526a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3536a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3546a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3556a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    err = drmCommandWriteRead(mDrmFd, cmd, data, size);
3566a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (err) {
3574157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
3586a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3596a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3606a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3616a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    return true;
3626a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
3636a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3646a6081a46a83da606cf21548879b37695adc7e1fAndy Qiubool Drm::writeIoctl(unsigned long cmd, void *data,
3656a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu                       unsigned long size)
3666a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
3676a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    int err;
3686a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3696a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (mDrmFd <= 0) {
3704157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("drm is not initialized");
3716a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3726a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3736a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3746a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (!data || !size) {
3754157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid parameters");
3766a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3776a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3786a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3796a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    err = drmCommandWrite(mDrmFd, cmd, data, size);
3806a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    if (err) {
3814157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
3826a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
3836a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
3846a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
3856a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    return true;
3866a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
3876a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
388466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
389466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hubool Drm::readIoctl(unsigned long cmd, void *data,
390466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu                       unsigned long size)
391466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu{
392466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    int err;
393466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
394466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    if (mDrmFd <= 0) {
3954157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("drm is not initialized");
396466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu        return false;
397466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    }
398466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
399466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    if (!data || !size) {
4004157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid parameters");
401466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu        return false;
402466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    }
403466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
404466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    err = drmCommandRead(mDrmFd, cmd, data, size);
405466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    if (err) {
4064157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
407466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu        return false;
408466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    }
409466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
410466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu    return true;
411466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu}
412466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
413466748a6f67ce4d1ad8baa944e68a88cf3c86d26Austin Hu
4146a6081a46a83da606cf21548879b37695adc7e1fAndy Qiuint Drm::getDrmFd() const
4156a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
4166a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    return mDrmFd;
4176a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
4186a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
41930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::getModeInfo(int device, drmModeModeInfo& mode)
4204a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li{
42130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    Mutex::Autolock _l(mLock);
42230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
42330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int outputIndex = getOutputIndex(device);
42430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (outputIndex < 0 ) {
42530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
4264a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li    }
4274a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li
42830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output= &mOutputs[outputIndex];
42930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->connected == false) {
4304157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
43130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
4324a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li    }
4334a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li
43430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) {
4354157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid width or height");
43630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
4374a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li    }
4384a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li
43930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    memcpy(&mode, &output->mode, sizeof(drmModeModeInfo));
44095dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang
44195dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#ifdef INTEL_SUPPORT_HDMI_PRIMARY
44295dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang    // FIXME: use default fb size instead of hdmi mode, because to
44395dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang    // support hdmi primary, we cannot report dynamic mode to SF.
44495dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang    mode.hdisplay = DEFAULT_DRM_FB_WIDTH;
44595dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang    mode.vdisplay = DEFAULT_DRM_FB_HEIGHT;
44695dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#endif
44795dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang
44830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return true;
4494a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li}
4504a17bd5f8632806430043ab67e10c54a1406a7a2Jackie Li
45130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height)
4526a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
4536a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    Mutex::Autolock _l(mLock);
4546a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
45530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int outputIndex = getOutputIndex(device);
45630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (outputIndex < 0 ) {
45730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
45830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
45930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
46030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output= &mOutputs[outputIndex];
46130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->connected == false) {
4624157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
46330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
4646a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
4656a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
46630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    width = output->connector->mmWidth;
46730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    height = output->connector->mmHeight;
46830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return true;
4696a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
4706a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
471af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiubool Drm::getDisplayResolution(int device, uint32_t& width, uint32_t& height)
472af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu{
473af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    Mutex::Autolock _l(mLock);
474af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu
475af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    int outputIndex = getOutputIndex(device);
476af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    if (outputIndex < 0) {
477af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu        return false;
478af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    }
479af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu
480af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    DrmOutput *output= &mOutputs[outputIndex];
481af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    if (output->connected == false) {
482af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu        ELOGTRACE("device is not connected");
483af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu        return false;
484af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    }
485af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu
486af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    width = output->mode.hdisplay;
487af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    height = output->mode.vdisplay;
488af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu
489af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    if (!width || !height) {
490af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu        ELOGTRACE("invalid width or height");
491af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu        return false;
492af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    }
493af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu    return true;
494af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu}
495af3bf2227c951a59e2dcc44ab90790d247225375Andy Qiu
49630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::isConnected(int device)
4976a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu{
4986a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    Mutex::Autolock _l(mLock);
4996a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
50065efc253a628175c7afa95c431b746ea20052794Andy Qiu    int output = getOutputIndex(device);
50165efc253a628175c7afa95c431b746ea20052794Andy Qiu    if (output < 0 ) {
5026a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu        return false;
5036a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu    }
5046a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
50530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return mOutputs[output].connected;
5066a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu}
5076a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
50865efc253a628175c7afa95c431b746ea20052794Andy Qiubool Drm::setDpmsMode(int device, int mode)
50965efc253a628175c7afa95c431b746ea20052794Andy Qiu{
51065efc253a628175c7afa95c431b746ea20052794Andy Qiu    Mutex::Autolock _l(mLock);
51165efc253a628175c7afa95c431b746ea20052794Andy Qiu
512ddb9b7fce03c36a660cd633b19191d9ce23c023bAustin Hu#ifdef INTEL_SUPPORT_HDMI_PRIMARY
513ddb9b7fce03c36a660cd633b19191d9ce23c023bAustin Hu    device = IDisplayDevice::DEVICE_EXTERNAL;
514ddb9b7fce03c36a660cd633b19191d9ce23c023bAustin Hu#endif
515ddb9b7fce03c36a660cd633b19191d9ce23c023bAustin Hu
51665efc253a628175c7afa95c431b746ea20052794Andy Qiu    int output = getOutputIndex(device);
51765efc253a628175c7afa95c431b746ea20052794Andy Qiu    if (output < 0 ) {
51865efc253a628175c7afa95c431b746ea20052794Andy Qiu        return false;
51965efc253a628175c7afa95c431b746ea20052794Andy Qiu    }
52065efc253a628175c7afa95c431b746ea20052794Andy Qiu
52165efc253a628175c7afa95c431b746ea20052794Andy Qiu    if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF &&
5226c061a816e1bb454afc8d294231bc235a771d646Nie Jun            mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY &&
5236c061a816e1bb454afc8d294231bc235a771d646Nie Jun            mode != IDisplayDevice::DEVICE_DISPLAY_ON) {
5244157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid mode %d", mode);
52565efc253a628175c7afa95c431b746ea20052794Andy Qiu        return false;
52665efc253a628175c7afa95c431b746ea20052794Andy Qiu    }
52765efc253a628175c7afa95c431b746ea20052794Andy Qiu
52830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *out = &mOutputs[output];
52930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (!out->connected) {
5304157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
53165efc253a628175c7afa95c431b746ea20052794Andy Qiu        return false;
53265efc253a628175c7afa95c431b746ea20052794Andy Qiu    }
53365efc253a628175c7afa95c431b746ea20052794Andy Qiu
53465efc253a628175c7afa95c431b746ea20052794Andy Qiu    drmModePropertyPtr props;
53565efc253a628175c7afa95c431b746ea20052794Andy Qiu    for (int i = 0; i < out->connector->count_props; i++) {
53665efc253a628175c7afa95c431b746ea20052794Andy Qiu        props = drmModeGetProperty(mDrmFd, out->connector->props[i]);
53765efc253a628175c7afa95c431b746ea20052794Andy Qiu        if (!props) {
53865efc253a628175c7afa95c431b746ea20052794Andy Qiu            continue;
53965efc253a628175c7afa95c431b746ea20052794Andy Qiu        }
54065efc253a628175c7afa95c431b746ea20052794Andy Qiu
54165efc253a628175c7afa95c431b746ea20052794Andy Qiu        if (strcmp(props->name, "DPMS") == 0) {
54265efc253a628175c7afa95c431b746ea20052794Andy Qiu            int ret = drmModeConnectorSetProperty(
54365efc253a628175c7afa95c431b746ea20052794Andy Qiu                mDrmFd,
54465efc253a628175c7afa95c431b746ea20052794Andy Qiu                out->connector->connector_id,
54565efc253a628175c7afa95c431b746ea20052794Andy Qiu                props->prop_id,
5466c061a816e1bb454afc8d294231bc235a771d646Nie Jun                (mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON :
5476c061a816e1bb454afc8d294231bc235a771d646Nie Jun                        IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ?
5486c061a816e1bb454afc8d294231bc235a771d646Nie Jun                        DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF);
54965efc253a628175c7afa95c431b746ea20052794Andy Qiu            drmModeFreeProperty(props);
55065efc253a628175c7afa95c431b746ea20052794Andy Qiu            if (ret != 0) {
5514157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev                ELOGTRACE("unable to set DPMS %d", mode);
55265efc253a628175c7afa95c431b746ea20052794Andy Qiu                return false;
55365efc253a628175c7afa95c431b746ea20052794Andy Qiu            } else {
55465efc253a628175c7afa95c431b746ea20052794Andy Qiu                return true;
55565efc253a628175c7afa95c431b746ea20052794Andy Qiu            }
55665efc253a628175c7afa95c431b746ea20052794Andy Qiu        }
55765efc253a628175c7afa95c431b746ea20052794Andy Qiu        drmModeFreeProperty(props);
55865efc253a628175c7afa95c431b746ea20052794Andy Qiu    }
55965efc253a628175c7afa95c431b746ea20052794Andy Qiu    return false;
56065efc253a628175c7afa95c431b746ea20052794Andy Qiu}
56165efc253a628175c7afa95c431b746ea20052794Andy Qiu
56230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiuvoid Drm::resetOutput(int index)
56330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu{
56430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output = &mOutputs[index];
56530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
56630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    output->connected = false;
56730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    memset(&output->mode, 0, sizeof(drmModeModeInfo));
56830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
56930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->connector) {
57030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        drmModeFreeConnector(output->connector);
57130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->connector = 0;
57230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
57330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->encoder) {
57430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        drmModeFreeEncoder(output->encoder);
57530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->encoder = 0;
57630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
57730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->crtc) {
57830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        drmModeFreeCrtc(output->crtc);
57930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->crtc = 0;
58030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
58130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->fbId) {
58230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        drmModeRmFB(mDrmFd, output->fbId);
58330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->fbId = 0;
58430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
58530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->fbHandle) {
58630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(output->fbHandle);
58730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        output->fbHandle = 0;
58830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
58930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu}
59030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
59130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::initDrmMode(int outputIndex)
59230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu{
59330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output= &mOutputs[outputIndex];
59430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (output->connector->count_modes <= 0) {
5954157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid count of modes");
59630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        return false;
59730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
59830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
59930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    drmModeModeInfoPtr mode;
60030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    int index = 0;
60130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    for (int i = 0; i < output->connector->count_modes; i++) {
60230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        mode = &output->connector->modes[i];
60330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
60430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            index = i;
60530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu            break;
60630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu        }
60730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
60830c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
60930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return setDrmMode(outputIndex, &output->connector->modes[index]);
61030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu}
61130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
61230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiubool Drm::setDrmMode(int index, drmModeModeInfoPtr mode)
61330c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu{
61430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    DrmOutput *output = &mOutputs[index];
61530c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
61697ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu    int oldFbId = 0;
6172fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang    int oldFbHandle = 0;
61897ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu    // reuse current frame buffer if there is no resolution change
61997ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu    int fbId = -1;
6202fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang
62112eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    drmModeModeInfo currentMode;
62212eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    memcpy(&currentMode, &output->mode, sizeof(drmModeModeInfo));
6232fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang
62412eefae3196eaadfcef7a543878fe816c4329a49Lin Xie    if (isSameDrmMode(mode, &currentMode))
62512eefae3196eaadfcef7a543878fe816c4329a49Lin Xie        return true;
62612eefae3196eaadfcef7a543878fe816c4329a49Lin Xie
62797ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu    if (currentMode.hdisplay != mode->hdisplay ||
62897ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        currentMode.vdisplay != mode->vdisplay) {
6292fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang
63097ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        oldFbId = output->fbId;
6312fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang        oldFbHandle = output->fbHandle;
63230c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
63397ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        // allocate frame buffer
63497ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        int stride = 0;
63595dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#ifdef INTEL_SUPPORT_HDMI_PRIMARY
63697ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
63797ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, &stride);
63895dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#else
63997ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
64097ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            mode->hdisplay, mode->vdisplay, &stride);
64195dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#endif
64297ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        if (output->fbHandle == 0) {
64397ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            ELOGTRACE("failed to allocate frame buffer");
64497ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            return false;
64597ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        }
64630c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
64797ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        int ret = 0;
64897ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        ret = drmModeAddFB(
64997ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            mDrmFd,
65095dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#ifdef INTEL_SUPPORT_HDMI_PRIMARY
65197ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            DEFAULT_DRM_FB_WIDTH,
65297ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            DEFAULT_DRM_FB_HEIGHT,
65395dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#else
65497ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            mode->hdisplay,
65597ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            mode->vdisplay,
65695dd47c04c25844c759e84a1473bf9f14c2bcb7bLei Zhang#endif
65797ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            DrmConfig::getFrameBufferDepth(),
65897ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            DrmConfig::getFrameBufferBpp(),
65997ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            stride,
66097ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            output->fbHandle,
66197ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            &output->fbId);
66297ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        if (ret != 0) {
66397ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            ELOGTRACE("drmModeAddFB failed, error: %d", ret);
66497ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu            return false;
66597ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        }
66697ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu        fbId = output->fbId;
667eb726af21649d79ed720bdf329e0849270995c45Andy Qiu    }
668eb726af21649d79ed720bdf329e0849270995c45Andy Qiu
6694157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev    ILOGTRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh);
6703f1974031c88750a14adc8f2f49538837238abf9Lin Xie
67197ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu    int ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, fbId, 0, 0,
672eb726af21649d79ed720bdf329e0849270995c45Andy Qiu                   &output->connector->connector_id, 1, mode);
67397ca3dba1b7c7fc5f35961ff6e6a14ef3843aa86Andy Qiu
67430c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    if (ret == 0) {
675eb726af21649d79ed720bdf329e0849270995c45Andy Qiu        //save mode
676eb726af21649d79ed720bdf329e0849270995c45Andy Qiu        memcpy(&output->mode, mode, sizeof(drmModeModeInfo));
67730c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    } else {
6784157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("drmModeSetCrtc failed. error: %d", ret);
67930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    }
68030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
6812fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang    if (oldFbId) {
6822fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang        drmModeRmFB(mDrmFd, oldFbId);
6832fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang    }
6842fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang
6852fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang    if (oldFbHandle) {
6862fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang        Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(oldFbHandle);
6872fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang    }
6882fb3ffb8c3d9f7ef6bcc11c69339eba9609d406fShi Yang
68930c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu    return ret == 0;
69030c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu}
69130c19aca49c615368ae3bce961c431fa901e90b9Andy Qiu
69265efc253a628175c7afa95c431b746ea20052794Andy Qiuint Drm::getOutputIndex(int device)
69365efc253a628175c7afa95c431b746ea20052794Andy Qiu{
69465efc253a628175c7afa95c431b746ea20052794Andy Qiu    switch (device) {
69565efc253a628175c7afa95c431b746ea20052794Andy Qiu    case IDisplayDevice::DEVICE_PRIMARY:
69665efc253a628175c7afa95c431b746ea20052794Andy Qiu        return OUTPUT_PRIMARY;
69765efc253a628175c7afa95c431b746ea20052794Andy Qiu    case IDisplayDevice::DEVICE_EXTERNAL:
69865efc253a628175c7afa95c431b746ea20052794Andy Qiu        return OUTPUT_EXTERNAL;
69965efc253a628175c7afa95c431b746ea20052794Andy Qiu    default:
7004157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid display device");
70165efc253a628175c7afa95c431b746ea20052794Andy Qiu        break;
70265efc253a628175c7afa95c431b746ea20052794Andy Qiu    }
70365efc253a628175c7afa95c431b746ea20052794Andy Qiu
70465efc253a628175c7afa95c431b746ea20052794Andy Qiu    return -1;
70565efc253a628175c7afa95c431b746ea20052794Andy Qiu}
70665efc253a628175c7afa95c431b746ea20052794Andy Qiu
707ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanleyint Drm::getPanelOrientation(int device)
708ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley{
709ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    int outputIndex = getOutputIndex(device);
710ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    if (outputIndex < 0) {
7114157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid device");
712ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley        return PANEL_ORIENTATION_0;
713ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    }
714ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley
715ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    DrmOutput *output= &mOutputs[outputIndex];
716ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    if (output->connected == false) {
7174157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
718ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley        return PANEL_ORIENTATION_0;
719ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    }
720ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley
721ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley    return output->panelOrientation;
722ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley}
723ab302a7c5992e3668443dc9bdac481c108c20a34Lee, Stanley
724452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish// HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs
725452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish// this is needed so getActiveConfig/setActiveConfig work correctly.  It is up to the
726452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish// user space to decide what speed to send.
727452fbc109a9c585737bcac18f19aff40574c3d79Jim BishdrmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount)
728452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish{
729452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    RETURN_NULL_IF_NOT_INIT();
730452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    Mutex::Autolock _l(mLock);
731452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish
732452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    if (modeCount != NULL)
733452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish        *modeCount = 0;
734452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    else
735452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish        return NULL;
736452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish
737452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    int outputIndex = getOutputIndex(device);
738452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    if (outputIndex < 0) {
7394157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid device");
740452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish        return NULL;
741452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    }
742452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish
743452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    DrmOutput *output= &mOutputs[outputIndex];
744452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    if (!output->connected) {
7454157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("device is not connected");
746452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish        return NULL;
747452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    }
748452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish
749452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    if (output->connector->count_modes <= 0) {
7504157ee3f6fb20e0a249b9eedc06f3b16785ba31bIliyan Malchev        ELOGTRACE("invalid count of modes");
751452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish        return NULL;
752452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    }
753452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish
754452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    *modeCount = output->connector->count_modes;
755452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish    return output->connector->modes;
756452fbc109a9c585737bcac18f19aff40574c3d79Jim Bish}
75765efc253a628175c7afa95c431b746ea20052794Andy Qiu
7586a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} // namespace intel
7596a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu} // namespace android
7606a6081a46a83da606cf21548879b37695adc7e1fAndy Qiu
761