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