blob: 84073f16665e8b64065fb67e95680193725483c6 [file] [log] [blame]
Saurabh Shah7d476ed2016-06-27 16:40:58 -07001/*
Mahesh Aiaf6956652021-08-19 07:48:22 -07002* Copyright (c) 2017 - 2018, 2021 The Linux Foundation. All rights reserved.
Saurabh Shah7d476ed2016-06-27 16:40:58 -07003*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are
6* met:
7* * Redistributions of source code must retain the above copyright
8* notice, this list of conditions and the following disclaimer.
9* * Redistributions in binary form must reproduce the above
10* copyright notice, this list of conditions and the following
11* disclaimer in the documentation and/or other materials provided
12* with the distribution.
13* * Neither the name of The Linux Foundation nor the names of its
14* contributors may be used to endorse or promote products derived
15* from this software without specific prior written permission.
16*
17* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30#include <errno.h>
31#include <fcntl.h>
32#include <sys/stat.h>
33#include <unistd.h>
34#include <xf86drm.h>
35#include <xf86drmMode.h>
Saurabh Shahfad1afd2017-01-31 12:09:59 -080036// Intentionally included after xf86 headers so that they in-turn include libdrm version of drm.h
37// that doesn't use keyword "virtual" for a variable name. Not doing so leads to the kernel version
38// of drm.h being included causing compilation to fail
39#include <drm/msm_drm.h>
Rheygine Medel99f7d1a2020-02-11 14:54:51 -080040#include <display/drm/sde_drm.h>
Saurabh Shah7d476ed2016-06-27 16:40:58 -070041#include <algorithm>
42#include <iterator>
Mahesh Aiaf6956652021-08-19 07:48:22 -070043#include <chrono>
44#include <thread>
Saurabh Shah7d476ed2016-06-27 16:40:58 -070045
46#include "drm_master.h"
47
48#define __CLASS__ "DRMMaster"
49
50using std::mutex;
51using std::lock_guard;
52using std::begin;
53using std::copy;
54using std::end;
55using std::fill;
56
57namespace drm_utils {
58
Saurabh Shah7d476ed2016-06-27 16:40:58 -070059DRMMaster *DRMMaster::s_instance = nullptr;
60mutex DRMMaster::s_lock;
61
62int DRMMaster::GetInstance(DRMMaster **master) {
63 lock_guard<mutex> obj(s_lock);
64
65 if (!s_instance) {
66 s_instance = new DRMMaster();
67 if (s_instance->Init() < 0) {
68 delete s_instance;
69 s_instance = nullptr;
70 return -ENODEV;
71 }
72 }
73
74 *master = s_instance;
75 return 0;
76}
77
Saurabh Shaha57cf162017-02-28 17:00:11 -080078void DRMMaster::DestroyInstance() {
79 lock_guard<mutex> obj(s_lock);
80 delete s_instance;
81 s_instance = nullptr;
82}
83
Saurabh Shah7d476ed2016-06-27 16:40:58 -070084int DRMMaster::Init() {
Mahesh Aiaf6956652021-08-19 07:48:22 -070085 uint8_t retry = 0;
86 do {
87 dev_fd_ = drmOpen("msm_drm", nullptr);
88 if(dev_fd_ < 0) {
Ramkumar Radhakrishnan4d96f052021-11-15 21:26:16 -080089 DRM_LOGW("drmOpen failed with error %d, retry %d", dev_fd_, retry);
Mahesh Aiaf6956652021-08-19 07:48:22 -070090 if (retry >= MAX_RETRY) {
91 return -ENODEV;
92 }
93 std::this_thread::sleep_for(std::chrono::milliseconds(100));
94 }
95 } while(dev_fd_ < 0 && retry++ < MAX_RETRY);
Saurabh Shah7d476ed2016-06-27 16:40:58 -070096
97 return 0;
98}
99
100DRMMaster::~DRMMaster() {
101 drmClose(dev_fd_);
102 dev_fd_ = -1;
103}
104
Saurabh Shahf84c4122017-04-07 10:34:40 -0700105int DRMMaster::CreateFbId(const DRMBuffer &drm_buffer, uint32_t *fb_id) {
Pullakavi Srinivas02434572021-02-28 23:46:09 +0530106 lock_guard<mutex> obj(s_lock);
Saurabh Shahf84c4122017-04-07 10:34:40 -0700107 uint32_t gem_handle = 0;
108 int ret = drmPrimeFDToHandle(dev_fd_, drm_buffer.fd, &gem_handle);
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700109 if (ret) {
Saurabh Shah66c941b2016-07-06 17:34:05 -0700110 DRM_LOGE("drmPrimeFDToHandle failed with error %d", ret);
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700111 return ret;
112 }
113
Saurabh Shahb1bdf6e2017-02-16 10:57:19 -0800114 struct drm_mode_fb_cmd2 cmd2 {};
115 cmd2.width = drm_buffer.width;
116 cmd2.height = drm_buffer.height;
117 cmd2.pixel_format = drm_buffer.drm_format;
118 cmd2.flags = DRM_MODE_FB_MODIFIERS;
Saurabh Shahf84c4122017-04-07 10:34:40 -0700119 fill(begin(cmd2.handles), begin(cmd2.handles) + drm_buffer.num_planes, gem_handle);
Saurabh Shahb1bdf6e2017-02-16 10:57:19 -0800120 copy(begin(drm_buffer.stride), end(drm_buffer.stride), begin(cmd2.pitches));
121 copy(begin(drm_buffer.offset), end(drm_buffer.offset), begin(cmd2.offsets));
122 fill(begin(cmd2.modifier), begin(cmd2.modifier) + drm_buffer.num_planes,
123 drm_buffer.drm_format_modifier);
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700124
Saurabh Shahb1bdf6e2017-02-16 10:57:19 -0800125 if ((ret = drmIoctl(dev_fd_, DRM_IOCTL_MODE_ADDFB2, &cmd2))) {
126 DRM_LOGE("DRM_IOCTL_MODE_ADDFB2 failed with error %d", ret);
Saurabh Shahf84c4122017-04-07 10:34:40 -0700127 } else {
128 *fb_id = cmd2.fb_id;
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700129 }
130
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700131 struct drm_gem_close gem_close = {};
132 gem_close.handle = gem_handle;
Saurabh Shahf84c4122017-04-07 10:34:40 -0700133 int ret1 = drmIoctl(dev_fd_, DRM_IOCTL_GEM_CLOSE, &gem_close);
134 if (ret1) {
135 DRM_LOGE("drmIoctl::DRM_IOCTL_GEM_CLOSE failed with error %d", ret1);
136 return ret1;
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700137 }
138
Saurabh Shahf84c4122017-04-07 10:34:40 -0700139 return ret;
140}
141
142int DRMMaster::RemoveFbId(uint32_t fb_id) {
Pullakavi Srinivas02434572021-02-28 23:46:09 +0530143 lock_guard<mutex> obj(s_lock);
Saurabh Shahf84c4122017-04-07 10:34:40 -0700144 int ret = 0;
Saurabh Shahfad1afd2017-01-31 12:09:59 -0800145#ifdef DRM_IOCTL_MSM_RMFB2
146 ret = drmIoctl(dev_fd_, DRM_IOCTL_MSM_RMFB2, &fb_id);
147 if (ret) {
148 DRM_LOGE("drmIoctl::DRM_IOCTL_MSM_RMFB2 failed for fb_id %d with error %d", fb_id, errno);
149 }
150#else
Rheygine Medela83c2d72020-02-12 15:43:40 -0800151 DRM_LOGE("drmModeRmFB is no longer used. DRM_IOCTL_MSM_RMFB2 not found");
Saurabh Shahfad1afd2017-01-31 12:09:59 -0800152#endif
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700153 return ret;
154}
155
Saurabh Shah23cd08a2017-07-10 15:18:14 -0700156bool DRMMaster::IsRmFbRefCounted() {
157#ifdef DRM_IOCTL_MSM_RMFB2
158 return true;
159#endif
160 return false;
161}
162
Saurabh Shah7d476ed2016-06-27 16:40:58 -0700163} // namespace drm_utils