16cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel/* 26cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* Copyright (c) 2017, The Linux Foundation. All rights reserved. 36cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* 46cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* Redistribution and use in source and binary forms, with or without 56cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* modification, are permitted provided that the following conditions are 66cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* met: 76cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* * Redistributions of source code must retain the above copyright 86cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* notice, this list of conditions and the following disclaimer. 96cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* * Redistributions in binary form must reproduce the above 106cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* copyright notice, this list of conditions and the following 116cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* disclaimer in the documentation and/or other materials provided 126cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* with the distribution. 136cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* * Neither the name of The Linux Foundation nor the names of its 146cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* contributors may be used to endorse or promote products derived 156cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* from this software without specific prior written permission. 166cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* 176cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 186cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 196cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 206cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 216cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 226cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 236cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 246cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 256cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 266cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 276cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel*/ 296cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 306cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#include <errno.h> 316cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 326cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#include "drm_master.h" 336cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#include "drm_res_mgr.h" 346cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 356cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#define DEBUG 0 366cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#define __CLASS__ "DRMResMgr" 376cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 386cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelusing std::mutex; 396cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelusing std::lock_guard; 406cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 416cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelnamespace drm_utils { 426cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 436cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry StrudelDRMResMgr *DRMResMgr::s_instance = nullptr; 446cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelmutex DRMResMgr::s_lock; 456cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 466cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelstatic bool GetConnector(int dev_fd, drmModeRes *res, drmModeConnector **connector) { 476cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel for (auto i = 0; i < res->count_connectors; i++) { 486cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeConnector *conn = drmModeGetConnector(dev_fd, res->connectors[i]); 496cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (conn && conn->connector_type == DRM_MODE_CONNECTOR_DSI && conn->count_modes && 506cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel conn->connection == DRM_MODE_CONNECTED) { 516cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel *connector = conn; 526cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGI("Found connector %d", conn->connector_id); 536cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return true; 546cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 556cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 566cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 576cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return false; 586cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} 596cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 606cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelstatic bool GetEncoder(int dev_fd, drmModeConnector *conn, drmModeEncoder **encoder) { 616cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel for (auto i = 0; i < conn->count_encoders; i++) { 626cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeEncoder *enc = drmModeGetEncoder(dev_fd, conn->encoders[i]); 636cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (enc && enc->encoder_type == DRM_MODE_ENCODER_DSI) { 646cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel *encoder = enc; 656cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGI("Found encoder %d", enc->encoder_id); 666cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return true; 676cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 686cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 696cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return false; 706cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} 716cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 726cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelstatic bool GetCrtc(int dev_fd, drmModeRes *res, drmModeEncoder *enc, drmModeCrtc **crtc) { 736cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel for (auto i = 0; i < res->count_crtcs; i++) { 746cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (enc->possible_crtcs & (1 << i)) { 756cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeCrtc *c = drmModeGetCrtc(dev_fd, res->crtcs[i]); 766cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (c) { 776cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel *crtc = c; 786cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGI("Found crtc %d", c->crtc_id); 796cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return true; 806cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 816cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 826cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 836cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 846cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return false; 856cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} 866cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 876cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel#define __CLASS__ "DRMResMgr" 886cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 896cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelint DRMResMgr::GetInstance(DRMResMgr **res_mgr) { 906cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel lock_guard<mutex> obj(s_lock); 916cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 926cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (!s_instance) { 936cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel s_instance = new DRMResMgr(); 946cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (s_instance->Init() < 0) { 956cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel delete s_instance; 966cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel s_instance = nullptr; 976cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return -ENODEV; 986cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 996cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1006cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1016cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel *res_mgr = s_instance; 1026cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return 0; 1036cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} 1046cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1056cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudelint DRMResMgr::Init() { 1066cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRMMaster *master = nullptr; 1076cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel int dev_fd = -1; 1086cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1096cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel int ret = DRMMaster::GetInstance(&master); 1106cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (ret < 0) { 1116cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return ret; 1126cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1136cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1146cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel master->GetHandle(&dev_fd); 1156cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeRes *res = drmModeGetResources(dev_fd); 1166cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (res == nullptr) { 1176cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGE("drmModeGetResources failed"); 1186cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return -ENODEV; 1196cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1206cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1216cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeConnector *conn = nullptr; 1226cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (!GetConnector(dev_fd, res, &conn)) { 1236cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGE("Failed to find a connector"); 1246cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return -ENODEV; 1256cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1266cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1276cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeEncoder *enc = nullptr; 1286cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (!GetEncoder(dev_fd, conn, &enc)) { 1296cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGE("Failed to find an encoder"); 1306cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeFreeConnector(conn); 1316cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return -ENODEV; 1326cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1336cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1346cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeCrtc *crtc = nullptr; 1356cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel if (!GetCrtc(dev_fd, res, enc, &crtc)) { 1366cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel DRM_LOGE("Failed to find a crtc"); 1376cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeFreeEncoder(enc); 1386cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeFreeConnector(conn); 1396cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel drmModeFreeResources(res); 1406cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return -ENODEV; 1416cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel } 1426cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1436cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel res_ = res; 1446cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel conn_ = conn; 1456cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel enc_ = enc; 1466cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel crtc_ = crtc; 1476cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1486cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel return 0; 1496cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} 1506cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel 1516cfbcfa35e4da3a5975d9904a8caae9968acc768Thierry Strudel} // namespace drm_utils 152