1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include "drm_driver.h" 16fb299fa2Sopenharmony_ci#include <cstdio> 17fb299fa2Sopenharmony_ci#include <unistd.h> 18fb299fa2Sopenharmony_ci#include "log/log.h" 19fb299fa2Sopenharmony_ci#include "securec.h" 20fb299fa2Sopenharmony_ci#include "ui_rotation.h" 21fb299fa2Sopenharmony_ci#include "updater_ui_const.h" 22fb299fa2Sopenharmony_ci 23fb299fa2Sopenharmony_cinamespace Updater { 24fb299fa2Sopenharmony_civoid DrmDriver::Flip(const uint8_t *buf) 25fb299fa2Sopenharmony_ci{ 26fb299fa2Sopenharmony_ci if (buff_.vaddr != MAP_FAILED) { 27fb299fa2Sopenharmony_ci UiRotation::GetInstance().RotateBuffer(buf, buff_.vaddr, buff_.size); 28fb299fa2Sopenharmony_ci } 29fb299fa2Sopenharmony_ci} 30fb299fa2Sopenharmony_ci 31fb299fa2Sopenharmony_civoid DrmDriver::Blank(bool blank) 32fb299fa2Sopenharmony_ci{ 33fb299fa2Sopenharmony_ci LOG(INFO) << "drm blank"; 34fb299fa2Sopenharmony_ci} 35fb299fa2Sopenharmony_ci 36fb299fa2Sopenharmony_civoid DrmDriver::Exit(void) 37fb299fa2Sopenharmony_ci{ 38fb299fa2Sopenharmony_ci ModesetDestroyFb(&buff_); 39fb299fa2Sopenharmony_ci} 40fb299fa2Sopenharmony_ci 41fb299fa2Sopenharmony_civoid DrmDriver::GetGrSurface(GrSurface &surface) 42fb299fa2Sopenharmony_ci{ 43fb299fa2Sopenharmony_ci surface.width = static_cast<int>(buff_.width); 44fb299fa2Sopenharmony_ci surface.height = static_cast<int>(buff_.height); 45fb299fa2Sopenharmony_ci surface.rowBytes = 0; 46fb299fa2Sopenharmony_ci surface.pixelBytes = 0; 47fb299fa2Sopenharmony_ci} 48fb299fa2Sopenharmony_ci 49fb299fa2Sopenharmony_ciint DrmDriver::ModesetCreateFb(struct BufferObject *bo) 50fb299fa2Sopenharmony_ci{ 51fb299fa2Sopenharmony_ci struct drm_mode_create_dumb create = {}; 52fb299fa2Sopenharmony_ci struct drm_mode_map_dumb map = {}; 53fb299fa2Sopenharmony_ci const int offsetNumber = 4; 54fb299fa2Sopenharmony_ci uint32_t handles[offsetNumber] = {0}; 55fb299fa2Sopenharmony_ci uint32_t pitches[offsetNumber] = {0}; 56fb299fa2Sopenharmony_ci uint32_t offsets[offsetNumber] = {0}; 57fb299fa2Sopenharmony_ci 58fb299fa2Sopenharmony_ci /* create a dumb-buffer, the pixel format is XRGB888 */ 59fb299fa2Sopenharmony_ci const int pixelDepth = 32; 60fb299fa2Sopenharmony_ci create.width = bo->width; 61fb299fa2Sopenharmony_ci create.height = bo->height; 62fb299fa2Sopenharmony_ci create.bpp = pixelDepth; 63fb299fa2Sopenharmony_ci drmIoctl(fd_, DRM_IOCTL_MODE_CREATE_DUMB, &create); 64fb299fa2Sopenharmony_ci 65fb299fa2Sopenharmony_ci /* bind the dumb-buffer to an FB object */ 66fb299fa2Sopenharmony_ci bo->pitch = create.pitch; 67fb299fa2Sopenharmony_ci bo->size = create.size; 68fb299fa2Sopenharmony_ci bo->handle = create.handle; 69fb299fa2Sopenharmony_ci 70fb299fa2Sopenharmony_ci handles[0] = bo->handle; 71fb299fa2Sopenharmony_ci pitches[0] = bo->pitch; 72fb299fa2Sopenharmony_ci offsets[0] = 0; 73fb299fa2Sopenharmony_ci int ret = drmModeAddFB2(fd_, bo->width, bo->height, DRM_FORMAT_ARGB8888, handles, pitches, offsets, &bo->fbId, 0); 74fb299fa2Sopenharmony_ci if (ret) { 75fb299fa2Sopenharmony_ci LOG(ERROR) << "[fbtest]failed to add fb (" << bo->width << "x" << bo->height << "): " << strerror(errno); 76fb299fa2Sopenharmony_ci return -1; 77fb299fa2Sopenharmony_ci } 78fb299fa2Sopenharmony_ci 79fb299fa2Sopenharmony_ci /* map the dumb-buffer to userspace */ 80fb299fa2Sopenharmony_ci map.handle = create.handle; 81fb299fa2Sopenharmony_ci drmIoctl(fd_, DRM_IOCTL_MODE_MAP_DUMB, &map); 82fb299fa2Sopenharmony_ci bo->vaddr = static_cast<uint8_t *>(mmap(0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, map.offset)); 83fb299fa2Sopenharmony_ci if (bo->vaddr == MAP_FAILED) { 84fb299fa2Sopenharmony_ci LOG(ERROR) << "failed to mmap framebuffer"; 85fb299fa2Sopenharmony_ci return -1; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci const uint32_t newColor = 0xff000000; 88fb299fa2Sopenharmony_ci uint32_t i = 0; 89fb299fa2Sopenharmony_ci uint32_t color = newColor; 90fb299fa2Sopenharmony_ci while (i < bo->size) { 91fb299fa2Sopenharmony_ci if (memcpy_s(&bo->vaddr[i], bo->size, &color, sizeof(color)) != EOK) { 92fb299fa2Sopenharmony_ci return -1; 93fb299fa2Sopenharmony_ci } 94fb299fa2Sopenharmony_ci i += sizeof(color); 95fb299fa2Sopenharmony_ci } 96fb299fa2Sopenharmony_ci return 0; 97fb299fa2Sopenharmony_ci} 98fb299fa2Sopenharmony_ci 99fb299fa2Sopenharmony_cidrmModeCrtc *DrmDriver::GetCrtc(const drmModeRes &res, const int fd, const drmModeConnector &conn) const 100fb299fa2Sopenharmony_ci{ 101fb299fa2Sopenharmony_ci // if connector has one encoder, use it 102fb299fa2Sopenharmony_ci drmModeEncoder *encoder = nullptr; 103fb299fa2Sopenharmony_ci if (conn.encoder_id != 0) { 104fb299fa2Sopenharmony_ci encoder = drmModeGetEncoder(fd, conn.encoder_id); 105fb299fa2Sopenharmony_ci } 106fb299fa2Sopenharmony_ci if (encoder != nullptr && encoder->crtc_id != 0) { 107fb299fa2Sopenharmony_ci uint32_t crtcId = encoder->crtc_id; 108fb299fa2Sopenharmony_ci drmModeFreeEncoder(encoder); 109fb299fa2Sopenharmony_ci return drmModeGetCrtc(fd, crtcId); 110fb299fa2Sopenharmony_ci } 111fb299fa2Sopenharmony_ci 112fb299fa2Sopenharmony_ci if (encoder != nullptr) { 113fb299fa2Sopenharmony_ci drmModeFreeEncoder(encoder); 114fb299fa2Sopenharmony_ci } 115fb299fa2Sopenharmony_ci 116fb299fa2Sopenharmony_ci // try get a vaild encoder and crtc 117fb299fa2Sopenharmony_ci for (int i = 0; i < conn.count_encoders; i++) { 118fb299fa2Sopenharmony_ci encoder = drmModeGetEncoder(fd, conn.encoders[i]); 119fb299fa2Sopenharmony_ci if (encoder == nullptr) { 120fb299fa2Sopenharmony_ci continue; 121fb299fa2Sopenharmony_ci } 122fb299fa2Sopenharmony_ci 123fb299fa2Sopenharmony_ci for (int j = 0; j < res.count_crtcs; j++) { 124fb299fa2Sopenharmony_ci if ((encoder->possible_crtcs & (1u << static_cast<uint32_t>(j))) != 0) { 125fb299fa2Sopenharmony_ci drmModeFreeEncoder(encoder); 126fb299fa2Sopenharmony_ci return drmModeGetCrtc(fd, res.crtcs[j]); 127fb299fa2Sopenharmony_ci } 128fb299fa2Sopenharmony_ci } 129fb299fa2Sopenharmony_ci drmModeFreeEncoder(encoder); 130fb299fa2Sopenharmony_ci } 131fb299fa2Sopenharmony_ci return nullptr; 132fb299fa2Sopenharmony_ci} 133fb299fa2Sopenharmony_ci 134fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetFirstConnector(const drmModeRes &res, const int fd) const 135fb299fa2Sopenharmony_ci{ 136fb299fa2Sopenharmony_ci // get connected connector 137fb299fa2Sopenharmony_ci for (int i = 0; i < res.count_connectors; i++) { 138fb299fa2Sopenharmony_ci drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]); 139fb299fa2Sopenharmony_ci if (conn == nullptr) { 140fb299fa2Sopenharmony_ci continue; 141fb299fa2Sopenharmony_ci } 142fb299fa2Sopenharmony_ci if (conn->count_modes > 0 && 143fb299fa2Sopenharmony_ci conn->connection == DRM_MODE_CONNECTED) { 144fb299fa2Sopenharmony_ci return conn; 145fb299fa2Sopenharmony_ci } 146fb299fa2Sopenharmony_ci drmModeFreeConnector(conn); 147fb299fa2Sopenharmony_ci } 148fb299fa2Sopenharmony_ci return nullptr; 149fb299fa2Sopenharmony_ci} 150fb299fa2Sopenharmony_ci 151fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetConnectorByType(const drmModeRes &res, const int fd, const uint32_t type) const 152fb299fa2Sopenharmony_ci{ 153fb299fa2Sopenharmony_ci // get connected connector 154fb299fa2Sopenharmony_ci for (int i = 0; i < res.count_connectors; i++) { 155fb299fa2Sopenharmony_ci drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]); 156fb299fa2Sopenharmony_ci if (conn == nullptr) { 157fb299fa2Sopenharmony_ci continue; 158fb299fa2Sopenharmony_ci } 159fb299fa2Sopenharmony_ci if (conn->connector_type == type && 160fb299fa2Sopenharmony_ci conn->count_modes > 0 && 161fb299fa2Sopenharmony_ci conn->connection == DRM_MODE_CONNECTED) { 162fb299fa2Sopenharmony_ci return conn; 163fb299fa2Sopenharmony_ci } 164fb299fa2Sopenharmony_ci drmModeFreeConnector(conn); 165fb299fa2Sopenharmony_ci } 166fb299fa2Sopenharmony_ci return nullptr; 167fb299fa2Sopenharmony_ci} 168fb299fa2Sopenharmony_ci 169fb299fa2Sopenharmony_ci 170fb299fa2Sopenharmony_cidrmModeConnector *DrmDriver::GetConnector(const drmModeRes &res, const int fd, uint32_t &modeId) const 171fb299fa2Sopenharmony_ci{ 172fb299fa2Sopenharmony_ci // get main connector : lvds edp and dsi 173fb299fa2Sopenharmony_ci uint32_t mainConnector[] = { 174fb299fa2Sopenharmony_ci DRM_MODE_CONNECTOR_LVDS, 175fb299fa2Sopenharmony_ci DRM_MODE_CONNECTOR_eDP, 176fb299fa2Sopenharmony_ci DRM_MODE_CONNECTOR_DSI, 177fb299fa2Sopenharmony_ci }; 178fb299fa2Sopenharmony_ci 179fb299fa2Sopenharmony_ci drmModeConnector *conn = nullptr; 180fb299fa2Sopenharmony_ci for (uint32_t i = 0; i < sizeof(mainConnector) / sizeof(mainConnector[0]); i++) { 181fb299fa2Sopenharmony_ci conn = GetConnectorByType(res, fd, mainConnector[i]); 182fb299fa2Sopenharmony_ci if (conn != nullptr) { 183fb299fa2Sopenharmony_ci break; 184fb299fa2Sopenharmony_ci } 185fb299fa2Sopenharmony_ci } 186fb299fa2Sopenharmony_ci 187fb299fa2Sopenharmony_ci if (conn == nullptr) { 188fb299fa2Sopenharmony_ci conn = GetFirstConnector(res, fd); 189fb299fa2Sopenharmony_ci } 190fb299fa2Sopenharmony_ci 191fb299fa2Sopenharmony_ci if (conn == nullptr) { 192fb299fa2Sopenharmony_ci LOG(ERROR) << "DrmDriver cannot get vaild connector"; 193fb299fa2Sopenharmony_ci return nullptr; 194fb299fa2Sopenharmony_ci } 195fb299fa2Sopenharmony_ci 196fb299fa2Sopenharmony_ci // get preferred mode index 197fb299fa2Sopenharmony_ci modeId = 0; 198fb299fa2Sopenharmony_ci for (int i = 0; i < conn->count_modes; i++) { 199fb299fa2Sopenharmony_ci if ((conn->modes[i].type & DRM_MODE_TYPE_PREFERRED) != 0) { 200fb299fa2Sopenharmony_ci modeId = static_cast<uint32_t>(i); 201fb299fa2Sopenharmony_ci break; 202fb299fa2Sopenharmony_ci } 203fb299fa2Sopenharmony_ci } 204fb299fa2Sopenharmony_ci 205fb299fa2Sopenharmony_ci return conn; 206fb299fa2Sopenharmony_ci} 207fb299fa2Sopenharmony_ci 208fb299fa2Sopenharmony_cidrmModeRes *DrmDriver::GetResources(int &fd) const 209fb299fa2Sopenharmony_ci{ 210fb299fa2Sopenharmony_ci // 1: open drm resource 211fb299fa2Sopenharmony_ci drmModeRes *res = nullptr; 212fb299fa2Sopenharmony_ci for (int i = 0; i < DRM_MAX_MINOR; i++) { 213fb299fa2Sopenharmony_ci res = GetOneResources(i, fd); 214fb299fa2Sopenharmony_ci if (res != nullptr) { 215fb299fa2Sopenharmony_ci break; 216fb299fa2Sopenharmony_ci } 217fb299fa2Sopenharmony_ci } 218fb299fa2Sopenharmony_ci return res; 219fb299fa2Sopenharmony_ci} 220fb299fa2Sopenharmony_ci 221fb299fa2Sopenharmony_cidrmModeRes *DrmDriver::GetOneResources(const int devIndex, int &fd) const 222fb299fa2Sopenharmony_ci{ 223fb299fa2Sopenharmony_ci // 1: open drm device 224fb299fa2Sopenharmony_ci fd = -1; 225fb299fa2Sopenharmony_ci std::string devName = std::string("/dev/dri/card") + std::to_string(devIndex); 226fb299fa2Sopenharmony_ci int tmpFd = open(devName.c_str(), O_RDWR | O_CLOEXEC); 227fb299fa2Sopenharmony_ci if (tmpFd < 0) { 228fb299fa2Sopenharmony_ci LOG(ERROR) << "open failed " << devName; 229fb299fa2Sopenharmony_ci return nullptr; 230fb299fa2Sopenharmony_ci } 231fb299fa2Sopenharmony_ci // 2: check drm capacity 232fb299fa2Sopenharmony_ci uint64_t cap = 0; 233fb299fa2Sopenharmony_ci int ret = drmGetCap(tmpFd, DRM_CAP_DUMB_BUFFER, &cap); 234fb299fa2Sopenharmony_ci if (ret != 0 || cap == 0) { 235fb299fa2Sopenharmony_ci LOG(ERROR) << "drmGetCap failed"; 236fb299fa2Sopenharmony_ci close(tmpFd); 237fb299fa2Sopenharmony_ci return nullptr; 238fb299fa2Sopenharmony_ci } 239fb299fa2Sopenharmony_ci 240fb299fa2Sopenharmony_ci // 3: get drm resources 241fb299fa2Sopenharmony_ci drmModeRes *res = drmModeGetResources(tmpFd); 242fb299fa2Sopenharmony_ci if (res == nullptr) { 243fb299fa2Sopenharmony_ci LOG(ERROR) << "drmModeGetResources failed"; 244fb299fa2Sopenharmony_ci close(tmpFd); 245fb299fa2Sopenharmony_ci return nullptr; 246fb299fa2Sopenharmony_ci } 247fb299fa2Sopenharmony_ci 248fb299fa2Sopenharmony_ci // 4: check it has connected connector and crtc 249fb299fa2Sopenharmony_ci if (res->count_crtcs > 0 && res->count_connectors > 0 && res->count_encoders > 0) { 250fb299fa2Sopenharmony_ci drmModeConnector *conn = GetFirstConnector(*res, tmpFd); 251fb299fa2Sopenharmony_ci if (conn != nullptr) { 252fb299fa2Sopenharmony_ci // don't close fd 253fb299fa2Sopenharmony_ci LOG(INFO) << "drm dev:" << devName; 254fb299fa2Sopenharmony_ci drmModeFreeConnector(conn); 255fb299fa2Sopenharmony_ci fd = tmpFd; 256fb299fa2Sopenharmony_ci return res; 257fb299fa2Sopenharmony_ci } 258fb299fa2Sopenharmony_ci } 259fb299fa2Sopenharmony_ci close(tmpFd); 260fb299fa2Sopenharmony_ci drmModeFreeResources(res); 261fb299fa2Sopenharmony_ci return nullptr; 262fb299fa2Sopenharmony_ci} 263fb299fa2Sopenharmony_ci 264fb299fa2Sopenharmony_ciint DrmDriver::DrmInit(void) 265fb299fa2Sopenharmony_ci{ 266fb299fa2Sopenharmony_ci // 1: open drm resource 267fb299fa2Sopenharmony_ci res_ = GetResources(fd_); 268fb299fa2Sopenharmony_ci if (fd_ < 0 || res_ == nullptr) { 269fb299fa2Sopenharmony_ci LOG(ERROR) << "DrmInit: GetResources failed"; 270fb299fa2Sopenharmony_ci return -1; 271fb299fa2Sopenharmony_ci } 272fb299fa2Sopenharmony_ci 273fb299fa2Sopenharmony_ci // 2 : get connected connector 274fb299fa2Sopenharmony_ci uint32_t modeId; 275fb299fa2Sopenharmony_ci conn_ = GetConnector(*res_, fd_, modeId); 276fb299fa2Sopenharmony_ci if (conn_ == nullptr) { 277fb299fa2Sopenharmony_ci LOG(ERROR) << "DrmInit: GetConnector failed"; 278fb299fa2Sopenharmony_ci return -1; 279fb299fa2Sopenharmony_ci } 280fb299fa2Sopenharmony_ci 281fb299fa2Sopenharmony_ci // 3: get vaild encoder and crtc 282fb299fa2Sopenharmony_ci crtc_ = GetCrtc(*res_, fd_, *conn_); 283fb299fa2Sopenharmony_ci if (crtc_ == nullptr) { 284fb299fa2Sopenharmony_ci LOG(ERROR) << "DrmInit: GetCrtc failed"; 285fb299fa2Sopenharmony_ci return -1; 286fb299fa2Sopenharmony_ci } 287fb299fa2Sopenharmony_ci 288fb299fa2Sopenharmony_ci // 4: create userspace buffer 289fb299fa2Sopenharmony_ci buff_.width = conn_->modes[modeId].hdisplay; 290fb299fa2Sopenharmony_ci buff_.height = conn_->modes[modeId].vdisplay; 291fb299fa2Sopenharmony_ci ModesetCreateFb(&buff_); 292fb299fa2Sopenharmony_ci 293fb299fa2Sopenharmony_ci // 5: bind ctrc and connector 294fb299fa2Sopenharmony_ci drmModeSetCrtc(fd_, crtc_->crtc_id, buff_.fbId, 0, 0, &conn_->connector_id, 1, &conn_->modes[modeId]); 295fb299fa2Sopenharmony_ci LOG(INFO) << "DrmInit: buff_.width:" << buff_.width << " buff_.height:" << buff_.height; 296fb299fa2Sopenharmony_ci LOG(INFO) << "DrmInit: crtc_id:" << crtc_->crtc_id << " connector_id:" << conn_->connector_id; 297fb299fa2Sopenharmony_ci LOG(INFO) << " drm init success."; 298fb299fa2Sopenharmony_ci return 0; 299fb299fa2Sopenharmony_ci} 300fb299fa2Sopenharmony_ci 301fb299fa2Sopenharmony_cibool DrmDriver::Init() 302fb299fa2Sopenharmony_ci{ 303fb299fa2Sopenharmony_ci // this static variable can guarantee Init be called only once 304fb299fa2Sopenharmony_ci static bool res = [this] () { 305fb299fa2Sopenharmony_ci if (DrmInit() == -1) { 306fb299fa2Sopenharmony_ci LOG(ERROR) << "load drm driver fail"; 307fb299fa2Sopenharmony_ci return false; 308fb299fa2Sopenharmony_ci } 309fb299fa2Sopenharmony_ci return true; 310fb299fa2Sopenharmony_ci } (); 311fb299fa2Sopenharmony_ci return res; 312fb299fa2Sopenharmony_ci} 313fb299fa2Sopenharmony_ci 314fb299fa2Sopenharmony_civoid DrmDriver::ModesetDestroyFb(struct BufferObject *bo) 315fb299fa2Sopenharmony_ci{ 316fb299fa2Sopenharmony_ci if (fd_ > 0 && bo->fbId != 0) { 317fb299fa2Sopenharmony_ci drmModeRmFB(fd_, bo->fbId); 318fb299fa2Sopenharmony_ci } 319fb299fa2Sopenharmony_ci if (bo->vaddr != MAP_FAILED) { 320fb299fa2Sopenharmony_ci munmap(bo->vaddr, bo->size); 321fb299fa2Sopenharmony_ci } 322fb299fa2Sopenharmony_ci if (fd_ > 0) { 323fb299fa2Sopenharmony_ci struct drm_mode_destroy_dumb destroy = {}; 324fb299fa2Sopenharmony_ci destroy.handle = bo->handle; 325fb299fa2Sopenharmony_ci drmIoctl(fd_, DRM_IOCTL_GEM_CLOSE, &destroy); 326fb299fa2Sopenharmony_ci } 327fb299fa2Sopenharmony_ci if (crtc_ != nullptr) { 328fb299fa2Sopenharmony_ci drmModeFreeCrtc(crtc_); 329fb299fa2Sopenharmony_ci } 330fb299fa2Sopenharmony_ci if (conn_ != nullptr) { 331fb299fa2Sopenharmony_ci drmModeFreeConnector(conn_); 332fb299fa2Sopenharmony_ci } 333fb299fa2Sopenharmony_ci if (res_ != nullptr) { 334fb299fa2Sopenharmony_ci drmModeFreeResources(res_); 335fb299fa2Sopenharmony_ci } 336fb299fa2Sopenharmony_ci if (fd_ > 0) { 337fb299fa2Sopenharmony_ci close(fd_); 338fb299fa2Sopenharmony_ci fd_ = -1; 339fb299fa2Sopenharmony_ci } 340fb299fa2Sopenharmony_ci} 341fb299fa2Sopenharmony_ci 342fb299fa2Sopenharmony_ciDrmDriver::~DrmDriver() 343fb299fa2Sopenharmony_ci{ 344fb299fa2Sopenharmony_ci ModesetDestroyFb(&buff_); 345fb299fa2Sopenharmony_ci} 346fb299fa2Sopenharmony_ci} // namespace Updater 347