blob: a31abb6cdedecc04183531531981c73cd150a2a4 [file] [log] [blame]
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +05301/*
2* Copyright (c) 2019, 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#include <stdint.h>
31#include <stdlib.h>
32#include <drm.h>
33// The 3 headers above are a workaround to prevent kernel drm.h from being used that has the
34// "virtual" keyword used for a variable. In future replace libdrm version drm.h with kernel
35// version drm/drm.h
36#include <drm_logger.h>
37#include <drm/drm_fourcc.h>
38#include <drm/sde_drm.h>
39
40#include <cstring>
41#include <map>
42#include <sstream>
43#include <string>
44#include <tuple>
45#include <utility>
46#include <vector>
47
48#include "drm_utils.h"
49#include "drm_plane.h"
50#include "drm_property.h"
51
52namespace sde_drm {
53
54using std::map;
55using std::string;
56using std::map;
57using std::pair;
58using std::vector;
59using std::unique_ptr;
60using std::tuple;
61using std::stringstream;
62
63static struct sde_drm_csc_v1 csc_10bit_convert[kCscTypeMax] = {
64 [kCscYuv2Rgb601L] = {
65 {
66 0x12A000000, 0x000000000, 0x198800000,
67 0x12A000000, 0x7F9B800000, 0x7F30000000,
68 0x12A000000, 0x204800000, 0x000000000,
69 },
70 { 0xffc0, 0xfe00, 0xfe00,},
71 { 0x0, 0x0, 0x0,},
72 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
73 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
74 },
75 [kCscYuv2Rgb601FR] = {
76 {
77 0x100000000, 0x0, 0x167000000,
78 0x100000000, 0x7fa8000000, 0x7f49000000,
79 0x100000000, 0x1c5800000, 0x0,
80 },
81 { 0x0000, 0xfe00, 0xfe00,},
82 { 0x0, 0x0, 0x0,},
83 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
84 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
85 },
86 [kCscYuv2Rgb709L] = {
87 {
88 0x12a000000, 0x0, 0x1cb000000,
89 0x12a000000, 0x7fc9800000, 0x7f77800000,
90 0x12a000000, 0x21d000000, 0x0,
91 },
92 { 0xffc0, 0xfe00, 0xfe00,},
93 { 0x0, 0x0, 0x0,},
94 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
95 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
96 },
97 [kCscYuv2Rgb2020L] = {
98 {
99 0x12b000000, 0x0, 0x1af000000,
100 0x12b000000, 0x7fd0000000, 0x7f59000000,
101 0x12b000000, 0x226000000, 0x0,
102 },
103 { 0xffc0, 0xfe00, 0xfe00,},
104 { 0x0, 0x0, 0x0,},
105 { 0x40, 0x3ac, 0x40, 0x3c0, 0x40, 0x3c0,},
106 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
107 },
108 [kCscYuv2Rgb2020FR] = {
109 {
110 0x100000000, 0x0, 0x179800000,
111 0x100000000, 0x7fd6000000, 0x7f6d800000,
112 0x100000000, 0x1e1800000, 0x0,
113 },
114 { 0x0000, 0xfe00, 0xfe00,},
115 { 0x0, 0x0, 0x0,},
116 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
117 { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,},
118 },
119};
120
121static uint8_t REFLECT_X = 0;
122static uint8_t REFLECT_Y = 0;
123static uint8_t ROTATE_90 = 0;
124static uint8_t ROTATE_0 = 0;
125
126// FB Secure Modes
127static uint8_t NON_SECURE = 0;
128static uint8_t SECURE = 1;
129static uint8_t NON_SECURE_DIR_TRANSLATION = 2;
130static uint8_t SECURE_DIR_TRANSLATION = 3;
131
132// Multi rect modes
133static uint8_t MULTIRECT_NONE = 0;
134static uint8_t MULTIRECT_PARALLEL = 1;
135static uint8_t MULTIRECT_SERIAL = 2;
136
137static void SetRect(DRMRect &source, drm_clip_rect *target) {
138 target->x1 = uint16_t(source.left);
139 target->y1 = uint16_t(source.top);
140 target->x2 = uint16_t(source.right);
141 target->y2 = uint16_t(source.bottom);
142}
143
144static void PopulateReflect(drmModePropertyRes *prop) {
145 if (REFLECT_X) {
146 return;
147 }
148
149 if (!drm_property_type_is(prop, DRM_MODE_PROP_BITMASK)) {
150 return;
151 }
152
153 for (auto i = 0; i < prop->count_enums; i++) {
154 string enum_name(prop->enums[i].name);
155 if (enum_name == "reflect-x") {
156 REFLECT_X = prop->enums[i].value;
157 } else if (enum_name == "reflect-y") {
158 REFLECT_Y = prop->enums[i].value;
159 } else if (enum_name == "rotate-90") {
160 ROTATE_90 = prop->enums[i].value;
161 } else if (enum_name == "rotate-0") {
162 ROTATE_0 = prop->enums[i].value;
163 }
164 }
165}
166
167static void PopulateSecureModes(drmModePropertyRes *prop) {
168 static bool secure_modes_populated = false;
169 if (!secure_modes_populated) {
170 for (auto i = 0; i < prop->count_enums; i++) {
171 string enum_name(prop->enums[i].name);
172 if (enum_name == "non_sec") {
173 NON_SECURE = prop->enums[i].value;
174 } else if (enum_name == "sec") {
175 SECURE = prop->enums[i].value;
176 } else if (enum_name == "non_sec_direct_translation") {
177 NON_SECURE_DIR_TRANSLATION = prop->enums[i].value;
178 } else if (enum_name == "sec_direct_translation") {
179 SECURE_DIR_TRANSLATION = prop->enums[i].value;
180 }
181 }
182 secure_modes_populated = true;
183 }
184}
185
186static InlineRotationVersion PopulateInlineRotationVersion(uint32_t ver) {
187 switch (ver) {
188 case 0x0000: return InlineRotationVersion::kInlineRotationNone;
189 case 0x0001: return InlineRotationVersion::kInlineRotationV1;
190 default: return InlineRotationVersion::kInlineRotationNone;
191 }
192}
193
194static QSEEDStepVersion PopulateQseedStepVersion(uint32_t hw_ver) {
195 switch (hw_ver) {
196 case 0x1003: return QSEEDStepVersion::V3;
197 case 0x1004: return QSEEDStepVersion::V4;
198 case 0x2004: return QSEEDStepVersion::V3LITE_V4;
199 case 0x3000: return QSEEDStepVersion::V3LITE_V5;
200 // default value. also corresponds to (hw_ver == 0x1002)
201 default: return QSEEDStepVersion::V2;
202 }
203}
204
205static void PopulateMultiRectModes(drmModePropertyRes *prop) {
206 static bool multirect_modes_populated = false;
207 if (!multirect_modes_populated) {
208 for (auto i = 0; i < prop->count_enums; i++) {
209 string enum_name(prop->enums[i].name);
210 if (enum_name == "none") {
211 MULTIRECT_NONE = prop->enums[i].value;
212 } else if (enum_name == "parallel") {
213 MULTIRECT_PARALLEL = prop->enums[i].value;
214 } else if (enum_name == "serial") {
215 MULTIRECT_SERIAL = prop->enums[i].value;
216 }
217 }
218 multirect_modes_populated = true;
219 }
220}
221
222#define __CLASS__ "DRMPlaneManager"
223
224DRMPlaneManager::DRMPlaneManager(int fd) : fd_(fd) {}
225
226void DRMPlaneManager::Init() {
227 drmModePlaneRes *resource = drmModeGetPlaneResources(fd_);
228 if (!resource) {
229 return;
230 }
231
232 for (uint32_t i = 0; i < resource->count_planes; i++) {
233 // The enumeration order itself is the priority from high to low
234 unique_ptr<DRMPlane> plane(new DRMPlane(fd_, i));
235 drmModePlane *libdrm_plane = drmModeGetPlane(fd_, resource->planes[i]);
236 if (libdrm_plane) {
237 plane->InitAndParse(libdrm_plane);
238 plane_pool_[resource->planes[i]] = std::move(plane);
239 } else {
240 DRM_LOGE("Critical error: drmModeGetPlane() failed for plane %d.", resource->planes[i]);
241 }
242 }
243
244 drmModeFreePlaneResources(resource);
245}
246
247void DRMPlaneManager::DumpByID(uint32_t id) {
248 plane_pool_.at(id)->Dump();
249}
250
251void DRMPlaneManager::Perform(DRMOps code, uint32_t obj_id, drmModeAtomicReq *req, va_list args) {
252 auto it = plane_pool_.find(obj_id);
253 if (it == plane_pool_.end()) {
254 DRM_LOGE("Invalid plane id %d", obj_id);
255 return;
256 }
257
258 if (code == DRMOps::PLANE_SET_SCALER_CONFIG) {
259 if (it->second->ConfigureScalerLUT(req, dir_lut_blob_id_, cir_lut_blob_id_,
260 sep_lut_blob_id_)) {
261 DRM_LOGD("Plane %d: Configuring scaler LUTs", obj_id);
262 }
263 }
264
265 it->second->Perform(code, req, args);
266}
267
268void DRMPlaneManager::Perform(DRMOps code, drmModeAtomicReq *req, uint32_t obj_id, ...) {
269 va_list args;
270 va_start(args, obj_id);
271 Perform(code, obj_id, req, args);
272 va_end(args);
273}
274
275void DRMPlaneManager::DumpAll() {
276 for (uint32_t i = 0; i < plane_pool_.size(); i++) {
277 plane_pool_[i]->Dump();
278 }
279}
280
281void DRMPlaneManager::GetPlanesInfo(DRMPlanesInfo *info) {
282 for (auto &plane : plane_pool_) {
283 info->push_back(std::make_pair(plane.first, plane.second->GetPlaneTypeInfo()));
284 }
285}
286
287void DRMPlaneManager::UnsetUnusedPlanes(uint32_t crtc_id, drmModeAtomicReq *req) {
288 // Unset planes that were assigned to the crtc referred to by crtc_id but are not requested
289 // in this round
290 for (auto &plane : plane_pool_) {
291 uint32_t assigned_crtc = 0;
292 uint32_t requested_crtc = 0;
293 plane.second->GetAssignedCrtc(&assigned_crtc);
294 plane.second->GetRequestedCrtc(&requested_crtc);
295 if (assigned_crtc == crtc_id && requested_crtc == 0) {
296 plane.second->Unset(req);
297 }
298 }
299}
300
301void DRMPlaneManager::RetainPlanes(uint32_t crtc_id) {
302 for (auto &plane : plane_pool_) {
303 uint32_t assigned_crtc = 0;
304 plane.second->GetAssignedCrtc(&assigned_crtc);
305 if (assigned_crtc == crtc_id) {
306 // Pretend this plane was requested by client
307 plane.second->SetRequestedCrtc(crtc_id);
308 const uint32_t plane_id = plane.first;
309 DRM_LOGD("Plane %d: Retaining on CRTC %d", plane_id, crtc_id);
310 }
311 }
312}
313
314void DRMPlaneManager::PostValidate(uint32_t crtc_id, bool success) {
315 for (auto &plane : plane_pool_) {
316 plane.second->PostValidate(crtc_id, success);
317 }
318}
319
320void DRMPlaneManager::PostCommit(uint32_t crtc_id, bool success) {
321 DRM_LOGD("crtc %d", crtc_id);
322 for (auto &plane : plane_pool_) {
323 plane.second->PostCommit(crtc_id, success);
324 }
325}
326
327void DRMPlaneManager::SetScalerLUT(const DRMScalerLUTInfo &lut_info) {
328 if (lut_info.dir_lut_size) {
329 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.dir_lut),
330 lut_info.dir_lut_size, &dir_lut_blob_id_);
331 }
332 if (lut_info.cir_lut_size) {
333 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.cir_lut),
334 lut_info.cir_lut_size, &cir_lut_blob_id_);
335 }
336 if (lut_info.sep_lut_size) {
337 drmModeCreatePropertyBlob(fd_, reinterpret_cast<void *>(lut_info.sep_lut),
338 lut_info.sep_lut_size, &sep_lut_blob_id_);
339 }
340}
341
342void DRMPlaneManager::UnsetScalerLUT() {
343 if (dir_lut_blob_id_) {
344 drmModeDestroyPropertyBlob(fd_, dir_lut_blob_id_);
345 dir_lut_blob_id_ = 0;
346 }
347 if (cir_lut_blob_id_) {
348 drmModeDestroyPropertyBlob(fd_, cir_lut_blob_id_);
349 cir_lut_blob_id_ = 0;
350 }
351 if (sep_lut_blob_id_) {
352 drmModeDestroyPropertyBlob(fd_, sep_lut_blob_id_);
353 sep_lut_blob_id_ = 0;
354 }
355}
356
357// ==============================================================================================//
358
359#undef __CLASS__
360#define __CLASS__ "DRMPlane"
361
362DRMPlane::DRMPlane(int fd, uint32_t priority) : fd_(fd), priority_(priority) {}
363
364DRMPlane::~DRMPlane() {
365 drmModeFreePlane(drm_plane_);
366}
367
368void DRMPlane::GetTypeInfo(const PropertyMap &prop_map) {
369 uint64_t blob_id;
370 drmModePropertyRes *prop;
371 DRMPlaneTypeInfo *info = &plane_type_info_;
372 // Ideally we should check if this property type is a blob and then proceed.
373 std::tie(blob_id, prop) = prop_map.at(DRMProperty::CAPABILITIES);
374 drmModePropertyBlobRes *blob = drmModeGetPropertyBlob(fd_, blob_id);
375 if (!blob) {
376 return;
377 }
378
379 const char *fmt_str = reinterpret_cast<const char *>(blob->data);
380 info->max_linewidth = 2560;
381 info->max_scaler_linewidth = 2560;
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530382 info->max_upscale = 1;
383 info->max_downscale = 1;
384 info->max_horizontal_deci = 0;
385 info->max_vertical_deci = 0;
386 info->master_plane_id = 0;
387 if (info->type == DRMPlaneType::CURSOR) {
388 info->max_linewidth = 128;
389 }
390 // TODO(user): change default to V2 once we start getting V3 via capabilities blob
391 info->qseed3_version = QSEEDStepVersion::V3;
392 info->has_excl_rect = has_excl_rect_;
393
394 // We may have multiple lines with each one dedicated for something specific
395 // like formats etc
396 stringstream stream(fmt_str);
397 string line = {};
398 string pixel_formats = "pixel_formats=";
399 string max_linewidth = "max_linewidth=";
400 string max_upscale = "max_upscale=";
401 string max_downscale = "max_downscale=";
402 string max_horizontal_deci = "max_horizontal_deci=";
403 string max_vertical_deci = "max_vertical_deci=";
404 string master_plane_id = "primary_smart_plane_id=";
405 string max_pipe_bw = "max_per_pipe_bw=";
Alex Sarraf2092d782019-06-07 17:32:21 -0700406 string max_pipe_bw_high = "max_per_pipe_bw_high=";
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530407 string scaler_version = "scaler_step_ver=";
408 string block_sec_ui = "block_sec_ui=";
409 string true_inline_rot_rev = "true_inline_rot_rev=";
410 string inline_rot_pixel_formats = "inline_rot_pixel_formats=";
Alex Sarrafee54c192019-04-02 17:19:49 -0700411 string true_inline_dwnscale_rt_numerator = "true_inline_dwnscale_rt_numerator=";
412 string true_inline_dwnscale_rt_denominator = "true_inline_dwnscale_rt_denominator=";
Alex Sarraf223f2f72019-01-10 17:30:45 -0800413 string true_inline_max_height = "true_inline_max_height=";
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530414
415 while (std::getline(stream, line)) {
416 if (line.find(inline_rot_pixel_formats) != string::npos) {
417 vector<pair<uint32_t, uint64_t>> inrot_formats_supported;
418 ParseFormats(line.erase(0, inline_rot_pixel_formats.length()), &inrot_formats_supported);
419 info->inrot_fmts_supported = std::move(inrot_formats_supported);
420 } else if (line.find(pixel_formats) != string::npos) {
421 vector<pair<uint32_t, uint64_t>> formats_supported;
422 ParseFormats(line.erase(0, pixel_formats.length()), &formats_supported);
423 info->formats_supported = std::move(formats_supported);
424 } else if (line.find(max_linewidth) != string::npos) {
425 info->max_linewidth = std::stoi(line.erase(0, max_linewidth.length()));
426 } else if (line.find(max_upscale) != string::npos) {
427 info->max_upscale = std::stoi(line.erase(0, max_upscale.length()));
428 } else if (line.find(max_downscale) != string::npos) {
429 info->max_downscale = std::stoi(line.erase(0, max_downscale.length()));
430 } else if (line.find(max_horizontal_deci) != string::npos) {
431 info->max_horizontal_deci = std::stoi(line.erase(0, max_horizontal_deci.length()));
432 } else if (line.find(max_vertical_deci) != string::npos) {
433 info->max_vertical_deci = std::stoi(line.erase(0, max_vertical_deci.length()));
434 } else if (line.find(master_plane_id) != string::npos) {
435 info->master_plane_id = std::stoi(line.erase(0, master_plane_id.length()));
436 DRM_LOGI("info->master_plane_id: detected master_plane=%d", info->master_plane_id);
437 } else if (line.find(max_pipe_bw) != string::npos) {
438 info->max_pipe_bandwidth = std::stoull(line.erase(0, max_pipe_bw.length()));
Alex Sarraf2092d782019-06-07 17:32:21 -0700439 } else if (line.find(max_pipe_bw_high) != string::npos) {
440 info->max_pipe_bandwidth_high = std::stoull(line.erase(0, max_pipe_bw_high.length()));
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530441 } else if (line.find(scaler_version) != string::npos) {
442 info->qseed3_version =
443 PopulateQseedStepVersion(std::stoi(line.erase(0, scaler_version.length())));
444 } else if (line.find(block_sec_ui) != string::npos) {
445 info->block_sec_ui = !!(std::stoi(line.erase(0, block_sec_ui.length())));
446 } else if (line.find(true_inline_rot_rev) != string::npos) {
447 info->inrot_version =
448 PopulateInlineRotationVersion(std::stoi(line.erase(0, true_inline_rot_rev.length())));
Alex Sarrafee54c192019-04-02 17:19:49 -0700449 } else if (line.find(true_inline_dwnscale_rt_numerator) != string::npos) {
450 info->true_inline_dwnscale_rt_num = std::stof(line.erase(0,
451 true_inline_dwnscale_rt_numerator.length()));
452 } else if (line.find(true_inline_dwnscale_rt_denominator) != string::npos) {
453 info->true_inline_dwnscale_rt_denom = std::stof(line.erase(0,
454 true_inline_dwnscale_rt_denominator.length()));
Alex Sarraf223f2f72019-01-10 17:30:45 -0800455 } else if (line.find(true_inline_max_height) != string::npos) {
456 info->max_rotation_linewidth = std::stoi(line.erase(0, true_inline_max_height.length()));
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530457 }
458 }
459
460 info->max_scaler_linewidth = (QSEEDStepVersion::V4 == info->qseed3_version) ? 2560 :
461 info->max_linewidth;
462 drmModeFreePropertyBlob(blob);
463}
464
465void DRMPlane::ParseProperties() {
466 // Map of property name to current value and property info pointer
467 PropertyMap prop_map;
468 bool csc = false;
469 bool scaler = false;
470 bool cursor = false;
471 drmModeObjectProperties *props =
472 drmModeObjectGetProperties(fd_, drm_plane_->plane_id, DRM_MODE_OBJECT_PLANE);
473 if (!props || !props->props || !props->prop_values) {
474 drmModeFreeObjectProperties(props);
475 return;
476 }
477
478 for (uint32_t j = 0; j < props->count_props; j++) {
479 drmModePropertyRes *info = drmModeGetProperty(fd_, props->props[j]);
480 if (!info) {
481 continue;
482 }
483
484 string property_name(info->name);
485 DRMProperty prop_enum = prop_mgr_.GetPropertyEnum(property_name);
486 if (prop_enum == DRMProperty::INVALID) {
487 DRM_LOGD("DRMProperty %s missing from global property mapping", info->name);
488 drmModeFreeProperty(info);
489 continue;
490 }
491
492 if (prop_enum == DRMProperty::EXCL_RECT) {
493 has_excl_rect_ = true;
494 }
495 if (prop_enum == DRMProperty::ROTATION) {
496 PopulateReflect(info);
497 } else if (prop_enum == DRMProperty::FB_TRANSLATION_MODE) {
498 PopulateSecureModes(info);
499 } else if (prop_enum == DRMProperty::MULTIRECT_MODE) {
500 PopulateMultiRectModes(info);
501 plane_type_info_.multirect_prop_present = true;
502 }
503
504 prop_mgr_.SetPropertyId(prop_enum, info->prop_id);
505 prop_map[prop_enum] = std::make_tuple(props->prop_values[j], info);
506 csc = prop_enum == DRMProperty::CSC_V1 ? true : csc;
507 scaler = (prop_enum == DRMProperty::SCALER_V1 || prop_enum == DRMProperty::SCALER_V2) \
508 ? true : scaler;
509 cursor = (prop_enum == DRMProperty::TYPE && props->prop_values[j] == DRM_PLANE_TYPE_CURSOR) \
510 ? true : cursor;
511
512 // Tone mapping properties.
513 if (prop_enum == DRMProperty::INVERSE_PMA) {
514 plane_type_info_.inverse_pma = true;
515 }
516
517 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::CSC_DMA_V1 &&
518 (uint32_t)prop_enum <= (uint32_t)DRMProperty::CSC_DMA_V1) {
519 plane_type_info_.dgm_csc_version =
520 ((uint32_t)prop_enum - (uint32_t)DRMProperty::CSC_DMA_V1 + 1);
521 }
522
523 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 &&
524 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5) {
525 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_IGC] =
526 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_IGC_V5 + 5);
527 }
528 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 &&
529 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5) {
530 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::DMA_1D_GC] =
531 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_DGM_1D_LUT_GC_V5 + 5);
532 }
533 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 &&
Sushil Chauhane273a532019-03-19 12:34:01 -0700534 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V6) {
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530535 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_1D_IGC] =
536 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_1D_LUT_IGC_V5 + 5);
537 }
538 if ((uint32_t)prop_enum >= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 &&
Sushil Chauhane273a532019-03-19 12:34:01 -0700539 (uint32_t)prop_enum <= (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V6) {
Gousemoodhin Nadaf2e3eb3f2018-12-12 15:25:22 +0530540 plane_type_info_.tonemap_lut_version_map[DRMTonemapLutType::VIG_3D_GAMUT] =
541 ((uint32_t)prop_enum - (uint32_t)DRMProperty::SDE_VIG_3D_LUT_GAMUT_V5 + 5);
542 }
543 }
544
545 DRMPlaneType type = DRMPlaneType::DMA;
546 if (csc && scaler) {
547 type = DRMPlaneType::VIG;
548 } else if (cursor) {
549 type = DRMPlaneType::CURSOR;
550 }
551
552 plane_type_info_.type = type;
553 GetTypeInfo(prop_map);
554
555 for (auto &prop : prop_map) {
556 drmModeFreeProperty(std::get<1>(prop.second));
557 }
558
559 drmModeFreeObjectProperties(props);
560}
561
562void DRMPlane::InitAndParse(drmModePlane *plane) {
563 drm_plane_ = plane;
564 ParseProperties();
565
566 unique_ptr<DRMPPManager> pp_mgr(new DRMPPManager(fd_));
567 pp_mgr_ = std::move(pp_mgr);
568 pp_mgr_->Init(prop_mgr_, DRM_MODE_OBJECT_PLANE);
569}
570
571bool DRMPlane::ConfigureScalerLUT(drmModeAtomicReq *req, uint32_t dir_lut_blob_id,
572 uint32_t cir_lut_blob_id, uint32_t sep_lut_blob_id) {
573 if (plane_type_info_.type != DRMPlaneType::VIG || is_lut_configured_) {
574 return false;
575 }
576
577 if (dir_lut_blob_id) {
578 AddProperty(req, drm_plane_->plane_id,
579 prop_mgr_.GetPropertyId(DRMProperty::LUT_ED),
580 dir_lut_blob_id, false /* cache */, tmp_prop_val_map_);
581 }
582 if (cir_lut_blob_id) {
583 AddProperty(req, drm_plane_->plane_id,
584 prop_mgr_.GetPropertyId(DRMProperty::LUT_CIR),
585 cir_lut_blob_id, false /* cache */, tmp_prop_val_map_);
586 }
587 if (sep_lut_blob_id) {
588 AddProperty(req, drm_plane_->plane_id,
589 prop_mgr_.GetPropertyId(DRMProperty::LUT_SEP),
590 sep_lut_blob_id, false /* cache */, tmp_prop_val_map_);
591 }
592
593 return true;
594}
595
596void DRMPlane::SetExclRect(drmModeAtomicReq *req, DRMRect rect) {
597 auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::EXCL_RECT);
598 drm_clip_rect clip_rect;
599 SetRect(rect, &clip_rect);
600 excl_rect_copy_ = clip_rect;
601 AddProperty(req, drm_plane_->plane_id, prop_id, reinterpret_cast<uint64_t>
602 (&excl_rect_copy_), false /* cache */, tmp_prop_val_map_);
603 DRM_LOGD("Plane %d: Setting exclusion rect [x,y,w,h][%d,%d,%d,%d]", drm_plane_->plane_id,
604 clip_rect.x1, clip_rect.y1, (clip_rect.x2 - clip_rect.x1),
605 (clip_rect.y2 - clip_rect.y1));
606}
607
608bool DRMPlane::SetCscConfig(drmModeAtomicReq *req, DRMCscType csc_type) {
609 if (plane_type_info_.type != DRMPlaneType::VIG) {
610 return false;
611 }
612
613 if (csc_type > kCscTypeMax) {
614 return false;
615 }
616
617 if (!prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_V1)) {
618 return false;
619 }
620
621 auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::CSC_V1);
622 if (csc_type == kCscTypeMax) {
623 AddProperty(req, drm_plane_->plane_id, prop_id, 0, false /* cache */, tmp_prop_val_map_);
624 } else {
625 csc_config_copy_ = csc_10bit_convert[csc_type];
626 AddProperty(req, drm_plane_->plane_id, prop_id,
627 reinterpret_cast<uint64_t>(&csc_config_copy_), false /* cache */,
628 tmp_prop_val_map_);
629 }
630
631 return true;
632}
633
634bool DRMPlane::SetScalerConfig(drmModeAtomicReq *req, uint64_t handle) {
635 if (plane_type_info_.type != DRMPlaneType::VIG) {
636 return false;
637 }
638
639 if (prop_mgr_.IsPropertyAvailable(DRMProperty::SCALER_V2)) {
640 auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::SCALER_V2);
641 sde_drm_scaler_v2 *scaler_v2_config = reinterpret_cast<sde_drm_scaler_v2 *>(handle);
642 uint64_t scaler_data = 0;
643 // The address needs to be valid even after async commit, since we are sending address to
644 // driver directly, instead of blob. So we need to copy over contents that client sent. Client
645 // may have sent an address of object on stack which will be released after this call.
646 scaler_v2_config_copy_ = *scaler_v2_config;
647 if (scaler_v2_config_copy_.enable) {
648 scaler_data = reinterpret_cast<uint64_t>(&scaler_v2_config_copy_);
649 }
650 AddProperty(req, drm_plane_->plane_id, prop_id, scaler_data, false /* cache */,
651 tmp_prop_val_map_);
652 return true;
653 }
654
655 return false;
656}
657
658void DRMPlane::SetDecimation(drmModeAtomicReq *req, uint32_t prop_id, uint32_t prop_value) {
659 if (plane_type_info_.type == DRMPlaneType::DMA || plane_type_info_.master_plane_id) {
660 // if value is 0, client is just trying to clear previous decimation, so bail out silently
661 if (prop_value > 0) {
662 DRM_LOGE("Plane %d: Setting decimation %d is not supported.", drm_plane_->plane_id,
663 prop_value);
664 }
665 return;
666 }
667
668 // TODO(user): Currently a ViG plane in smart DMA mode could receive a non-zero decimation value
669 // but there is no good way to catch. In any case fix will be in client
670 AddProperty(req, drm_plane_->plane_id, prop_id, prop_value, true /* cache */, tmp_prop_val_map_);
671 DRM_LOGD("Plane %d: Setting decimation %d", drm_plane_->plane_id, prop_value);
672}
673
674void DRMPlane::PostValidate(uint32_t crtc_id, bool /*success*/) {
675 if (requested_crtc_id_ == crtc_id) {
676 SetRequestedCrtc(0);
677 tmp_prop_val_map_ = committed_prop_val_map_;
678 }
679}
680
681void DRMPlane::PostCommit(uint32_t crtc_id, bool success) {
682 DRM_LOGD("crtc %d", crtc_id);
683 if (!success) {
684 // To reset
685 PostValidate(crtc_id, success);
686 return;
687 }
688
689 uint32_t assigned_crtc = 0;
690 uint32_t requested_crtc = 0;
691
692 GetAssignedCrtc(&assigned_crtc);
693 GetRequestedCrtc(&requested_crtc);
694
695 // In future, it is possible that plane is already attached in case of continuous splash. This
696 // will cause the first commit to only unstage pipes. We want to mark luts as configured only
697 // when they really are, which typically happens if a crtc is requested for a plane
698 if (requested_crtc == crtc_id && !is_lut_configured_) {
699 is_lut_configured_ = true;
700 }
701
702 if (requested_crtc && assigned_crtc && requested_crtc != assigned_crtc) {
703 // We should never be here
704 DRM_LOGE("Found plane %d switching from crtc %d to crtc %d", drm_plane_->plane_id,
705 assigned_crtc, requested_crtc);
706 }
707
708 // If we have set a pipe OR unset a pipe during commit, update states
709 if (requested_crtc == crtc_id || assigned_crtc == crtc_id) {
710 committed_prop_val_map_ = tmp_prop_val_map_;
711 SetAssignedCrtc(requested_crtc);
712 SetRequestedCrtc(0);
713 }
714}
715
716void DRMPlane::Perform(DRMOps code, drmModeAtomicReq *req, va_list args) {
717 uint32_t prop_id = 0;
718 uint32_t obj_id = drm_plane_->plane_id;
719
720 switch (code) {
721 // TODO(user): Check if these exist in map before attempting to access
722 case DRMOps::PLANE_SET_SRC_RECT: {
723 DRMRect rect = va_arg(args, DRMRect);
724 // source co-ordinates accepted by DRM are 16.16 fixed point
725 prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_X);
726 AddProperty(req, obj_id, prop_id, rect.left << 16, true /* cache */, tmp_prop_val_map_);
727 prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_Y);
728 AddProperty(req, obj_id, prop_id, rect.top << 16, true /* cache */, tmp_prop_val_map_);
729 prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_W);
730 AddProperty(req, obj_id, prop_id, (rect.right - rect.left) << 16, true /* cache */,
731 tmp_prop_val_map_);
732 prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_H);
733 AddProperty(req, obj_id, prop_id, (rect.bottom - rect.top) << 16, true /* cache */,
734 tmp_prop_val_map_);
735 DRM_LOGV("Plane %d: Setting crop [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
736 rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
737 } break;
738
739 case DRMOps::PLANE_SET_DST_RECT: {
740 DRMRect rect = va_arg(args, DRMRect);
741 prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_X);
742 AddProperty(req, obj_id, prop_id, rect.left, true /* cache */, tmp_prop_val_map_);
743 prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_Y);
744 AddProperty(req, obj_id, prop_id, rect.top, true /* cache */, tmp_prop_val_map_);
745 prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_W);
746 AddProperty(req, obj_id, prop_id, (rect.right - rect.left), true /* cache */,
747 tmp_prop_val_map_);
748 prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_H);
749 AddProperty(req, obj_id, prop_id, (rect.bottom - rect.top), true /* cache */,
750 tmp_prop_val_map_);
751 DRM_LOGV("Plane %d: Setting dst [x,y,w,h][%d,%d,%d,%d]", obj_id, rect.left,
752 rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
753 } break;
754 case DRMOps::PLANE_SET_EXCL_RECT: {
755 DRMRect excl_rect = va_arg(args, DRMRect);
756 SetExclRect(req, excl_rect);
757 } break;
758
759 case DRMOps::PLANE_SET_ZORDER: {
760 uint32_t zpos = va_arg(args, uint32_t);
761 prop_id = prop_mgr_.GetPropertyId(DRMProperty::ZPOS);
762 AddProperty(req, obj_id, prop_id, zpos, true /* cache */, tmp_prop_val_map_);
763 DRM_LOGD("Plane %d: Setting z %d", obj_id, zpos);
764 } break;
765
766 case DRMOps::PLANE_SET_ROTATION: {
767 uint32_t rot_bit_mask = va_arg(args, uint32_t);
768 uint32_t drm_rot_bit_mask = 0;
769 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_H)) {
770 drm_rot_bit_mask |= 1 << REFLECT_X;
771 }
772 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::FLIP_V)) {
773 drm_rot_bit_mask |= 1 << REFLECT_Y;
774 }
775 if (rot_bit_mask & static_cast<uint32_t>(DRMRotation::ROT_90)) {
776 drm_rot_bit_mask |= 1 << ROTATE_90;
777 } else {
778 drm_rot_bit_mask |= 1 << ROTATE_0;
779 }
780 prop_id = prop_mgr_.GetPropertyId(DRMProperty::ROTATION);
781 AddProperty(req, obj_id, prop_id, drm_rot_bit_mask, true /* cache */, tmp_prop_val_map_);
782 DRM_LOGV("Plane %d: Setting rotation mask %x", obj_id, drm_rot_bit_mask);
783 } break;
784
785 case DRMOps::PLANE_SET_ALPHA: {
786 uint32_t alpha = va_arg(args, uint32_t);
787 prop_id = prop_mgr_.GetPropertyId(DRMProperty::ALPHA);
788 AddProperty(req, obj_id, prop_id, alpha, true /* cache */, tmp_prop_val_map_);
789 DRM_LOGV("Plane %d: Setting alpha %d", obj_id, alpha);
790 } break;
791
792 case DRMOps::PLANE_SET_BLEND_TYPE: {
793 uint32_t blending = va_arg(args, uint32_t);
794 prop_id = prop_mgr_.GetPropertyId(DRMProperty::BLEND_OP);
795 AddProperty(req, obj_id, prop_id, blending, true /* cache */, tmp_prop_val_map_);
796 DRM_LOGV("Plane %d: Setting blending %d", obj_id, blending);
797 } break;
798
799 case DRMOps::PLANE_SET_H_DECIMATION: {
800 uint32_t deci = va_arg(args, uint32_t);
801 prop_id = prop_mgr_.GetPropertyId(DRMProperty::H_DECIMATE);
802 SetDecimation(req, prop_id, deci);
803 } break;
804
805 case DRMOps::PLANE_SET_V_DECIMATION: {
806 uint32_t deci = va_arg(args, uint32_t);
807 prop_id = prop_mgr_.GetPropertyId(DRMProperty::V_DECIMATE);
808 SetDecimation(req, prop_id, deci);
809 } break;
810
811 case DRMOps::PLANE_SET_SRC_CONFIG: {
812 bool src_config = va_arg(args, uint32_t);
813 prop_id = prop_mgr_.GetPropertyId(DRMProperty::SRC_CONFIG);
814 AddProperty(req, obj_id, prop_id, src_config, true /* cache */, tmp_prop_val_map_);
815 DRM_LOGV("Plane %d: Setting src_config flags-%x", obj_id, src_config);
816 } break;
817
818 case DRMOps::PLANE_SET_CRTC: {
819 uint32_t crtc_id = va_arg(args, uint32_t);
820 prop_id = prop_mgr_.GetPropertyId(DRMProperty::CRTC_ID);
821 AddProperty(req, obj_id, prop_id, crtc_id, true /* cache */, tmp_prop_val_map_);
822 SetRequestedCrtc(crtc_id);
823 DRM_LOGV("Plane %d: Setting crtc %d", obj_id, crtc_id);
824 } break;
825
826 case DRMOps::PLANE_SET_FB_ID: {
827 uint32_t fb_id = va_arg(args, uint32_t);
828 prop_id = prop_mgr_.GetPropertyId(DRMProperty::FB_ID);
829 AddProperty(req, obj_id, prop_id, fb_id, true /* cache */, tmp_prop_val_map_);
830 DRM_LOGV("Plane %d: Setting fb_id %d", obj_id, fb_id);
831 } break;
832
833 case DRMOps::PLANE_SET_ROT_FB_ID: {
834 uint32_t fb_id = va_arg(args, uint32_t);
835 prop_id = prop_mgr_.GetPropertyId(DRMProperty::ROT_FB_ID);
836 drmModeAtomicAddProperty(req, obj_id, prop_id, fb_id);
837 DRM_LOGV("Plane %d: Setting rot_fb_id %d", obj_id, fb_id);
838 } break;
839
840 case DRMOps::PLANE_SET_INPUT_FENCE: {
841 int fence = va_arg(args, int);
842 prop_id = prop_mgr_.GetPropertyId(DRMProperty::INPUT_FENCE);
843 AddProperty(req, obj_id, prop_id, fence, false /* cache */, tmp_prop_val_map_);
844 DRM_LOGV("Plane %d: Setting input fence %d", obj_id, fence);
845 } break;
846
847 case DRMOps::PLANE_SET_SCALER_CONFIG: {
848 uint64_t handle = va_arg(args, uint64_t);
849 if (SetScalerConfig(req, handle)) {
850 DRM_LOGV("Plane %d: Setting scaler config", obj_id);
851 }
852 } break;
853
854 case DRMOps::PLANE_SET_FB_SECURE_MODE: {
855 int secure_mode = va_arg(args, int);
856 uint32_t fb_secure_mode = NON_SECURE;
857 switch (secure_mode) {
858 case (int)DRMSecureMode::NON_SECURE:
859 fb_secure_mode = NON_SECURE;
860 break;
861 case (int)DRMSecureMode::SECURE:
862 fb_secure_mode = SECURE;
863 break;
864 case (int)DRMSecureMode::NON_SECURE_DIR_TRANSLATION:
865 fb_secure_mode = NON_SECURE_DIR_TRANSLATION;
866 break;
867 case (int)DRMSecureMode::SECURE_DIR_TRANSLATION:
868 fb_secure_mode = SECURE_DIR_TRANSLATION;
869 break;
870 default:
871 DRM_LOGE("Invalid secure mode %d to set on plane %d", secure_mode, obj_id);
872 break;
873 }
874
875 prop_id = prop_mgr_.GetPropertyId(DRMProperty::FB_TRANSLATION_MODE);
876 AddProperty(req, obj_id, prop_id, fb_secure_mode, true /* cache */, tmp_prop_val_map_);
877 DRM_LOGD("Plane %d: Setting FB secure mode %d", obj_id, fb_secure_mode);
878 } break;
879
880 case DRMOps::PLANE_SET_CSC_CONFIG: {
881 uint32_t* csc_type = va_arg(args, uint32_t*);
882 if (csc_type) {
883 SetCscConfig(req, (DRMCscType)*csc_type);
884 }
885 } break;
886
887 case DRMOps::PLANE_SET_MULTIRECT_MODE: {
888 DRMMultiRectMode drm_multirect_mode = (DRMMultiRectMode)va_arg(args, uint32_t);
889 SetMultiRectMode(req, drm_multirect_mode);
890 } break;
891
892 case DRMOps::PLANE_SET_INVERSE_PMA: {
893 uint32_t pma = va_arg(args, uint32_t);
894 prop_id = prop_mgr_.GetPropertyId(DRMProperty::INVERSE_PMA);
895 AddProperty(req, obj_id, prop_id, pma, true /* cache */, tmp_prop_val_map_);
896 DRM_LOGD("Plane %d: %s inverse pma", obj_id, pma ? "Setting" : "Resetting");
897 } break;
898
899 case DRMOps::PLANE_SET_DGM_CSC_CONFIG: {
900 uint64_t handle = va_arg(args, uint64_t);
901 if (SetDgmCscConfig(req, handle)) {
902 DRM_LOGD("Plane %d: Setting Csc Lut config", obj_id);
903 }
904 } break;
905
906 case DRMOps::PLANE_SET_POST_PROC: {
907 DRMPPFeatureInfo *data = va_arg(args, DRMPPFeatureInfo*);
908 if (data) {
909 DRM_LOGD("Plane %d: Set post proc", obj_id);
910 pp_mgr_->SetPPFeature(req, obj_id, *data);
911 }
912 } break;
913
914 default:
915 DRM_LOGE("Invalid opcode %d for DRM Plane %d", code, obj_id);
916 }
917}
918
919void DRMPlane::PerformWrapper(DRMOps code, drmModeAtomicReq *req, ...) {
920 va_list args;
921 va_start(args, req);
922 Perform(code, req, args);
923 va_end(args);
924}
925
926void DRMPlane::Dump() {
927 DRM_LOGE(
928 "id: %d\tcrtc id: %d\tfb id: %d\tCRTC_xy: %dx%d\txy: %dx%d\tgamma "
929 "size: %d\tpossible crtc: 0x%x\n",
930 drm_plane_->plane_id, drm_plane_->crtc_id, drm_plane_->fb_id, drm_plane_->crtc_x,
931 drm_plane_->crtc_y, drm_plane_->x, drm_plane_->y, drm_plane_->gamma_size,
932 drm_plane_->possible_crtcs);
933 DRM_LOGE("Format Suported: \n");
934 for (uint32_t i = 0; i < (uint32_t)drm_plane_->count_formats; i++)
935 DRM_LOGE(" %4.4s", (char *)&drm_plane_->formats[i]);
936}
937
938void DRMPlane::SetMultiRectMode(drmModeAtomicReq *req, DRMMultiRectMode drm_multirect_mode) {
939 if (!plane_type_info_.multirect_prop_present) {
940 return;
941 }
942 uint32_t obj_id = drm_plane_->plane_id;
943 uint32_t multirect_mode = MULTIRECT_NONE;
944 switch (drm_multirect_mode) {
945 case DRMMultiRectMode::NONE:
946 multirect_mode = MULTIRECT_NONE;
947 break;
948 case DRMMultiRectMode::PARALLEL:
949 multirect_mode = MULTIRECT_PARALLEL;
950 break;
951 case DRMMultiRectMode::SERIAL:
952 multirect_mode = MULTIRECT_SERIAL;
953 break;
954 default:
955 DRM_LOGE("Invalid multirect mode %d to set on plane %d", drm_multirect_mode, obj_id);
956 break;
957 }
958 auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::MULTIRECT_MODE);
959 AddProperty(req, obj_id, prop_id, multirect_mode, true /* cache */, tmp_prop_val_map_);
960 DRM_LOGD("Plane %d: Setting multirect_mode %d", obj_id, multirect_mode);
961}
962
963void DRMPlane::Unset(drmModeAtomicReq *req) {
964 DRM_LOGD("Plane %d: Unsetting from crtc %d", drm_plane_->plane_id, assigned_crtc_id_);
965 PerformWrapper(DRMOps::PLANE_SET_FB_ID, req, 0);
966 PerformWrapper(DRMOps::PLANE_SET_CRTC, req, 0);
967 DRMRect rect = {0, 0, 0, 0};
968 PerformWrapper(DRMOps::PLANE_SET_SRC_RECT, req, rect);
969 PerformWrapper(DRMOps::PLANE_SET_DST_RECT, req, rect);
970 PerformWrapper(DRMOps::PLANE_SET_EXCL_RECT, req, rect);
971 if (plane_type_info_.inverse_pma) {
972 PerformWrapper(DRMOps::PLANE_SET_INVERSE_PMA, req, 0);
973 }
974 tmp_prop_val_map_.clear();
975 committed_prop_val_map_.clear();
976}
977
978bool DRMPlane::SetDgmCscConfig(drmModeAtomicReq *req, uint64_t handle) {
979 if (plane_type_info_.type == DRMPlaneType::DMA &&
980 prop_mgr_.IsPropertyAvailable(DRMProperty::CSC_DMA_V1)) {
981 auto prop_id = prop_mgr_.GetPropertyId(DRMProperty::CSC_DMA_V1);
982 sde_drm_csc_v1 *csc_v1 = reinterpret_cast<sde_drm_csc_v1 *>(handle);
983 uint64_t csc_v1_data = 0;
984 sde_drm_csc_v1 csc_v1_tmp = {};
985 csc_config_copy_ = *csc_v1;
986 if (std::memcmp(&csc_config_copy_, &csc_v1_tmp, sizeof(sde_drm_csc_v1)) != 0) {
987 csc_v1_data = reinterpret_cast<uint64_t>(&csc_config_copy_);
988 }
989 DRM_LOGV("Dgm CSC = %d", csc_v1_data);
990 AddProperty(req, drm_plane_->plane_id, prop_id,
991 reinterpret_cast<uint64_t>(csc_v1_data), false /* cache */,
992 tmp_prop_val_map_);
993
994 return true;
995 }
996
997 return false;
998}
999
1000} // namespace sde_drm