1 /*
2 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
3 *
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 /*
31 * Changes from Qualcomm Innovation Center are provided under the following license:
32 *
33 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted (subject to the limitations in the
37 * disclaimer below) provided that the following conditions are met:
38 *
39 * * Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 *
42 * * Redistributions in binary form must reproduce the above
43 * copyright notice, this list of conditions and the following
44 * disclaimer in the documentation and/or other materials provided
45 * with the distribution.
46 *
47 * * Neither the name of Qualcomm Innovation Center, Inc. nor the
48 * names of its contributors may be used to endorse or promote
49 * products derived from this software without specific prior
50 * written permission.
51 *
52 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
53 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
54 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
55 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
56 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
58 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
60 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
62 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
63 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
64 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 #include <stdint.h>
68 #include <stdlib.h>
69 #include <drm.h>
70 // The 3 headers above are a workaround to prevent kernel drm.h from being used that has the
71 // "virtual" keyword used for a variable. In future replace libdrm version drm.h with kernel
72 // version drm/drm.h
73 #include <drm_logger.h>
74 #include <drm/drm_fourcc.h>
75 #include <drm/sde_drm.h>
76
77 #include <cstring>
78 #include <sstream>
79 #include <string>
80 #include <tuple>
81 #include <utility>
82 #include <vector>
83 #include <algorithm>
84
85 #include "drm_utils.h"
86 #include "drm_plane.h"
87 #include "drm_property.h"
88
89 namespace sde_drm {
90
91 using std::string;
92 using std::pair;
93 using std::vector;
94 using std::unique_ptr;
95 using std::tuple;
96 using std::stringstream;
97 using std::mutex;
98 using std::lock_guard;
99
100 #define MAX_SCALER_LINEWIDTH 2560
101
102 static struct sde_drm_csc_v1 csc_10bit_convert[kCscTypeMax] = {
103 [kCscYuv2Rgb601L] = {
104 {
105 0x12A000000, 0x000000000, 0x198800000,
106 0x12A000000, 0x7F9B800000, 0x7F30000000,
107 0x12A000000, 0x204800000, 0x000000000,
108 },
109 { 0xffc0, 0xfe00, 0xfe00,},
110 { 0x0, 0x0, 0x0,},
111 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
112 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
113 },
114 [kCscYuv2Rgb601FR] = {
115 {
116 0x100000000, 0x0, 0x167000000,
117 0x100000000, 0x7fa8000000, 0x7f49000000,
118 0x100000000, 0x1c5800000, 0x0,
119 },
120 { 0x0000, 0xfe00, 0xfe00,},
121 { 0x0, 0x0, 0x0,},
122 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
123 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
124 },
125 [kCscYuv2Rgb709L] = {
126 {
127 0x12a000000, 0x0, 0x1cb000000,
128 0x12a000000, 0x7fc9800000, 0x7f77800000,
129 0x12a000000, 0x21d000000, 0x0,
130 },
131 { 0xffc0, 0xfe00, 0xfe00,},
132 { 0x0, 0x0, 0x0,},
133 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
134 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
135 },
136 [kCscYuv2Rgb2020L] = {
137 {
138 0x12b000000, 0x0, 0x1af000000,
139 0x12b000000, 0x7fd0000000, 0x7f59000000,
140 0x12b000000, 0x226000000, 0x0,
141 },
142 { 0xffc0, 0xfe00, 0xfe00,},
143 { 0x0, 0x0, 0x0,},
144 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
145 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
146 },
147 [kCscYuv2Rgb2020FR] = {
148 {
149 0x100000000, 0x0, 0x179800000,
150 0x100000000, 0x7fd6000000, 0x7f6d800000,
151 0x100000000, 0x1e1800000, 0x0,
152 },
153 { 0x0000, 0xfe00, 0xfe00,},
154 { 0x0, 0x0, 0x0,},
155 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
156 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
157 },
158 };
159
160 static uint8_t REFLECT_X = 0;
161 static uint8_t REFLECT_Y = 0;
162 static uint8_t ROTATE_90 = 0;
163 static uint8_t ROTATE_0 = 0;
164
165 // FB Secure Modes
166 static uint8_t NON_SECURE = 0;
167 static uint8_t SECURE = 1;
168 static uint8_t NON_SECURE_DIR_TRANSLATION = 2;
169 static uint8_t SECURE_DIR_TRANSLATION = 3;
170
171 // Multi rect modes
172 static uint8_t MULTIRECT_NONE = 0;
173 static uint8_t MULTIRECT_PARALLEL = 1;
174 static uint8_t MULTIRECT_SERIAL = 2;
175
SetRect(DRMRect & source,drm_clip_rect * target)176 static void SetRect(DRMRect &source, drm_clip_rect *target) {
177 target->x1 = uint16_t(source.left);
178 target->y1 = uint16_t(source.top);
179 target->x2 = uint16_t(source.right);
180 target->y2 = uint16_t(source.bottom);
181 }
182
PopulateReflect(drmModePropertyRes * prop)183 static void PopulateReflect(drmModePropertyRes *prop) {
184 if (REFLECT_X) {
185 return;
186 }
187
188 if (!drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
189 return;
190 }
191
192 for (auto i = 0; i < prop->count_enums; i++) {
193 string enum_name(prop->enums[i].name);
194 if (enum_name == "reflect-x") {
195 REFLECT_X = prop->enums[i].value;
196 } else if (enum_name == "reflect-y") {
197 REFLECT_Y = prop->enums[i].value;
198 } else if (enum_name == "rotate-90") {
199 ROTATE_90 = prop->enums[i].value;
200 } else if (enum_name == "rotate-0") {
201 ROTATE_0 = prop->enums[i].value;
202 }
203 }
204 }
205
PopulateSecureModes(drmModePropertyRes * prop)206 static void PopulateSecureModes(drmModePropertyRes *prop) {
207 static bool secure_modes_populated = false;
208 if (!secure_modes_populated) {
209 for (auto i = 0; i < prop->count_enums; i++) {
210 string enum_name(prop->enums[i].name);
211 if (enum_name == "non_sec") {
212 NON_SECURE = prop->enums[i].value;
213 } else if (enum_name == "sec") {
214 SECURE = prop->enums[i].value;
215 } else if (enum_name == "non_sec_direct_translation") {
216 NON_SECURE_DIR_TRANSLATION = prop->enums[i].value;
217 } else if (enum_name == "sec_direct_translation") {
218 SECURE_DIR_TRANSLATION = prop->enums[i].value;
219 }
220 }
221 secure_modes_populated = true;
222 }
223 }
224
PopulateInlineRotationVersion(uint32_t ver)225 static InlineRotationVersion PopulateInlineRotationVersion(uint32_t ver) {
226 switch (ver) {
227 case 0x0000: return InlineRotationVersion::kInlineRotationNone;
228 case 0x0001:
229 case 0x0100: return InlineRotationVersion::kInlineRotationV1;
230 case 0x0200: return InlineRotationVersion::kInlineRotationV2;
231 default: return InlineRotationVersion::kInlineRotationNone;
232 }
233 }
234
PopulateQseedStepVersion(uint32_t hw_ver)235 static QSEEDStepVersion PopulateQseedStepVersion(uint32_t hw_ver) {
236 switch (hw_ver) {
237 case 0x1003: return QSEEDStepVersion::V3;
238 case 0x1004: return QSEEDStepVersion::V4;
239 case 0x2004: return QSEEDStepVersion::V3LITE_V4;
240 case 0x3000: return QSEEDStepVersion::V3LITE_V5;
241 // default value. also corresponds to (hw_ver == 0x1002)
242 default: return QSEEDStepVersion::V2;
243 }
244 }
245
PopulateMultiRectModes(drmModePropertyRes * prop)246 static void PopulateMultiRectModes(drmModePropertyRes *prop) {
247 static bool multirect_modes_populated = false;
248 if (!multirect_modes_populated) {
249 for (auto i = 0; i < prop->count_enums; i++) {
250 string enum_name(prop->enums[i].name);
251 if (enum_name == "none") {
252 MULTIRECT_NONE = prop->enums[i].value;
253 } else if (enum_name == "parallel") {
254 MULTIRECT_PARALLEL = prop->enums[i].value;
255 } else if (enum_name == "serial") {
256 MULTIRECT_SERIAL = prop->enums[i].value;
257 }
258 }
259 multirect_modes_populated = true;
260 }
261 }
262
GetColorLutString(DRMTonemapLutType lut_type)263 static const char *GetColorLutString(DRMTonemapLutType lut_type) {
264 switch (lut_type) {
265 case DRMTonemapLutType::DMA_1D_IGC:
266 return "DMA IGC";
267 case DRMTonemapLutType::DMA_1D_GC:
268 return "DMA GC";
269 case DRMTonemapLutType::VIG_1D_IGC:
270 return "VIG IGC";
271 case DRMTonemapLutType::VIG_3D_GAMUT:
272 return "VIG 3D";
273 default:
274 return "Unknown Lut";
275 }
276 }
277
278 #define __CLASS__ "DRMPlaneManager"
279
GetDRMonemapLutTypeFromPPFeatureID(DRMPPFeatureID id,DRMTonemapLutType * lut_type)280 static bool GetDRMonemapLutTypeFromPPFeatureID(DRMPPFeatureID id, DRMTonemapLutType *lut_type) {
281 switch (id) {
282 case kFeatureDgmIgc:
283 *lut_type = DRMTonemapLutType::DMA_1D_IGC;
284 break;
285 case kFeatureDgmGc:
286 *lut_type = DRMTonemapLutType::DMA_1D_GC;
287 break;
288 case kFeatureVigIgc:
289 *lut_type = DRMTonemapLutType::VIG_1D_IGC;
290 break;
291 case kFeatureVigGamut:
292 *lut_type = DRMTonemapLutType::VIG_3D_GAMUT;
293 break;
294 default:
295 DRM_LOGE("Invalid DRMPPFeature id = %d", id);
296 return false;
297 }
298 return true;
299 }
300
DRMPlaneManager(int fd)301 DRMPlaneManager::DRMPlaneManager(int fd) : fd_(fd) {}
302
Init()303 void DRMPlaneManager::Init() {
304 drmModePlaneRes *resource = drmModeGetPlaneResources(fd_);
305 if (!resource) {
306 return;
307 }
308
309 for (uint32_t i = 0; i < resource->count_planes; i++) {
310 // The enumeration order itself is the priority from high to low
311 unique_ptr<DRMPlane> plane(new DRMPlane(fd_, i));
312 drmModePlane *libdrm_plane = drmModeGetPlane(fd_, resource->planes[i]);
313 if (libdrm_plane) {
314 plane->InitAndParse(libdrm_plane);
315 object_pool_[resource->planes[i]] = std::move(plane);
316 } else {
317 DRM_LOGE("Critical error: drmModeGetPlane() failed for plane %d.", resource->planes[i]);
318 }
319 }
320
321 drmModeFreePlaneResources(resource);
322 }
323
Perform(DRMOps code,uint32_t obj_id,drmModeAtomicReq * req,va_list args)324 void DRMPlaneManager::Perform(DRMOps code, uint32_t obj_id, drmModeAtomicReq *req, va_list args) {
325 lock_guard<mutex> lock(lock_);
326 auto plane = GetObject(obj_id);
327 if (plane == nullptr) {
328 DRM_LOGE("Invalid plane id %d", obj_id);
329 return;
330 }
331
332 if (code == DRMOps::PLANE_SET_SCALER_CONFIG) {
333 if (plane->ConfigureScalerLUT(dir_lut_blob_id_, cir_lut_blob_id_,
334 sep_lut_blob_id_)) {
335 DRM_LOGD("Plane %d: Configuring scaler LUTs", obj_id);
336 }
337 }
338
339 plane->Perform(code, req, args);
340 }
341
GetPlanesInfo(DRMPlanesInfo * info)342 void DRMPlaneManager::GetPlanesInfo(DRMPlanesInfo *info) {
343 for (auto &plane : object_pool_) {
344 info->push_back(std::make_pair(plane.first, plane.second->GetPlaneTypeInfo()));
345 }
346 }
347
UnsetUnusedResources(uint32_t crtc_id,bool is_commit,drmModeAtomicReq * req)348 void DRMPlaneManager::UnsetUnusedResources(uint32_t crtc_id, bool is_commit, drmModeAtomicReq *req) {
349 // Unset planes that were assigned to the crtc referred to by crtc_id but are not requested
350 // in this round
351 lock_guard<mutex> lock(lock_);
352 for (auto &plane : object_pool_) {
353 uint32_t assigned_crtc = 0;
354 uint32_t requested_crtc = 0;
355 plane.second->GetAssignedCrtc(&assigned_crtc);
356 plane.second->GetRequestedCrtc(&requested_crtc);
357 if (assigned_crtc == crtc_id && requested_crtc == 0) {
358 plane.second->Unset(is_commit, req);
359 } else if (requested_crtc == crtc_id) {
360 // Plane is acquired, call reset color luts, which will reset if needed
361 plane.second->ResetColorLUTs(is_commit, req);
362 }
363 }
364 }
365
RetainPlanes(uint32_t crtc_id)366 void DRMPlaneManager::RetainPlanes(uint32_t crtc_id) {
367 for (auto &plane : object_pool_) {
368 uint32_t assigned_crtc = 0;
369 plane.second->GetAssignedCrtc(&assigned_crtc);
370 if (assigned_crtc == crtc_id) {
371 // Pretend this plane was requested by client
372 plane.second->SetRequestedCrtc(crtc_id);
373 const uint32_t plane_id = plane.first;
374 DRM_LOGD("Plane %d: Retaining on CRTC %d", plane_id, crtc_id);
375 }
376 }
377 }
378
PostValidate(uint32_t crtc_id)379 void DRMPlaneManager::PostValidate(uint32_t crtc_id) {
380 lock_guard<mutex> lock(lock_);
381 for (auto &plane : object_pool_) {
382 plane.second->PostValidate(crtc_id);
383 }
384 }
385
PostCommit(uint32_t crtc_id,bool success)386 void DRMPlaneManager::PostCommit(uint32_t crtc_id, bool success) {
387 lock_guard<mutex> lock(lock_);
388 DRM_LOGD("crtc %d", crtc_id);
389 for (auto &plane : object_pool_) {
390 plane.second->PostCommit(crtc_id, success);
391 }
392 }
393
SetScalerLUT(const DRMScalerLUTInfo & lut_info)394 void DRMPlaneManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
395 if (lut_info.dir_lut_size) {
396 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.dir_lut),
397 lut_info.dir_lut_size, &dir_lut_blob_id_);
398 }
399 if (lut_info.cir_lut_size) {
400 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.cir_lut),
401 lut_info.cir_lut_size, &cir_lut_blob_id_);
402 }
403 if (lut_info.sep_lut_size) {
404 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.sep_lut),
405 lut_info.sep_lut_size, &sep_lut_blob_id_);
406 }
407 }
408
UnsetScalerLUT()409 void DRMPlaneManager::UnsetScalerLUT() {
410 if (dir_lut_blob_id_) {
411 drmModeDestroyPropertyBlob(fd_, dir_lut_blob_id_);
412 dir_lut_blob_id_ = 0;
413 }
414 if (cir_lut_blob_id_) {
415 drmModeDestroyPropertyBlob(fd_, cir_lut_blob_id_);
416 cir_lut_blob_id_ = 0;
417 }
418 if (sep_lut_blob_id_) {
419 drmModeDestroyPropertyBlob(fd_, sep_lut_blob_id_);
420 sep_lut_blob_id_ = 0;
421 }
422 }
423
424 // ==============================================================================================//
425
426 #undef __CLASS__
427 #define __CLASS__ "DRMPlane"
428
DRMPlane(int fd,uint32_t priority)429 DRMPlane::DRMPlane(int fd, uint32_t priority)
430 : DRMObject(prop_mgr_), fd_(fd), priority_(priority) {}
431
~DRMPlane()432 DRMPlane::~DRMPlane() {
433 drmModeFreePlane(drm_plane_);
434 }
435
GetTypeInfo(const PropertyMap & prop_map)436 void DRMPlane::GetTypeInfo(const PropertyMap &prop_map) {
437 uint64_t blob_id = 0;
438 drmModePropertyRes *prop = nullptr;
439 DRMPlaneTypeInfo *info = &plane_type_info_;
440 // Ideally we should check if this property type is a blob and then proceed.
441 std::tie(blob_id, prop) = prop_map.at(DRMProperty::CAPABILITIES);
442 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
443 if (!blob) {
444 return;
445 }
446
447 if (!blob->data) {
448 return;
449 }
450
451 char *fmt_str = new char[blob->length + 1];
452 memcpy (fmt_str, blob->data, blob->length);
453 fmt_str[blob->length] = '\0';
454
455 info->max_linewidth = 2560;
456 info->max_scaler_linewidth = MAX_SCALER_LINEWIDTH;
457 info->max_upscale = 1;
458 info->max_downscale = 1;
459 info->max_horizontal_deci = 0;
460 info->max_vertical_deci = 0;
461 info->master_plane_id = 0;
462 if (info->type == DRMPlaneType::CURSOR) {
463 info->max_linewidth = 128;
464 }
465 // TODO(user): change default to V2 once we start getting V3 via capabilities blob
466 info->qseed3_version = QSEEDStepVersion::V3;
467 info->has_excl_rect = has_excl_rect_;
468
469 // We may have multiple lines with each one dedicated for something specific
470 // like formats etc
471 stringstream stream(fmt_str);
472 DRM_LOGI("stream str %s len %zu blob str %s len %d", stream.str().c_str(), stream.str().length(),
473 static_cast<const char *>(blob->data), blob->length);
474
475 string line = {};
476 string pixel_formats = "pixel_formats=";
477 string max_linewidth = "max_linewidth=";
478 string max_upscale = "max_upscale=";
479 string max_downscale = "max_downscale=";
480 string max_horizontal_deci = "max_horizontal_deci=";
481 string max_vertical_deci = "max_vertical_deci=";
482 string master_plane_id = "primary_smart_plane_id=";
483 string max_pipe_bw = "max_per_pipe_bw=";
484 string max_pipe_bw_high = "max_per_pipe_bw_high=";
485 string scaler_version = "scaler_step_ver=";
486 string block_sec_ui = "block_sec_ui=";
487 string true_inline_rot_rev = "true_inline_rot_rev=";
488 string inline_rot_pixel_formats = "inline_rot_pixel_formats=";
489 string true_inline_dwnscale_rt_numerator = "true_inline_dwnscale_rt_numerator=";
490 string true_inline_dwnscale_rt_denominator = "true_inline_dwnscale_rt_denominator=";
491 string true_inline_max_height = "true_inline_max_height=";
492
493 while (std::getline(stream, line)) {
494 if (line.find(inline_rot_pixel_formats) != string::npos) {
495 vector<pair<uint32_t, uint64_t>> inrot_formats_supported;
496 ParseFormats(line.erase(0, inline_rot_pixel_formats.length()), &inrot_formats_supported);
497 info->inrot_fmts_supported = std::move(inrot_formats_supported);
498 } else if (line.find(pixel_formats) != string::npos) {
499 vector<pair<uint32_t, uint64_t>> formats_supported;
500 ParseFormats(line.erase(0, pixel_formats.length()), &formats_supported);
501 info->formats_supported = std::move(formats_supported);
502 } else if (line.find(max_linewidth) != string::npos) {
503 info->max_linewidth = std::stoi(line.erase(0, max_linewidth.length()));
504 } else if (line.find(max_upscale) != string::npos) {
505 info->max_upscale = std::stoi(line.erase(0, max_upscale.length()));
506 } else if (line.find(max_downscale) != string::npos) {
507 info->max_downscale = std::stoi(line.erase(0, max_downscale.length()));
508 } else if (line.find(max_horizontal_deci) != string::npos) {
509 info->max_horizontal_deci = std::stoi(line.erase(0, max_horizontal_deci.length()));
510 } else if (line.find(max_vertical_deci) != string::npos) {
511 info->max_vertical_deci = std::stoi(line.erase(0, max_vertical_deci.length()));
512 } else if (line.find(master_plane_id) != string::npos) {
513 info->master_plane_id = std::stoi(line.erase(0, master_plane_id.length()));
514 DRM_LOGI("info->master_plane_id: detected master_plane=%d", info->master_plane_id);
515 } else if (line.find(max_pipe_bw) != string::npos) {
516 info->max_pipe_bandwidth = std::stoull(line.erase(0, max_pipe_bw.length()));
517 } else if (line.find(max_pipe_bw_high) != string::npos) {
518 info->max_pipe_bandwidth_high = std::stoull(line.erase(0, max_pipe_bw_high.length()));
519 } else if (line.find(scaler_version) != string::npos) {
520 info->qseed3_version =
521 PopulateQseedStepVersion(std::stoi(line.erase(0, scaler_version.length())));
522 } else if (line.find(block_sec_ui) != string::npos) {
523 info->block_sec_ui = !!(std::stoi(line.erase(0, block_sec_ui.length())));
524 } else if (line.find(true_inline_rot_rev) != string::npos) {
525 info->inrot_version =
526 PopulateInlineRotationVersion(std::stoi(line.erase(0, true_inline_rot_rev.length())));
527 } else if (line.find(true_inline_dwnscale_rt_numerator) != string::npos) {
528 info->true_inline_dwnscale_rt_num = std::stof(line.erase(0,
529 true_inline_dwnscale_rt_numerator.length()));
530 } else if (line.find(true_inline_dwnscale_rt_denominator) != string::npos) {
531 info->true_inline_dwnscale_rt_denom = std::stof(line.erase(0,
532 true_inline_dwnscale_rt_denominator.length()));
533 } else if (line.find(true_inline_max_height) != string::npos) {
534 info->max_rotation_linewidth = std::stoi(line.erase(0, true_inline_max_height.length()));
535 }
536 }
537
538 // TODO(user): Get max_scaler_linewidth and non_scaler_linewidth from driver
539 // max_linewidth can be smaller than 2560 for few target, so make sure to assign the minimum of both
540 info->max_scaler_linewidth = (info->qseed3_version < QSEEDStepVersion::V4) ? info->max_linewidth :
541 std::min((uint32_t)MAX_SCALER_LINEWIDTH, info->max_linewidth);
542
543 drmModeFreePropertyBlob(blob);
544 delete[] fmt_str;
545 }
546
ParseProperties()547 void DRMPlane::ParseProperties() {
548 // Map of property name to current value and property info pointer
549 PropertyMap prop_map;
550 bool csc = false;
551 bool scaler = false;
552 bool cursor = false;
553 drmModeObjectProperties *props =
554 drmModeObjectGetProperties(fd_, drm_plane_->plane_id, DRM_MODE_OBJECT_PLANE);
555 if (!props || !props->props || !props->prop_values) {
556 drmModeFreeObjectProperties(props);
557 return;
558 }
559
560 for (uint32_t j = 0; j < props->count_props; j++) {
561 drmModePropertyRes *info = drmModeGetProperty(fd_, props->props[j]);
562 if (!info) {
563 continue;
564 }
565
566 string property_name(info->name);
567 DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
568 if (prop_enum == DRMProperty::INVALID) {
569 DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
570 drmModeFreeProperty(info);
571 continue;
572 }
573
574 if (prop_enum == DRMProperty::EXCL_RECT) {
575 has_excl_rect_ = true;
576 }
577 if (prop_enum == DRMProperty::ROTATION) {
578 PopulateReflect(info);
579 } else if (prop_enum == DRMProperty::FB_TRANSLATION_MODE) {
580 PopulateSecureModes(info);
581 } else if (prop_enum == DRMProperty::MULTIRECT_MODE) {
582 PopulateMultiRectModes(info);
583 plane_type_info_.multirect_prop_present = true;
584 }
585
586 prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
587 prop_map[prop_enum] = std::make_tuple(props->prop_values[j], info);
588 csc = prop_enum == DRMProperty::CSC_V1 ? true : csc;
589 scaler = (prop_enum == DRMProperty::SCALER_V1 || prop_enum == DRMProperty::SCALER_V2) \
590 ? true : scaler;
591 cursor = (prop_enum == DRMProperty::TYPE && props->prop_values[j] == DRM_PLANE_TYPE_CURSOR) \
592 ? true : cursor;
593
594 // Tone mapping properties.
595 if (prop_enum == DRMProperty::INVERSE_PMA) {
596 plane_type_info_.inverse_pma = true;
597 }
598
599 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::CSC_DMA_V1 &&
600 (uint32_t)prop_enum <= (uint32_t)DRMProperty::CSC_DMA_V1) {
601 plane_type_info_.dgm_csc_version =
602 ((uint32_t)prop_enum - (uint32_t)DRMProperty::CSC_DMA_V1 + 1);
603 }
604
605 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 &&
606 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5) {
607 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_IGC] =
608 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 + 5);
609 }
610 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 &&
611 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5) {
612 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_GC] =
613 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 + 5);
614 }
615 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 &&
616 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V6) {
617 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_1D_IGC] =
618 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 + 5);
619 }
620 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 &&
621 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V6) {
622 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_3D_GAMUT] =
623 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 + 5);
624 }
625 }
626
627 DRMPlaneType type = DRMPlaneType::DMA;
628 if (csc && scaler) {
629 type = DRMPlaneType::VIG;
630 } else if (cursor) {
631 type = DRMPlaneType::CURSOR;
632 }
633
634 plane_type_info_.type = type;
635 GetTypeInfo(prop_map);
636
637 for (auto &prop : prop_map) {
638 drmModeFreeProperty(std::get<1>(prop.second));
639 }
640
641 drmModeFreeObjectProperties(props);
642 }
643
InitAndParse(drmModePlane * plane)644 void DRMPlane::InitAndParse(drmModePlane *plane) {
645 drm_plane_ = plane;
646 ParseProperties();
647
648 unique_ptr<DRMPPManager> pp_mgr(new DRMPPManager(fd_));
649 pp_mgr_ = std::move(pp_mgr);
650 pp_mgr_->Init(prop_mgr_, DRM_MODE_OBJECT_PLANE);
651 }
652
ConfigureScalerLUT(uint32_t dir_lut_blob_id,uint32_t cir_lut_blob_id,uint32_t sep_lut_blob_id)653 bool DRMPlane::ConfigureScalerLUT(uint32_t dir_lut_blob_id,
654 uint32_t cir_lut_blob_id, uint32_t sep_lut_blob_id) {
655 if (plane_type_info_.type != DRMPlaneType::VIG || is_lut_configured_) {
656 return false;
657 }
658
659 if (dir_lut_blob_id) {
660 AddProperty(DRMProperty::LUT_ED, dir_lut_blob_id, true);
661 }
662 if (cir_lut_blob_id) {
663 AddProperty(DRMProperty::LUT_CIR, cir_lut_blob_id, true);
664 }
665 if (sep_lut_blob_id) {
666 AddProperty(DRMProperty::LUT_SEP, sep_lut_blob_id, true);
667 }
668
669 return true;
670 }
671
SetExclRect(DRMRect rect)672 void DRMPlane::SetExclRect(DRMRect rect) {
673 drm_clip_rect clip_rect;
674 SetRect(rect, &clip_rect);
675 excl_rect_copy_ = clip_rect;
676 AddProperty(DRMProperty::EXCL_RECT,
677 reinterpret_cast<uint64_t>(&excl_rect_copy_), true);
678 DRM_LOGD("Plane %d: Setting exclusion rect [x,y,w,h][%d,%d,%d,%d]", drm_plane_->plane_id,
679 clip_rect.x1, clip_rect.y1, (clip_rect.x2 - clip_rect.x1),
680 (clip_rect.y2 - clip_rect.y1));
681 }
682
SetCscConfig(DRMCscType csc_type)683 bool DRMPlane::SetCscConfig(DRMCscType csc_type) {
684 if (plane_type_info_.type != DRMPlaneType::VIG) {
685 return false;
686 }
687
688 if (csc_type > kCscTypeMax) {
689 return false;
690 }
691
692 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_V1)) {
693 return false;
694 }
695
696 if (csc_type == kCscTypeMax) {
697 AddProperty(DRMProperty::CSC_V1, 0);
698 } else {
699 csc_config_copy_ = csc_10bit_convert[csc_type];
700 AddProperty(DRMProperty::CSC_V1,
701 reinterpret_cast<uint64_t>(&csc_config_copy_), true);
702 }
703
704 return true;
705 }
706
SetScalerConfig(uint64_t handle)707 bool DRMPlane::SetScalerConfig(uint64_t handle) {
708 if (plane_type_info_.type != DRMPlaneType::VIG) {
709 return false;
710 }
711
712 if (prop_mgr_.IsPropertyAvailable(DRMProperty::SCALER_V2)) {
713 sde_drm_scaler_v2 *scaler_v2_config = reinterpret_cast<sde_drm_scaler_v2 *>(handle);
714 uint64_t scaler_data = 0;
715 // The address needs to be valid even after async commit, since we are sending address to
716 // driver directly, instead of blob. So we need to copy over contents that client sent. Client
717 // may have sent an address of object on stack which will be released after this call.
718 scaler_v2_config_copy_ = *scaler_v2_config;
719 if (scaler_v2_config_copy_.enable) {
720 scaler_data = reinterpret_cast<uint64_t>(&scaler_v2_config_copy_);
721 }
722 AddProperty(DRMProperty::SCALER_V2, scaler_data, scaler_data != 0);
723 return true;
724 }
725
726 return false;
727 }
728
SetDecimation(DRMProperty prop,uint32_t prop_value)729 void DRMPlane::SetDecimation(DRMProperty prop, uint32_t prop_value) {
730 if (plane_type_info_.type == DRMPlaneType::DMA || plane_type_info_.master_plane_id) {
731 // if value is 0, client is just trying to clear previous decimation, so bail out silently
732 if (prop_value > 0) {
733 DRM_LOGE("Plane %d: Setting decimation %d is not supported.", drm_plane_->plane_id,
734 prop_value);
735 }
736 return;
737 }
738
739 // TODO(user): Currently a ViG plane in smart DMA mode could receive a non-zero decimation value
740 // but there is no good way to catch. In any case fix will be in client
741 AddProperty(prop, prop_value);
742 DRM_LOGD("Plane %d: Setting decimation %d", drm_plane_->plane_id, prop_value);
743 }
744
PostValidate(uint32_t crtc_id)745 void DRMPlane::PostValidate(uint32_t crtc_id) {
746 DiscardDirtyProperties();
747 if (requested_crtc_id_ == crtc_id) {
748 SetRequestedCrtc(0);
749 }
750 }
751
PostCommit(uint32_t crtc_id,bool success)752 void DRMPlane::PostCommit(uint32_t crtc_id, bool success) {
753 DRM_LOGD("crtc %d", crtc_id);
754 if (!success) {
755 // To reset
756 PostValidate(crtc_id);
757 return;
758 }
759
760 uint32_t assigned_crtc = 0;
761 uint32_t requested_crtc = 0;
762
763 CommitProperties();
764 GetAssignedCrtc(&assigned_crtc);
765 GetRequestedCrtc(&requested_crtc);
766
767 // In future, it is possible that plane is already attached in case of continuous splash. This
768 // will cause the first commit to only unstage pipes. We want to mark luts as configured only
769 // when they really are, which typically happens if a crtc is requested for a plane
770 if (requested_crtc == crtc_id && !is_lut_configured_) {
771 is_lut_configured_ = true;
772 }
773
774 if (requested_crtc && assigned_crtc && requested_crtc != assigned_crtc) {
775 // We should never be here
776 DRM_LOGE("Found plane %d switching from crtc %d to crtc %d", drm_plane_->plane_id,
777 assigned_crtc, requested_crtc);
778 }
779
780 // If we have set a pipe OR unset a pipe during commit, update states
781 if (requested_crtc == crtc_id || assigned_crtc == crtc_id) {
782 SetAssignedCrtc(requested_crtc);
783 SetRequestedCrtc(0);
784 }
785 }
786
Perform(DRMOps code,drmModeAtomicReq * req,va_list args)787 void DRMPlane::Perform(DRMOps code, drmModeAtomicReq *req, va_list args) {
788 uint32_t obj_id = drm_plane_->plane_id;
789
790 switch (code) {
791 // TODO(user): Check if these exist in map before attempting to access
792 case DRMOps::PLANE_SET_SRC_RECT: {
793 DRMRect rect = va_arg(args, DRMRect);
794 // source co-ordinates accepted by DRM are 16.16 fixed point
795 AddProperty(DRMProperty::SRC_X, rect.left << 16);
796 AddProperty(DRMProperty::SRC_Y, rect.top << 16);
797 AddProperty(DRMProperty::SRC_W, (rect.right - rect.left) << 16);
798 AddProperty(DRMProperty::SRC_H, (rect.bottom - rect.top) << 16);
799 DRM_LOGV("Plane %d: Setting crop [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
800 rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
801 } break;
802
803 case DRMOps::PLANE_SET_DST_RECT: {
804 DRMRect rect = va_arg(args, DRMRect);
805 AddProperty(DRMProperty::CRTC_X, rect.left);
806 AddProperty(DRMProperty::CRTC_Y, rect.top);
807 AddProperty(DRMProperty::CRTC_W, (rect.right - rect.left));
808 AddProperty(DRMProperty::CRTC_H, (rect.bottom - rect.top));
809 DRM_LOGV("Plane %d: Setting dst [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
810 rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
811 } break;
812 case DRMOps::PLANE_SET_EXCL_RECT: {
813 DRMRect excl_rect = va_arg(args, DRMRect);
814 SetExclRect(excl_rect);
815 } break;
816
817 case DRMOps::PLANE_SET_ZORDER: {
818 uint32_t zpos = va_arg(args, uint32_t);
819 AddProperty(DRMProperty::ZPOS, zpos);
820 DRM_LOGD("Plane %d: Setting z %d", obj_id, zpos);
821 } break;
822
823 case DRMOps::PLANE_SET_ROTATION: {
824 uint32_t rot_bit_mask = va_arg(args, uint32_t);
825 uint32_t drm_rot_bit_mask = 0;
826 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_H)) {
827 drm_rot_bit_mask |= 1 << REFLECT_X;
828 }
829 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_V)) {
830 drm_rot_bit_mask |= 1 << REFLECT_Y;
831 }
832 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::ROT_90)) {
833 drm_rot_bit_mask |= 1 << ROTATE_90;
834 } else {
835 drm_rot_bit_mask |= 1 << ROTATE_0;
836 }
837 AddProperty(DRMProperty::ROTATION, drm_rot_bit_mask);
838 DRM_LOGV("Plane %d: Setting rotation mask %x", obj_id, drm_rot_bit_mask);
839 } break;
840
841 case DRMOps::PLANE_SET_ALPHA: {
842 uint32_t alpha = va_arg(args, uint32_t);
843 AddProperty(DRMProperty::ALPHA, alpha);
844 DRM_LOGV("Plane %d: Setting alpha %d", obj_id, alpha);
845 } break;
846
847 case DRMOps::PLANE_SET_BLEND_TYPE: {
848 uint32_t blending = va_arg(args, uint32_t);
849 AddProperty(DRMProperty::BLEND_OP, blending);
850 DRM_LOGV("Plane %d: Setting blending %d", obj_id, blending);
851 } break;
852
853 case DRMOps::PLANE_SET_H_DECIMATION: {
854 uint32_t deci = va_arg(args, uint32_t);
855 SetDecimation(DRMProperty::H_DECIMATE, deci);
856 } break;
857
858 case DRMOps::PLANE_SET_V_DECIMATION: {
859 uint32_t deci = va_arg(args, uint32_t);
860 SetDecimation(DRMProperty::V_DECIMATE, deci);
861 } break;
862
863 case DRMOps::PLANE_SET_SRC_CONFIG: {
864 bool src_config = va_arg(args, uint32_t);
865 AddProperty(DRMProperty::SRC_CONFIG, src_config);
866 DRM_LOGV("Plane %d: Setting src_config flags-%x", obj_id, src_config);
867 } break;
868
869 case DRMOps::PLANE_SET_CRTC: {
870 uint32_t crtc_id = va_arg(args, uint32_t);
871 AddProperty(DRMProperty::CRTC_ID, crtc_id);
872 SetRequestedCrtc(crtc_id);
873 DRM_LOGV("Plane %d: Setting crtc %d", obj_id, crtc_id);
874 } break;
875
876 case DRMOps::PLANE_SET_FB_ID: {
877 uint32_t fb_id = va_arg(args, uint32_t);
878 AddProperty(DRMProperty::FB_ID, fb_id);
879 DRM_LOGV("Plane %d: Setting fb_id %d", obj_id, fb_id);
880 } break;
881
882 case DRMOps::PLANE_SET_ROT_FB_ID: {
883 uint32_t fb_id = va_arg(args, uint32_t);
884 AddProperty(DRMProperty::ROT_FB_ID, fb_id, true);
885 DRM_LOGV("Plane %d: Setting rot_fb_id %d", obj_id, fb_id);
886 } break;
887
888 case DRMOps::PLANE_SET_INPUT_FENCE: {
889 int fence = va_arg(args, int);
890 AddProperty(DRMProperty::INPUT_FENCE, fence, true);
891 DRM_LOGV("Plane %d: Setting input fence %d", obj_id, fence);
892 } break;
893
894 case DRMOps::PLANE_SET_SCALER_CONFIG: {
895 uint64_t handle = va_arg(args, uint64_t);
896 if (SetScalerConfig(handle)) {
897 DRM_LOGV("Plane %d: Setting scaler config", obj_id);
898 }
899 } break;
900
901 case DRMOps::PLANE_SET_FB_SECURE_MODE: {
902 int secure_mode = va_arg(args, int);
903 uint32_t fb_secure_mode = NON_SECURE;
904 switch (secure_mode) {
905 case (int)DRMSecureMode::NON_SECURE:
906 fb_secure_mode = NON_SECURE;
907 break;
908 case (int)DRMSecureMode::SECURE:
909 fb_secure_mode = SECURE;
910 break;
911 case (int)DRMSecureMode::NON_SECURE_DIR_TRANSLATION:
912 fb_secure_mode = NON_SECURE_DIR_TRANSLATION;
913 break;
914 case (int)DRMSecureMode::SECURE_DIR_TRANSLATION:
915 fb_secure_mode = SECURE_DIR_TRANSLATION;
916 break;
917 default:
918 DRM_LOGE("Invalid secure mode %d to set on plane %d", secure_mode, obj_id);
919 break;
920 }
921
922 AddProperty(DRMProperty::FB_TRANSLATION_MODE, fb_secure_mode);
923 DRM_LOGD("Plane %d: Setting FB secure mode %d", obj_id, fb_secure_mode);
924 } break;
925
926 case DRMOps::PLANE_SET_CSC_CONFIG: {
927 uint32_t* csc_type = va_arg(args, uint32_t*);
928 if (csc_type) {
929 SetCscConfig((DRMCscType)*csc_type);
930 }
931 } break;
932
933 case DRMOps::PLANE_SET_MULTIRECT_MODE: {
934 DRMMultiRectMode drm_multirect_mode = (DRMMultiRectMode)va_arg(args, uint32_t);
935 SetMultiRectMode(drm_multirect_mode);
936 } break;
937
938 case DRMOps::PLANE_SET_INVERSE_PMA: {
939 uint32_t pma = va_arg(args, uint32_t);
940 AddProperty(DRMProperty::INVERSE_PMA, pma);
941 DRM_LOGD("Plane %d: %s inverse pma", obj_id, pma ? "Setting" : "Resetting");
942 } break;
943
944 case DRMOps::PLANE_SET_DGM_CSC_CONFIG: {
945 uint64_t handle = va_arg(args, uint64_t);
946 if (SetDgmCscConfig(handle)) {
947 DRM_LOGD("Plane %d: Setting Csc Lut config", obj_id);
948 }
949 } break;
950
951 case DRMOps::PLANE_SET_POST_PROC: {
952 DRMPPFeatureInfo *data = va_arg(args, DRMPPFeatureInfo*);
953 if (data) {
954 DRM_LOGD("Plane %d: Set post proc feature id - %d", obj_id, data->id);
955 pp_mgr_->SetPPFeature(req, obj_id, *data);
956 UpdatePPLutFeatureInuse(data);
957 }
958 } break;
959
960 case DRMOps::PLANE_SET_SSPP_LAYOUT: {
961 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::SDE_SSPP_LAYOUT)) {
962 DRM_LOGD("SSPP_LAYOUT property isn't exposed");
963 break;
964 }
965 DRMSSPPLayoutIndex layout_index = (DRMSSPPLayoutIndex) va_arg(args, uint32_t);
966 AddProperty(DRMProperty::SDE_SSPP_LAYOUT, (uint32_t)layout_index);
967 DRM_LOGD("Plane %d: Setting SSPP Layout to %d", obj_id, layout_index);
968 } break;
969
970 default:
971 DRM_LOGE("Invalid opcode %d for DRM Plane %d", code, obj_id);
972 }
973 }
974
UpdatePPLutFeatureInuse(DRMPPFeatureInfo * data)975 void DRMPlane::UpdatePPLutFeatureInuse(DRMPPFeatureInfo *data) {
976 DRMTonemapLutType lut_type = {};
977 bool ret = GetDRMonemapLutTypeFromPPFeatureID(data->id, &lut_type);
978 if (ret == false) {
979 DRM_LOGE("Failed to get the lut type from PPFeatureID = %d", data->id);
980 return;
981 }
982
983 const auto state = data->payload ? kActive : kInactive;
984
985 switch (lut_type) {
986 case DRMTonemapLutType::DMA_1D_GC:
987 dgm_1d_lut_gc_state_ = state;
988 break;
989 case DRMTonemapLutType::DMA_1D_IGC:
990 dgm_1d_lut_igc_state_ = state;
991 break;
992 case DRMTonemapLutType::VIG_1D_IGC:
993 vig_1d_lut_igc_state_ = state;
994 break;
995 case DRMTonemapLutType::VIG_3D_GAMUT:
996 vig_3d_lut_gamut_state_ = state;
997 break;
998 default:
999 DRM_LOGE("Invalid lut_type = %d state = %d", lut_type, state);
1000 }
1001 return;
1002 }
1003
PerformWrapper(DRMOps code,drmModeAtomicReq * req,...)1004 void DRMPlane::PerformWrapper(DRMOps code, drmModeAtomicReq *req, ...) {
1005 va_list args;
1006 va_start(args, req);
1007 Perform(code, req, args);
1008 va_end(args);
1009 }
1010
Dump()1011 void DRMPlane::Dump() {
1012 DRM_LOGE(
1013 "id: %d\tcrtc id: %d\tfb id: %d\tCRTC_xy: %dx%d\txy: %dx%d\tgamma "
1014 "size: %d\tpossible crtc: 0x%x\n",
1015 drm_plane_->plane_id, drm_plane_->crtc_id, drm_plane_->fb_id, drm_plane_->crtc_x,
1016 drm_plane_->crtc_y, drm_plane_->x, drm_plane_->y, drm_plane_->gamma_size,
1017 drm_plane_->possible_crtcs);
1018 DRM_LOGE("Format Suported: \n");
1019 for (uint32_t i = 0; i < (uint32_t)drm_plane_->count_formats; i++)
1020 DRM_LOGE(" %4.4s", (char *)&drm_plane_->formats[i]);
1021 }
1022
SetMultiRectMode(DRMMultiRectMode drm_multirect_mode)1023 void DRMPlane::SetMultiRectMode(DRMMultiRectMode drm_multirect_mode) {
1024 if (!plane_type_info_.multirect_prop_present) {
1025 return;
1026 }
1027 uint32_t obj_id = drm_plane_->plane_id;
1028 uint32_t multirect_mode = MULTIRECT_NONE;
1029 switch (drm_multirect_mode) {
1030 case DRMMultiRectMode::NONE:
1031 multirect_mode = MULTIRECT_NONE;
1032 break;
1033 case DRMMultiRectMode::PARALLEL:
1034 multirect_mode = MULTIRECT_PARALLEL;
1035 break;
1036 case DRMMultiRectMode::SERIAL:
1037 multirect_mode = MULTIRECT_SERIAL;
1038 break;
1039 default:
1040 DRM_LOGE("Invalid multirect mode %d to set on plane %d", drm_multirect_mode, GetObjectId());
1041 break;
1042 }
1043 AddProperty(DRMProperty::MULTIRECT_MODE, multirect_mode);
1044 DRM_LOGD("Plane %d: Setting multirect_mode %d", obj_id, multirect_mode);
1045 }
1046
Unset(bool is_commit,drmModeAtomicReq * req)1047 void DRMPlane::Unset(bool is_commit, drmModeAtomicReq *req) {
1048 DRM_LOGD("Plane %d: Unsetting from crtc %d", drm_plane_->plane_id, assigned_crtc_id_);
1049 PerformWrapper(DRMOps::PLANE_SET_FB_ID, req, 0);
1050 PerformWrapper(DRMOps::PLANE_SET_CRTC, req, 0);
1051 DRMRect rect = {0, 0, 0, 0};
1052 PerformWrapper(DRMOps::PLANE_SET_SRC_RECT, req, rect);
1053 PerformWrapper(DRMOps::PLANE_SET_DST_RECT, req, rect);
1054 PerformWrapper(DRMOps::PLANE_SET_EXCL_RECT, req, rect);
1055 if (plane_type_info_.inverse_pma) {
1056 PerformWrapper(DRMOps::PLANE_SET_INVERSE_PMA, req, 0);
1057 }
1058
1059 // Reset the sspp tonemap properties if they were set and update the in-use only if
1060 // its a Commit as Unset is called in Validate as well.
1061 if (dgm_csc_in_use_) {
1062 uint64_t csc_v1 = 0;
1063 AddProperty(DRMProperty::CSC_DMA_V1, csc_v1, true);
1064 DRM_LOGV("Plane %d Clearing DGM CSC", drm_plane_->plane_id);
1065 dgm_csc_in_use_ = !is_commit;
1066 }
1067 ResetColorLUTs(is_commit, req);
1068 }
1069
SetDgmCscConfig(uint64_t handle)1070 bool DRMPlane::SetDgmCscConfig(uint64_t handle) {
1071 if (plane_type_info_.type == DRMPlaneType::DMA &&
1072 prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_DMA_V1)) {
1073 sde_drm_csc_v1 *csc_v1 = reinterpret_cast<sde_drm_csc_v1 *>(handle);
1074 uint64_t csc_v1_data = 0;
1075 sde_drm_csc_v1 csc_v1_tmp = {};
1076 csc_config_copy_ = *csc_v1;
1077 if (std::memcmp(&csc_config_copy_, &csc_v1_tmp, sizeof(sde_drm_csc_v1)) != 0) {
1078 csc_v1_data = reinterpret_cast<uint64_t>(&csc_config_copy_);
1079 }
1080 AddProperty(DRMProperty::CSC_DMA_V1, csc_v1_data, true);
1081 dgm_csc_in_use_ = (csc_v1_data != 0);
1082 DRM_LOGV("Plane %d in_use = %d", drm_plane_->plane_id, dgm_csc_in_use_);
1083
1084 return true;
1085 }
1086
1087 return false;
1088 }
1089
ResetColorLUTs(bool is_commit,drmModeAtomicReq * req)1090 void DRMPlane::ResetColorLUTs(bool is_commit, drmModeAtomicReq *req) {
1091 // Reset the color luts if they were set and update the state only if its a Commit as Unset
1092 // is called in Validate as well.
1093 for (int i = 0; i <= static_cast<int>(DRMTonemapLutType::VIG_3D_GAMUT); i++) {
1094 auto itr = plane_type_info_.tonemap_lut_version_map.find(static_cast<DRMTonemapLutType>(i));
1095 if (itr != plane_type_info_.tonemap_lut_version_map.end()) {
1096 ResetColorLUTState(static_cast<DRMTonemapLutType>(i), is_commit, req);
1097 }
1098 }
1099 }
1100
ResetColorLUTState(DRMTonemapLutType lut_type,bool is_commit,drmModeAtomicReq * req)1101 void DRMPlane::ResetColorLUTState(DRMTonemapLutType lut_type, bool is_commit,
1102 drmModeAtomicReq *req) {
1103 DRMPlaneLutState *lut_state = nullptr;
1104 DRMPPFeatureID feature_id = {};
1105 switch (lut_type) {
1106 case DRMTonemapLutType::DMA_1D_GC:
1107 lut_state = &dgm_1d_lut_gc_state_;
1108 feature_id = kFeatureDgmGc;
1109 break;
1110 case DRMTonemapLutType::DMA_1D_IGC:
1111 lut_state = &dgm_1d_lut_igc_state_;
1112 feature_id = kFeatureDgmIgc;
1113 break;
1114 case DRMTonemapLutType::VIG_1D_IGC:
1115 lut_state = &vig_1d_lut_igc_state_;
1116 feature_id = kFeatureVigIgc;
1117 break;
1118 case DRMTonemapLutType::VIG_3D_GAMUT:
1119 lut_state = &vig_3d_lut_gamut_state_;
1120 feature_id = kFeatureVigGamut;
1121 break;
1122 default:
1123 DLOGE("Invalid lut type = %d", lut_type);
1124 return;
1125 }
1126
1127 if (*lut_state == kInactive) {
1128 DRM_LOGV("Plane %d %s Lut not used", drm_plane_->plane_id, GetColorLutString(lut_type));
1129 return;
1130 }
1131
1132 DRMPlaneLutState target_state;
1133 // If plane is getting unset, clearing of LUT will not be applied in hw.
1134 // In that case, mark LUT as dirty and make sure that these are cleared the
1135 // next time the plane gets used
1136 if (*lut_state == kActive && requested_crtc_id_ == 0) {
1137 target_state = kDirty;
1138 } else if (*lut_state == kDirty && requested_crtc_id_ != 0) {
1139 // If plane is getting activated while LUT is in dirty state, the new state
1140 // should be inactive but still need to clear exiting LUT config in hw
1141 target_state = kInactive;
1142 } else {
1143 return;
1144 }
1145
1146 if (is_commit) {
1147 DRM_LOGD("Plane %d Clearing %s Lut, moving from (%d) -> (%d)", drm_plane_->plane_id,
1148 GetColorLutString(lut_type), *lut_state, target_state);
1149
1150 *lut_state = target_state;
1151 }
1152
1153 ResetColorLUT(feature_id, req);
1154 }
1155
ResetColorLUT(DRMPPFeatureID id,drmModeAtomicReq * req)1156 void DRMPlane::ResetColorLUT(DRMPPFeatureID id, drmModeAtomicReq *req) {
1157 DRMPPFeatureInfo pp_feature_info = {};
1158 pp_feature_info.type = kPropBlob;
1159 pp_feature_info.payload = nullptr;
1160 pp_feature_info.id = id;
1161 pp_mgr_->SetPPFeature(req, drm_plane_->plane_id, pp_feature_info);
1162 }
1163
1164 } // namespace sde_drm
1165