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
178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <HwcTrace.h>
188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <Drm.h>
198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <DrmConfig.h>
208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <Hwcomposer.h>
218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol#include <ExternalDevice.h>
228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace android {
248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolnamespace intel {
258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolExternalDevice::ExternalDevice(Hwcomposer& hwc, DeviceControlFactory* controlFactory)
278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    : PhysicalDevice(DEVICE_EXTERNAL, hwc, controlFactory),
288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mHdcpControl(NULL),
298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mAbortModeSettingCond(),
308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mPendingDrmMode(),
318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mHotplugEventPending(false),
328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol      mExpectedRefreshRate(0)
338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    CTRACE();
358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin PujolExternalDevice::~ExternalDevice()
388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    CTRACE();
408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool ExternalDevice::initialize()
438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!PhysicalDevice::initialize()) {
458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DEINIT_AND_RETURN_FALSE("failed to initialize physical device");
468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHdcpControl = mControlFactory->createHdcpControl();
498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mHdcpControl) {
508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DEINIT_AND_RETURN_FALSE("failed to create HDCP control");
518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHotplugEventPending = false;
548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mConnected) {
558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHdcpControl->startHdcpAsync(HdcpLinkStatusListener, this);
568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    UeventObserver *observer = Hwcomposer::getInstance().getUeventObserver();
598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (observer) {
608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        observer->registerListener(
618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            DrmConfig::getHotplugString(),
628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            hotplugEventListener,
638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            this);
648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else {
658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("Uevent observer is NULL");
668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::deinitialize()
718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // abort mode settings if it is in the middle
738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mAbortModeSettingCond.signal();
748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mThread.get()) {
758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread->join();
768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread = NULL;
778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mHdcpControl) {
808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHdcpControl->stopHdcp();
818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        delete mHdcpControl;
828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHdcpControl = 0;
838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHotplugEventPending = false;
868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    PhysicalDevice::deinitialize();
878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool ExternalDevice::setDrmMode(drmModeModeInfo& value)
908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mConnected) {
928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("external device is not connected");
938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mThread.get()) {
978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread->join();
988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mThread = NULL;
998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Drm *drm = Hwcomposer::getInstance().getDrm();
1028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfo mode;
1038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drm->getModeInfo(mType, mode);
1048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (drm->isSameDrmMode(&value, &mode))
1058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
1068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // any issue here by faking connection status?
1088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mConnected = false;
1098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mPendingDrmMode = value;
1108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // setting mode in a working thread
1128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mThread = new ModeSettingThread(this);
1138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mThread.get()) {
1148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to create mode settings thread");
1158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
1168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mThread->run("ModeSettingsThread", PRIORITY_URGENT_DISPLAY);
1198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
1208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool ExternalDevice::threadLoop()
1238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
1248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // one-time execution
1258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    setDrmMode();
1268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return false;
1278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::setDrmMode()
1308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
1318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ITRACE("start mode setting...");
1328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Drm *drm = Hwcomposer::getInstance().getDrm();
1348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mConnected = false;
1368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHwc.hotplug(mType, false);
1378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    {
1398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        Mutex::Autolock lock(mLock);
1408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // TODO: make timeout value flexible, or wait until surface flinger
1418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        // acknowledges hot unplug event.
1428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        status_t err = mAbortModeSettingCond.waitRelative(mLock, milliseconds(20));
1438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (err != -ETIMEDOUT) {
1448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ITRACE("Mode settings is interrupted");
1458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mHwc.hotplug(mType, true);
1468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            return;
1478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
1488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // TODO: potential threading issue with onHotplug callback
1518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHdcpControl->stopHdcp();
1528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!drm->setDrmMode(mType, mPendingDrmMode)) {
1538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to set Drm mode");
1548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.hotplug(mType, true);
1558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
1568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!PhysicalDevice::updateDisplayConfigs()) {
1598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to update display configs");
1608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.hotplug(mType, true);
1618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
1628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mConnected = true;
1648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHotplugEventPending = true;
1658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // delay sending hotplug event until HDCP is authenticated
1668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mHdcpControl->startHdcpAsync(HdcpLinkStatusListener, this) == false) {
1678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("startHdcpAsync() failed; HDCP is not enabled");
1688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHotplugEventPending = false;
1698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.hotplug(mType, true);
1708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mExpectedRefreshRate = 0;
1728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::HdcpLinkStatusListener(bool success, void *userData)
1768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
1778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (userData == NULL) {
1788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
1798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ExternalDevice *p = (ExternalDevice*)userData;
1828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    p->HdcpLinkStatusListener(success);
1838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
1848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::HdcpLinkStatusListener(bool success)
1868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
1878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!success) {
1888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("HDCP is not authenticated, disabling dynamic vsync");
1898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.getVsyncManager()->enableDynamicVsync(false);
1908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mHotplugEventPending) {
1938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DTRACE("HDCP authentication status %d, sending hotplug event...", success);
1948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.hotplug(mType, mConnected);
1958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHotplugEventPending = false;
1968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
1978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
1988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (success) {
1998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ITRACE("HDCP authenticated, enabling dynamic vsync");
2008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.getVsyncManager()->enableDynamicVsync(true);
2018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::hotplugEventListener(void *data)
2058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ExternalDevice *pThis = (ExternalDevice*)data;
2078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (pThis) {
2088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        pThis->hotplugListener();
2098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::hotplugListener()
2138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    bool ret;
2158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    CTRACE();
2178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // abort mode settings if it is in the middle
2198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mAbortModeSettingCond.signal();
2208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // remember the current connection status before detection
2228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    bool connected = mConnected;
2238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // detect display configs
2258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ret = detectDisplayConfigs();
2268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (ret == false) {
2278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ETRACE("failed to detect display config");
2288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ITRACE("hotpug event: %d", mConnected);
2328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (connected == mConnected) {
2348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("same connection status detected, hotplug event ignored");
2358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mConnected == false) {
2398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHotplugEventPending = false;
2408b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.getVsyncManager()->resetVsyncSource();
2418b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHdcpControl->stopHdcp();
2428b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHwc.hotplug(mType, mConnected);
2438b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else {
2448b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DTRACE("start HDCP asynchronously...");
2458b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol         // delay sending hotplug event till HDCP is authenticated.
2468b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mHotplugEventPending = true;
2478b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ret = mHdcpControl->startHdcpAsync(HdcpLinkStatusListener, this);
2488b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (ret == false) {
2498b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            ETRACE("failed to start HDCP");
2508b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mHotplugEventPending = false;
2518b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mHwc.hotplug(mType, mConnected);
2528b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        }
2538b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2548b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mActiveDisplayConfig = 0;
2558b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2568b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2578b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolint ExternalDevice::getRefreshRate()
2588b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2598b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Drm *drm = Hwcomposer::getInstance().getDrm();
2608b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfo mode;
2618b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!drm->getModeInfo(IDisplayDevice::DEVICE_EXTERNAL, mode))
2628b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return 0;
2638b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return mode.vrefresh;
2648b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
2658b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2668b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolvoid ExternalDevice::setRefreshRate(int hz)
2678b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
2688b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    RETURN_VOID_IF_NOT_INIT();
2698b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2708b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ITRACE("setting refresh rate to %d", hz);
2718b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2728b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mBlank) {
2738b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        WTRACE("external device is blank");
2748b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2758b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2768b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2778b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    Drm *drm = Hwcomposer::getInstance().getDrm();
2788b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drmModeModeInfo mode;
2798b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!drm->getModeInfo(IDisplayDevice::DEVICE_EXTERNAL, mode))
2808b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2818b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2828b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (hz == 0 && (mode.type & DRM_MODE_TYPE_PREFERRED))
2838b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2848b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2858b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (hz == (int)mode.vrefresh)
2868b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2878b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2888b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (mExpectedRefreshRate != 0 &&
2898b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            mExpectedRefreshRate == hz && mHotplugEventPending) {
2908b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        ITRACE("Ignore a new refresh setting event because there is a same event is handling");
2918b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return;
2928b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
2938b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mExpectedRefreshRate = hz;
2948b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2958b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    ITRACE("changing refresh rate from %d to %d", mode.vrefresh, hz);
2968b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2978b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHwc.getVsyncManager()->enableDynamicVsync(false);
2988b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
2998b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHdcpControl->stopHdcp();
3008b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3018b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    drm->setRefreshRate(IDisplayDevice::DEVICE_EXTERNAL, hz);
3028b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3038b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHotplugEventPending = false;
3048b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHdcpControl->startHdcpAsync(HdcpLinkStatusListener, this);
3058b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    mHwc.getVsyncManager()->enableDynamicVsync(true);
3068b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3078b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3088b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolint ExternalDevice::getActiveConfig()
3098b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
3108b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mConnected) {
3118b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return 0;
3128b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3138b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return mActiveDisplayConfig;
3148b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3158b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3168b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujolbool ExternalDevice::setActiveConfig(int index)
3178b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol{
3188b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (!mConnected) {
3198b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        if (index == 0)
3208b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            return true;
3218b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        else
3228b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol            return false;
3238b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3248b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3258b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // for now we will only permit the frequency change.  In the future
3268b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    // we may need to set mode as well.
3278b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    if (index >= 0 && index < static_cast<int>(mDisplayConfigs.size())) {
3288b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        DisplayConfig *config = mDisplayConfigs.itemAt(index);
3298b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        setRefreshRate(config->getRefreshRate());
3308b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        mActiveDisplayConfig = index;
3318b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return true;
3328b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    } else {
3338b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol        return false;
3348b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    }
3358b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol    return true;
3368b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol}
3378b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol
3388b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace intel
3398b0063f7f46289983bd1bf9ca61662b4a2ddf5b6Benjamin Pujol} // namespace android
340