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