18b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol/*
28b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Copyright (c) 2014 Intel Corporation 
38b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
48b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Licensed under the Apache License, Version 2.0 (the "License");
58b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// you may not use this file except in compliance with the License.
68b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// You may obtain a copy of the License at
78b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
88b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//      http://www.apache.org/licenses/LICENSE-2.0
98b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol//
108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// Unless required by applicable law or agreed to in writing, software
118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// distributed under the License is distributed on an "AS IS" BASIS,
128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// See the License for the specific language governing permissions and
148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// limitations under the License.
158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol*/
168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <fcntl.h>
178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <errno.h>
188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <HwcTrace.h>
198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <IDisplayDevice.h>
208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <DrmConfig.h>
218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <Drm.h>
228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <Hwcomposer.h>
238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace android {
258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace intel {
268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolDrm::Drm()
288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    : mDrmFd(0),
298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mLock(),
308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mInitialized(false)
318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    memset(&mOutputs, 0, sizeof(mOutputs));
338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolDrm::~Drm()
368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    WARN_IF_NOT_DEINIT();
388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::initialize()
418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mInitialized) {
438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("Drm object has been initialized");
448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    const char *path = DrmConfig::getDrmPath();
488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mDrmFd = open(path, O_RDWR, 0);
498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mDrmFd < 0) {
508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to open Drm, error: %s", strerror(errno));
518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DTRACE("mDrmFd = %d", mDrmFd);
548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    memset(&mOutputs, 0, sizeof(mOutputs));
568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mInitialized = true;
578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid Drm::deinitialize()
618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < OUTPUT_MAX; i++) {
638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        resetOutput(i);
648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mDrmFd) {
678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        close(mDrmFd);
688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mDrmFd = 0;
698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mInitialized = false;
718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::detect(int device)
748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    RETURN_FALSE_IF_NOT_INIT();
768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0 ) {
808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    resetOutput(outputIndex);
848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // get drm resources
868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeResPtr resources = drmModeGetResources(mDrmFd);
878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!resources) {
888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("fail to get drm resources, error: %s", strerror(errno));
898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeConnectorPtr connector = NULL;
938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output = &mOutputs[outputIndex];
948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    bool ret = false;
958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // find connector for the given device
978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < resources->count_connectors; i++) {
988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!resources->connectors || !resources->connectors[i]) {
998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ETRACE("fail to get drm resources connectors, error: %s", strerror(errno));
1008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            continue;
1018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        connector = drmModeGetConnector(mDrmFd, resources->connectors[i]);
1048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!connector) {
1058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ETRACE("drmModeGetConnector failed");
1068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            continue;
1078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (connector->connector_type != DrmConfig::getDrmConnector(device)) {
1108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            drmModeFreeConnector(connector);
1118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            continue;
1128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (connector->connection != DRM_MODE_CONNECTED) {
1158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("device %d is not connected", device);
1168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            drmModeFreeConnector(connector);
1178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ret = true;
1188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
1198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->connector = connector;
1228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->connected = true;
1238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // get proper encoder for the given connector
1258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (connector->encoder_id) {
1268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("Drm connector has encoder attached on device %d", device);
1278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id);
1288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            if (!output->encoder) {
1298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                ETRACE("failed to get encoder from a known encoder id");
1308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                // fall through to get an encoder
1318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
1328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!output->encoder) {
1348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("getting encoder for device %d", device);
1358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            drmModeEncoderPtr encoder;
1368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            for (int j = 0; j < resources->count_encoders; j++) {
1378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (!resources->encoders || !resources->encoders[j]) {
1388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    ETRACE("fail to get drm resources encoders, error: %s", strerror(errno));
1398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    continue;
1408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]);
1438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (!encoder) {
1448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    ETRACE("drmModeGetEncoder failed");
1458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    continue;
1468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) {
1488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    output->encoder = encoder;
1498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    break;
1508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                drmModeFreeEncoder(encoder);
1528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                encoder = NULL;
1538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
1548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!output->encoder) {
1568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ETRACE("failed to get drm encoder");
1578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
1588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // get an attached crtc or spare crtc
1618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (output->encoder->crtc_id) {
1628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("Drm encoder has crtc attached on device %d", device);
1638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id);
1648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            if (!output->crtc) {
1658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                ETRACE("failed to get crtc from a known crtc id");
1668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                // fall through to get a spare crtc
1678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
1688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!output->crtc) {
1708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("getting crtc for device %d", device);
1718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            drmModeCrtcPtr crtc;
1728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            for (int j = 0; j < resources->count_crtcs; j++) {
1738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (!resources->crtcs || !resources->crtcs[j]) {
1748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    ETRACE("fail to get drm resources crtcs, error: %s", strerror(errno));
1758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    continue;
1768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]);
1798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (!crtc) {
1808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    ETRACE("drmModeGetCrtc failed");
1818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    continue;
1828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                if (crtc->buffer_id == 0) {
1848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    output->crtc = crtc;
1858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                    break;
1868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                }
1878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                drmModeFreeCrtc(crtc);
1888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
1898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!output->crtc) {
1918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ETRACE("failed to get drm crtc");
1928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
1938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // current mode
1968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (output->crtc->mode_valid) {
1978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("mode is valid, kernel mode settings");
1988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo));
1998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ret = true;
2008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        } else {
2018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("mode is invalid, setting preferred mode");
2028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ret = initDrmMode(outputIndex);
2038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (outputIndex == OUTPUT_PRIMARY) {
2068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) {
2078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                ETRACE("failed to get device %d orientation", device);
2088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                output->panelOrientation = PANEL_ORIENTATION_0;
2098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
2108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        } else {
2118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            output->panelOrientation = PANEL_ORIENTATION_0;
2128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        break;
2148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!ret) {
2178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) {
2188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            // a fatal failure on primary device
2198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            // non fatal on secondary device
2208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            WTRACE("device %d is disabled?", device);
2218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ret = true;
2228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol         resetOutput(outputIndex);
2248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else if (output->connected) {
2258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ITRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh);
2268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeFreeResources(resources);
2298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return ret;
2308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::isSameDrmMode(drmModeModeInfoPtr value,
2338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeModeInfoPtr base) const
2348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (base->hdisplay == value->hdisplay &&
2368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        base->vdisplay == value->vdisplay &&
2378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        base->vrefresh == value->vrefresh &&
2388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        (base->flags & value->flags) == value->flags) {
2398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        VTRACE("Drm mode is not changed");
2408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
2418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return false;
2448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::setDrmMode(int device, drmModeModeInfo& value)
2478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    RETURN_FALSE_IF_NOT_INIT();
2498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
2508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (device != IDisplayDevice::DEVICE_EXTERNAL) {
2528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("Setting mode on invalid device %d", device);
2538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
2548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
2578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0 ) {
2588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid device");
2598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
2608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
2638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!output->connected) {
2648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
2658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
2668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connector->count_modes <= 0) {
2698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid count of modes");
2708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
2718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfoPtr mode;
2748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int index = 0;
2758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < output->connector->count_modes; i++) {
2768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode = &output->connector->modes[i];
2778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
2788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            index = i;
2798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (isSameDrmMode(&value, mode)) {
2818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            index = i;
2828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
2838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mode = &output->connector->modes[index];
2878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return setDrmMode(outputIndex, mode);
2888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::setRefreshRate(int device, int hz)
2918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    RETURN_FALSE_IF_NOT_INIT();
2938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
2948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (device != IDisplayDevice::DEVICE_EXTERNAL) {
2968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("Setting mode on invalid device %d", device);
2978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
2988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
3018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0 ) {
3028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid device");
3038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
3078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!output->connected) {
3088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
3098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connector->count_modes <= 0) {
3138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid count of modes");
3148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfoPtr mode;
3188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int index = 0;
3198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < output->connector->count_modes; i++) {
3208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode = &output->connector->modes[i];
3218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
3228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            index = i;
3238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
3248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (mode->hdisplay == output->mode.hdisplay &&
3258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mode->vdisplay == output->mode.vdisplay &&
3268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mode->vrefresh == (uint32_t)hz) {
3278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            index = i;
3288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
3298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
3308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mode = &output->connector->modes[index];
3338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return setDrmMode(outputIndex, mode);
3348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::writeReadIoctl(unsigned long cmd, void *data,
3378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                           unsigned long size)
3388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
3398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int err;
3408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mDrmFd <= 0) {
3428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("drm is not initialized");
3438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!data || !size) {
3478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid parameters");
3488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    err = drmCommandWriteRead(mDrmFd, cmd, data, size);
3528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (err) {
3538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("failed to call %ld ioctl with failure %d", cmd, err);
3548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
3588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::writeIoctl(unsigned long cmd, void *data,
3618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                       unsigned long size)
3628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
3638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int err;
3648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mDrmFd <= 0) {
3668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("drm is not initialized");
3678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!data || !size) {
3718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid parameters");
3728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    err = drmCommandWrite(mDrmFd, cmd, data, size);
3768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (err) {
3778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("failed to call %ld ioctl with failure %d", cmd, err);
3788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
3828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::readIoctl(unsigned long cmd, void *data,
3868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                       unsigned long size)
3878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
3888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int err;
3898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mDrmFd <= 0) {
3918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("drm is not initialized");
3928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!data || !size) {
3968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid parameters");
3978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    err = drmCommandRead(mDrmFd, cmd, data, size);
4018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (err) {
4028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("failed to call %ld ioctl with failure %d", cmd, err);
4038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
4078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
4088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolint Drm::getDrmFd() const
4118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
4128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return mDrmFd;
4138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
4148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::getModeInfo(int device, drmModeModeInfo& mode)
4168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
4178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
4188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
4208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0 ) {
4218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
4258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connected == false) {
4268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
4278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) {
4318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid width or height");
4328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    memcpy(&mode, &output->mode, sizeof(drmModeModeInfo));
4368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
4378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
4388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height)
4408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
4418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
4428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
4448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0 ) {
4458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
4498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connected == false) {
4508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
4518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    width = output->connector->mmWidth;
4558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    height = output->connector->mmHeight;
4568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
4578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
4588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::isConnected(int device)
4608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
4618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
4628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int output = getOutputIndex(device);
4648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output < 0 ) {
4658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return mOutputs[output].connected;
4698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
4708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::setDpmsMode(int device, int mode)
4728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
4738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
4748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int output = getOutputIndex(device);
4768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output < 0 ) {
4778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF &&
4818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY &&
4828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mode != IDisplayDevice::DEVICE_DISPLAY_ON) {
4838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid mode %d", mode);
4848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *out = &mOutputs[output];
4888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!out->connected) {
4898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
4908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
4918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
4928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
4938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModePropertyPtr props;
4948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < out->connector->count_props; i++) {
4958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        props = drmModeGetProperty(mDrmFd, out->connector->props[i]);
4968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (!props) {
4978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            continue;
4988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
4998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (strcmp(props->name, "DPMS") == 0) {
5018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            int ret = drmModeConnectorSetProperty(
5028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                mDrmFd,
5038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                out->connector->connector_id,
5048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                props->prop_id,
5058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                (mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON :
5068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                        IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ?
5078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                        DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF);
5088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            drmModeFreeProperty(props);
5098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            if (ret != 0) {
5108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                ETRACE("unable to set DPMS %d", mode);
5118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                return false;
5128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            } else {
5138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                return true;
5148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            }
5158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
5168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeFreeProperty(props);
5178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return false;
5198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
5208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid Drm::resetOutput(int index)
5228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
5238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output = &mOutputs[index];
5248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    output->connected = false;
5268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    memset(&output->mode, 0, sizeof(drmModeModeInfo));
5278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connector) {
5298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeFreeConnector(output->connector);
5308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->connector = 0;
5318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->encoder) {
5338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeFreeEncoder(output->encoder);
5348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->encoder = 0;
5358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->crtc) {
5378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeFreeCrtc(output->crtc);
5388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->crtc = 0;
5398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->fbId) {
5418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeRmFB(mDrmFd, output->fbId);
5428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->fbId = 0;
5438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->fbHandle) {
5458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(
5468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            (buffer_handle_t)output->fbHandle);
5478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->fbHandle = 0;
5488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
5508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::initDrmMode(int outputIndex)
5528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
5538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
5548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connector->count_modes <= 0) {
5558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid count of modes");
5568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
5578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfoPtr mode;
5608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int index = 0;
5618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    for (int i = 0; i < output->connector->count_modes; i++) {
5628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode = &output->connector->modes[i];
5638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (mode->type & DRM_MODE_TYPE_PREFERRED) {
5648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            index = i;
5658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            break;
5668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
5678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return setDrmMode(outputIndex, &output->connector->modes[index]);
5708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
5718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool Drm::setDrmMode(int index, drmModeModeInfoPtr mode)
5738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
5748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output = &mOutputs[index];
5758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int oldFbId =0;
5778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    buffer_handle_t oldFbHandle = 0;
5788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfo currentMode;
5808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    memcpy(&currentMode, &output->mode, sizeof(drmModeModeInfo));
5818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (isSameDrmMode(mode, &currentMode))
5838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
5848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->fbId) {
5878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        oldFbId = output->fbId;
5888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->fbId = 0;
5898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->fbHandle) {
5928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        oldFbHandle = output->fbHandle;
5938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        output->fbHandle = 0;
5948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
5958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
5968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // allocate frame buffer
5978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int stride = 0;
5988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
5998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode->hdisplay, mode->vdisplay, &stride);
6008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->fbHandle == 0) {
6018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to allocate frame buffer");
6028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
6038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    uint32_t bo_handles[4] = {0};
6068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    uint32_t pitches[4] = {0};
6078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    uint32_t offsets[4] = {0};
6088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int ret = 0;
6098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // We use bo_handles[0] and bo_handles[1] to store buffer_handle_t
6118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // to support 32 and 64 platforms.
6128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    bo_handles[0] = ((unsigned long)(output->fbHandle)) & 0xffffffff;
6138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    bo_handles[1] = ((unsigned long)(output->fbHandle) >> 32) & 0xffffffff;
6148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    pitches[0] = stride * DrmConfig::getFrameBufferBpp() / 8;
6158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ret = drmModeAddFB2(
6178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mDrmFd,
6188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode->hdisplay,
6198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mode->vdisplay,
6208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DrmConfig::convertHalFormatToDrmFormat(DrmConfig::getFrameBufferFormat()),
6218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        bo_handles,
6228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        pitches,
6238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        offsets,
6248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        &output->fbId,
6258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        0);
6268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (ret != 0) {
6278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("drmModeAddFB2 failed, error: %d", ret);
6288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
6298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ITRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh);
6328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, output->fbId, 0, 0,
6348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol                   &output->connector->connector_id, 1, mode);
6358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (ret == 0) {
6368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        //save mode
6378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        memcpy(&output->mode, mode, sizeof(drmModeModeInfo));
6388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else {
6398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("drmModeSetCrtc failed. error: %d", ret);
6408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (oldFbId) {
6438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        drmModeRmFB(mDrmFd, oldFbId);
6448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (oldFbHandle) {
6478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer((buffer_handle_t)oldFbHandle);
6488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return ret == 0;
6518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
6528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolint Drm::getOutputIndex(int device)
6548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
6558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    switch (device) {
6568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    case IDisplayDevice::DEVICE_PRIMARY:
6578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return OUTPUT_PRIMARY;
6588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    case IDisplayDevice::DEVICE_EXTERNAL:
6598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return OUTPUT_EXTERNAL;
6608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    default:
6618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid display device");
6628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        break;
6638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return -1;
6668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
6678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolint Drm::getPanelOrientation(int device)
6698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
6708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
6718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0) {
6728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid device");
6738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return PANEL_ORIENTATION_0;
6748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
6778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connected == false) {
6788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
6798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return PANEL_ORIENTATION_0;
6808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
6818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return output->panelOrientation;
6838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
6848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs
6868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// this is needed so getActiveConfig/setActiveConfig work correctly.  It is up to the
6878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol// user space to decide what speed to send.
6888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujoldrmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount)
6898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
6908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    RETURN_NULL_IF_NOT_INIT();
6918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Mutex::Autolock _l(mLock);
6928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (modeCount != NULL)
6948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        *modeCount = 0;
6958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    else
6968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return NULL;
6978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
6988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    int outputIndex = getOutputIndex(device);
6998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (outputIndex < 0) {
7008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid device");
7018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return NULL;
7028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
7038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
7048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    DrmOutput *output= &mOutputs[outputIndex];
7058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!output->connected) {
7068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("device is not connected");
7078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return NULL;
7088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
7098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
7108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (output->connector->count_modes <= 0) {
7118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("invalid count of modes");
7128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return NULL;
7138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
7148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
7158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    *modeCount = output->connector->count_modes;
7168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return output->connector->modes;
7178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
7188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
7198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace intel
7208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace android
7218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
722