1 /*
2 * Copyright (c) 2014 - 2016, 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 #define __STDC_FORMAT_MACROS
31
32 #include <stdio.h>
33 #include <ctype.h>
34 #include <math.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <inttypes.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <linux/fb.h>
43 #include <utils/constants.h>
44 #include <utils/debug.h>
45 #include <utils/sys.h>
46 #include <vector>
47 #include <algorithm>
48 #include <string>
49
50 #include "hw_device.h"
51 #include "hw_info_interface.h"
52
53 #define __CLASS__ "HWDevice"
54
55 using std::string;
56 using std::to_string;
57 using std::fstream;
58
59 namespace sdm {
60
HWDevice(BufferSyncHandler * buffer_sync_handler)61 HWDevice::HWDevice(BufferSyncHandler *buffer_sync_handler)
62 : fb_node_index_(-1), fb_path_("/sys/devices/virtual/graphics/fb"),
63 buffer_sync_handler_(buffer_sync_handler), synchronous_commit_(false) {
64 }
65
Init()66 DisplayError HWDevice::Init() {
67 char device_name[64] = {0};
68
69 // Read the fb node index
70 fb_node_index_ = GetFBNodeIndex(device_type_);
71 if (fb_node_index_ == -1) {
72 DLOGE("%s should be present", device_name_);
73 return kErrorHardware;
74 }
75
76 // Populate Panel Info (Used for Partial Update)
77 PopulateHWPanelInfo();
78 // Populate HW Capabilities
79 hw_resource_ = HWResourceInfo();
80 hw_info_intf_->GetHWResourceInfo(&hw_resource_);
81
82 snprintf(device_name, sizeof(device_name), "%s%d", "/dev/graphics/fb", fb_node_index_);
83 device_fd_ = Sys::open_(device_name, O_RDWR);
84 if (device_fd_ < 0) {
85 DLOGE("open %s failed err = %d errstr = %s", device_name, errno, strerror(errno));
86 return kErrorResources;
87 }
88
89 return HWScale::Create(&hw_scale_, hw_resource_.has_qseed3);
90 }
91
Deinit()92 DisplayError HWDevice::Deinit() {
93 HWScale::Destroy(hw_scale_);
94
95 if (device_fd_ >= 0) {
96 Sys::close_(device_fd_);
97 device_fd_ = -1;
98 }
99
100 return kErrorNone;
101 }
102
GetActiveConfig(uint32_t * active_config)103 DisplayError HWDevice::GetActiveConfig(uint32_t *active_config) {
104 *active_config = 0;
105 return kErrorNone;
106 }
107
GetNumDisplayAttributes(uint32_t * count)108 DisplayError HWDevice::GetNumDisplayAttributes(uint32_t *count) {
109 *count = 1;
110 return kErrorNone;
111 }
112
GetDisplayAttributes(uint32_t index,HWDisplayAttributes * display_attributes)113 DisplayError HWDevice::GetDisplayAttributes(uint32_t index,
114 HWDisplayAttributes *display_attributes) {
115 return kErrorNone;
116 }
117
GetHWPanelInfo(HWPanelInfo * panel_info)118 DisplayError HWDevice::GetHWPanelInfo(HWPanelInfo *panel_info) {
119 *panel_info = hw_panel_info_;
120 return kErrorNone;
121 }
122
SetDisplayAttributes(uint32_t index)123 DisplayError HWDevice::SetDisplayAttributes(uint32_t index) {
124 return kErrorNone;
125 }
126
SetDisplayAttributes(const HWDisplayAttributes & display_attributes)127 DisplayError HWDevice::SetDisplayAttributes(const HWDisplayAttributes &display_attributes) {
128 return kErrorNotSupported;
129 }
130
GetConfigIndex(uint32_t mode,uint32_t * index)131 DisplayError HWDevice::GetConfigIndex(uint32_t mode, uint32_t *index) {
132 return kErrorNone;
133 }
134
PowerOn()135 DisplayError HWDevice::PowerOn() {
136 DTRACE_SCOPED();
137
138 if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_UNBLANK) < 0) {
139 if (errno == ESHUTDOWN) {
140 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
141 return kErrorShutDown;
142 }
143 IOCTL_LOGE(FB_BLANK_UNBLANK, device_type_);
144 return kErrorHardware;
145 }
146
147 return kErrorNone;
148 }
149
PowerOff()150 DisplayError HWDevice::PowerOff() {
151 return kErrorNone;
152 }
153
Doze()154 DisplayError HWDevice::Doze() {
155 return kErrorNone;
156 }
157
DozeSuspend()158 DisplayError HWDevice::DozeSuspend() {
159 return kErrorNone;
160 }
161
Standby()162 DisplayError HWDevice::Standby() {
163 return kErrorNone;
164 }
165
Validate(HWLayers * hw_layers)166 DisplayError HWDevice::Validate(HWLayers *hw_layers) {
167 DTRACE_SCOPED();
168
169 DisplayError error = kErrorNone;
170
171 HWLayersInfo &hw_layer_info = hw_layers->info;
172 LayerStack *stack = hw_layer_info.stack;
173
174 DLOGV_IF(kTagDriverConfig, "************************** %s Validate Input ***********************",
175 device_name_);
176 DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
177
178 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
179 uint32_t &mdp_layer_count = mdp_commit.input_layer_cnt;
180
181 DLOGI_IF(kTagDriverConfig, "left_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.left_roi.x,
182 mdp_commit.left_roi.y, mdp_commit.left_roi.w, mdp_commit.left_roi.h);
183 DLOGI_IF(kTagDriverConfig, "right_roi: x = %d, y = %d, w = %d, h = %d", mdp_commit.right_roi.x,
184 mdp_commit.right_roi.y, mdp_commit.right_roi.w, mdp_commit.right_roi.h);
185
186 for (uint32_t i = 0; i < hw_layer_info.count; i++) {
187 uint32_t layer_index = hw_layer_info.index[i];
188 Layer *layer = stack->layers.at(layer_index);
189 LayerBuffer *input_buffer = layer->input_buffer;
190 HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
191 HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
192 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
193 bool is_rotator_used = (hw_rotator_session->hw_block_count != 0);
194 bool is_cursor_pipe_used = (hw_layer_info.use_hw_cursor & layer->flags.cursor);
195
196 for (uint32_t count = 0; count < 2; count++) {
197 HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
198 HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
199
200 if (hw_rotate_info->valid) {
201 input_buffer = &hw_rotator_session->output_buffer;
202 }
203
204 if (pipe_info->valid) {
205 mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_count];
206 mdp_layer_buffer &mdp_buffer = mdp_layer.buffer;
207
208 mdp_buffer.width = input_buffer->width;
209 mdp_buffer.height = input_buffer->height;
210 mdp_buffer.comp_ratio.denom = 1000;
211 mdp_buffer.comp_ratio.numer = UINT32(hw_layers->config[i].compression * 1000);
212
213 if (layer->flags.solid_fill) {
214 mdp_buffer.format = MDP_ARGB_8888;
215 } else {
216 error = SetFormat(input_buffer->format, &mdp_buffer.format);
217 if (error != kErrorNone) {
218 return error;
219 }
220 }
221 mdp_layer.alpha = layer->plane_alpha;
222 mdp_layer.z_order = UINT16(pipe_info->z_order);
223 mdp_layer.transp_mask = 0xffffffff;
224 SetBlending(layer->blending, &mdp_layer.blend_op);
225 mdp_layer.pipe_ndx = pipe_info->pipe_id;
226 mdp_layer.horz_deci = pipe_info->horizontal_decimation;
227 mdp_layer.vert_deci = pipe_info->vertical_decimation;
228
229 SetRect(pipe_info->src_roi, &mdp_layer.src_rect);
230 SetRect(pipe_info->dst_roi, &mdp_layer.dst_rect);
231 SetMDPFlags(layer, is_rotator_used, is_cursor_pipe_used, &mdp_layer.flags);
232 SetCSC(layer->input_buffer->csc, &mdp_layer.color_space);
233 if (pipe_info->flags & kIGC) {
234 SetIGC(layer->input_buffer, mdp_layer_count);
235 }
236 if (pipe_info->flags & kMultiRect) {
237 mdp_layer.flags |= MDP_LAYER_MULTIRECT_ENABLE;
238 if (pipe_info->flags & kMultiRectParallelMode) {
239 mdp_layer.flags |= MDP_LAYER_MULTIRECT_PARALLEL_MODE;
240 }
241 }
242 mdp_layer.bg_color = layer->solid_fill_color;
243
244 // HWScaleData to MDP driver
245 hw_scale_->SetHWScaleData(pipe_info->scale_data, mdp_layer_count, &mdp_commit,
246 pipe_info->sub_block_type);
247 mdp_layer.scale = hw_scale_->GetScaleDataRef(mdp_layer_count, pipe_info->sub_block_type);
248
249 mdp_layer_count++;
250
251 DLOGV_IF(kTagDriverConfig, "******************* Layer[%d] %s pipe Input ******************",
252 i, count ? "Right" : "Left");
253 DLOGV_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d", mdp_buffer.width, mdp_buffer.height,
254 mdp_buffer.format);
255 DLOGV_IF(kTagDriverConfig, "plane_alpha %d, zorder %d, blending %d, horz_deci %d, "
256 "vert_deci %d, pipe_id = 0x%x, mdp_flags 0x%x", mdp_layer.alpha, mdp_layer.z_order,
257 mdp_layer.blend_op, mdp_layer.horz_deci, mdp_layer.vert_deci, mdp_layer.pipe_ndx,
258 mdp_layer.flags);
259 DLOGV_IF(kTagDriverConfig, "src_rect [%d, %d, %d, %d]", mdp_layer.src_rect.x,
260 mdp_layer.src_rect.y, mdp_layer.src_rect.w, mdp_layer.src_rect.h);
261 DLOGV_IF(kTagDriverConfig, "dst_rect [%d, %d, %d, %d]", mdp_layer.dst_rect.x,
262 mdp_layer.dst_rect.y, mdp_layer.dst_rect.w, mdp_layer.dst_rect.h);
263 hw_scale_->DumpScaleData(mdp_layer.scale);
264 DLOGV_IF(kTagDriverConfig, "*************************************************************");
265 }
266 }
267 }
268
269 // TODO(user): This block should move to the derived class
270 if (device_type_ == kDeviceVirtual) {
271 LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
272 mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
273 mdp_out_layer_.buffer.width = output_buffer->width;
274 mdp_out_layer_.buffer.height = output_buffer->height;
275 if (output_buffer->flags.secure) {
276 mdp_out_layer_.flags |= MDP_LAYER_SECURE_SESSION;
277 }
278 mdp_out_layer_.buffer.comp_ratio.denom = 1000;
279 mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
280 #ifdef OUT_LAYER_COLOR_SPACE
281 SetCSC(output_buffer->csc, &mdp_out_layer_.color_space);
282 #endif
283 SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
284
285 DLOGI_IF(kTagDriverConfig, "********************* Output buffer Info ************************");
286 DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d",
287 mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
288 mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx);
289 DLOGI_IF(kTagDriverConfig, "*****************************************************************");
290 }
291
292 uint32_t index = 0;
293 for (uint32_t i = 0; i < hw_resource_.hw_dest_scalar_info.count; i++) {
294 DestScaleInfoMap::iterator it = hw_layer_info.dest_scale_info_map.find(i);
295
296 if (it == hw_layer_info.dest_scale_info_map.end()) {
297 continue;
298 }
299
300 HWDestScaleInfo *dest_scale_info = it->second;
301
302 mdp_destination_scaler_data *dest_scalar_data = &mdp_dest_scalar_data_[index];
303 hw_scale_->SetHWScaleData(dest_scale_info->scale_data, index, &mdp_commit,
304 kHWDestinationScalar);
305
306 if (dest_scale_info->scale_update) {
307 dest_scalar_data->flags |= MDP_DESTSCALER_SCALE_UPDATE;
308 }
309
310 dest_scalar_data->dest_scaler_ndx = i;
311 dest_scalar_data->lm_width = dest_scale_info->mixer_width;
312 dest_scalar_data->lm_height = dest_scale_info->mixer_height;
313 dest_scalar_data->scale = reinterpret_cast <uint64_t>
314 (hw_scale_->GetScaleDataRef(index, kHWDestinationScalar));
315
316 index++;
317
318 DLOGV_IF(kTagDriverConfig, "************************ DestScalar[%d] **************************",
319 dest_scalar_data->dest_scaler_ndx);
320 DLOGV_IF(kTagDriverConfig, "Mixer WxH %dx%d", dest_scalar_data->lm_width,
321 dest_scalar_data->lm_height);
322 DLOGI_IF(kTagDriverConfig, "*****************************************************************");
323 }
324 mdp_commit.dest_scaler_cnt = UINT32(hw_layer_info.dest_scale_info_map.size());
325
326 mdp_commit.flags |= MDP_VALIDATE_LAYER;
327 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
328 if (errno == ESHUTDOWN) {
329 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
330 return kErrorShutDown;
331 }
332 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
333 DumpLayerCommit(mdp_disp_commit_);
334 return kErrorHardware;
335 }
336
337 return kErrorNone;
338 }
339
DumpLayerCommit(const mdp_layer_commit & layer_commit)340 void HWDevice::DumpLayerCommit(const mdp_layer_commit &layer_commit) {
341 const mdp_layer_commit_v1 &mdp_commit = layer_commit.commit_v1;
342 const mdp_input_layer *mdp_layers = mdp_commit.input_layers;
343 const mdp_rect &l_roi = mdp_commit.left_roi;
344 const mdp_rect &r_roi = mdp_commit.right_roi;
345
346 DLOGI("mdp_commit: flags = %x, release fence = %x", mdp_commit.flags, mdp_commit.release_fence);
347 DLOGI("left_roi: x = %d, y = %d, w = %d, h = %d", l_roi.x, l_roi.y, l_roi.w, l_roi.h);
348 DLOGI("right_roi: x = %d, y = %d, w = %d, h = %d", r_roi.x, r_roi.y, r_roi.w, r_roi.h);
349 for (uint32_t i = 0; i < mdp_commit.input_layer_cnt; i++) {
350 const mdp_input_layer &layer = mdp_layers[i];
351 const mdp_rect &src_rect = layer.src_rect;
352 const mdp_rect &dst_rect = layer.dst_rect;
353 DLOGI("layer = %d, pipe_ndx = %x, z = %d, flags = %x",
354 i, layer.pipe_ndx, layer.z_order, layer.flags);
355 DLOGI("src_rect: x = %d, y = %d, w = %d, h = %d",
356 src_rect.x, src_rect.y, src_rect.w, src_rect.h);
357 DLOGI("dst_rect: x = %d, y = %d, w = %d, h = %d",
358 dst_rect.x, dst_rect.y, dst_rect.w, dst_rect.h);
359 }
360 }
361
Commit(HWLayers * hw_layers)362 DisplayError HWDevice::Commit(HWLayers *hw_layers) {
363 DTRACE_SCOPED();
364
365 HWLayersInfo &hw_layer_info = hw_layers->info;
366 LayerStack *stack = hw_layer_info.stack;
367
368 DLOGV_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
369 device_name_);
370 DLOGV_IF(kTagDriverConfig, "SDE layer count is %d", hw_layer_info.count);
371
372 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
373 uint32_t mdp_layer_index = 0;
374
375 for (uint32_t i = 0; i < hw_layer_info.count; i++) {
376 uint32_t layer_index = hw_layer_info.index[i];
377 LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer;
378 HWPipeInfo *left_pipe = &hw_layers->config[i].left_pipe;
379 HWPipeInfo *right_pipe = &hw_layers->config[i].right_pipe;
380 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
381
382 for (uint32_t count = 0; count < 2; count++) {
383 HWPipeInfo *pipe_info = (count == 0) ? left_pipe : right_pipe;
384 HWRotateInfo *hw_rotate_info = &hw_rotator_session->hw_rotate_info[count];
385
386 if (hw_rotate_info->valid) {
387 input_buffer = &hw_rotator_session->output_buffer;
388 }
389
390 if (pipe_info->valid) {
391 mdp_layer_buffer &mdp_buffer = mdp_in_layers_[mdp_layer_index].buffer;
392 mdp_input_layer &mdp_layer = mdp_in_layers_[mdp_layer_index];
393 if (input_buffer->planes[0].fd >= 0) {
394 mdp_buffer.plane_count = 1;
395 mdp_buffer.planes[0].fd = input_buffer->planes[0].fd;
396 mdp_buffer.planes[0].offset = input_buffer->planes[0].offset;
397 SetStride(device_type_, input_buffer->format, input_buffer->planes[0].stride,
398 &mdp_buffer.planes[0].stride);
399 } else {
400 mdp_buffer.plane_count = 0;
401 }
402
403 mdp_buffer.fence = input_buffer->acquire_fence_fd;
404 mdp_layer_index++;
405
406 DLOGV_IF(kTagDriverConfig, "****************** Layer[%d] %s pipe Input *******************",
407 i, count ? "Right" : "Left");
408 DLOGI_IF(kTagDriverConfig, "in_w %d, in_h %d, in_f %d, horz_deci %d, vert_deci %d",
409 mdp_buffer.width, mdp_buffer.height, mdp_buffer.format, mdp_layer.horz_deci,
410 mdp_layer.vert_deci);
411 DLOGI_IF(kTagDriverConfig, "in_buf_fd %d, in_buf_offset %d, in_buf_stride %d, " \
412 "in_plane_count %d, in_fence %d, layer count %d", mdp_buffer.planes[0].fd,
413 mdp_buffer.planes[0].offset, mdp_buffer.planes[0].stride, mdp_buffer.plane_count,
414 mdp_buffer.fence, mdp_commit.input_layer_cnt);
415 DLOGV_IF(kTagDriverConfig, "*************************************************************");
416 }
417 }
418 }
419
420 // TODO(user): Move to derived class
421 if (device_type_ == kDeviceVirtual) {
422 LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
423
424 if (output_buffer->planes[0].fd >= 0) {
425 mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
426 mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
427 SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
428 &mdp_out_layer_.buffer.planes[0].stride);
429 mdp_out_layer_.buffer.plane_count = 1;
430 } else {
431 DLOGE("Invalid output buffer fd");
432 return kErrorParameters;
433 }
434
435 mdp_out_layer_.buffer.fence = output_buffer->acquire_fence_fd;
436
437 DLOGI_IF(kTagDriverConfig, "********************** Output buffer Info ***********************");
438 DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d, acquire_fence %d",
439 mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
440 mdp_out_layer_.buffer.planes[0].stride, mdp_out_layer_.buffer.fence);
441 DLOGI_IF(kTagDriverConfig, "*****************************************************************");
442 }
443
444 mdp_commit.release_fence = -1;
445 mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
446 if (synchronous_commit_) {
447 mdp_commit.flags |= MDP_COMMIT_WAIT_FOR_FINISH;
448 }
449 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
450 if (errno == ESHUTDOWN) {
451 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
452 return kErrorShutDown;
453 }
454 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
455 DumpLayerCommit(mdp_disp_commit_);
456 synchronous_commit_ = false;
457 return kErrorHardware;
458 }
459
460 stack->retire_fence_fd = mdp_commit.retire_fence;
461
462 // MDP returns only one release fence for the entire layer stack. Duplicate this fence into all
463 // layers being composed by MDP.
464
465 std::vector<uint32_t> fence_dup_flag;
466 fence_dup_flag.clear();
467
468 for (uint32_t i = 0; i < hw_layer_info.count; i++) {
469 uint32_t layer_index = hw_layer_info.index[i];
470 LayerBuffer *input_buffer = stack->layers.at(layer_index)->input_buffer;
471 HWRotatorSession *hw_rotator_session = &hw_layers->config[i].hw_rotator_session;
472
473 if (hw_rotator_session->hw_block_count) {
474 input_buffer = &hw_rotator_session->output_buffer;
475 }
476
477 // Make sure the release fence is duplicated only once for each buffer.
478 if (std::find(fence_dup_flag.begin(), fence_dup_flag.end(), layer_index) ==
479 fence_dup_flag.end()) {
480 input_buffer->release_fence_fd = Sys::dup_(mdp_commit.release_fence);
481 fence_dup_flag.push_back(layer_index);
482 }
483 }
484 fence_dup_flag.clear();
485
486 hw_layer_info.sync_handle = Sys::dup_(mdp_commit.release_fence);
487
488 DLOGI_IF(kTagDriverConfig, "*************************** %s Commit Input ************************",
489 device_name_);
490 DLOGI_IF(kTagDriverConfig, "retire_fence_fd %d", stack->retire_fence_fd);
491 DLOGI_IF(kTagDriverConfig, "*******************************************************************");
492
493 if (mdp_commit.release_fence >= 0) {
494 Sys::close_(mdp_commit.release_fence);
495 }
496
497 if (synchronous_commit_) {
498 // A synchronous commit can be requested when changing the display mode so we need to update
499 // panel info.
500 PopulateHWPanelInfo();
501 synchronous_commit_ = false;
502 }
503
504 return kErrorNone;
505 }
506
Flush()507 DisplayError HWDevice::Flush() {
508 ResetDisplayParams();
509 mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
510 mdp_commit.input_layer_cnt = 0;
511 mdp_commit.output_layer = NULL;
512
513 mdp_commit.flags &= UINT32(~MDP_VALIDATE_LAYER);
514 if (Sys::ioctl_(device_fd_, INT(MSMFB_ATOMIC_COMMIT), &mdp_disp_commit_) < 0) {
515 if (errno == ESHUTDOWN) {
516 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
517 return kErrorShutDown;
518 }
519 IOCTL_LOGE(MSMFB_ATOMIC_COMMIT, device_type_);
520 DumpLayerCommit(mdp_disp_commit_);
521 return kErrorHardware;
522 }
523 return kErrorNone;
524 }
525
SetFormat(const LayerBufferFormat & source,uint32_t * target)526 DisplayError HWDevice::SetFormat(const LayerBufferFormat &source, uint32_t *target) {
527 switch (source) {
528 case kFormatARGB8888: *target = MDP_ARGB_8888; break;
529 case kFormatRGBA8888: *target = MDP_RGBA_8888; break;
530 case kFormatBGRA8888: *target = MDP_BGRA_8888; break;
531 case kFormatRGBX8888: *target = MDP_RGBX_8888; break;
532 case kFormatBGRX8888: *target = MDP_BGRX_8888; break;
533 case kFormatRGBA5551: *target = MDP_RGBA_5551; break;
534 case kFormatRGBA4444: *target = MDP_RGBA_4444; break;
535 case kFormatRGB888: *target = MDP_RGB_888; break;
536 case kFormatBGR888: *target = MDP_BGR_888; break;
537 case kFormatRGB565: *target = MDP_RGB_565; break;
538 case kFormatBGR565: *target = MDP_BGR_565; break;
539 case kFormatYCbCr420Planar: *target = MDP_Y_CB_CR_H2V2; break;
540 case kFormatYCrCb420Planar: *target = MDP_Y_CR_CB_H2V2; break;
541 case kFormatYCrCb420PlanarStride16: *target = MDP_Y_CR_CB_GH2V2; break;
542 case kFormatYCbCr420SemiPlanar: *target = MDP_Y_CBCR_H2V2; break;
543 case kFormatYCrCb420SemiPlanar: *target = MDP_Y_CRCB_H2V2; break;
544 case kFormatYCbCr422H1V2SemiPlanar: *target = MDP_Y_CBCR_H1V2; break;
545 case kFormatYCrCb422H1V2SemiPlanar: *target = MDP_Y_CRCB_H1V2; break;
546 case kFormatYCbCr422H2V1SemiPlanar: *target = MDP_Y_CBCR_H2V1; break;
547 case kFormatYCrCb422H2V1SemiPlanar: *target = MDP_Y_CRCB_H2V1; break;
548 case kFormatYCbCr422H2V1Packed: *target = MDP_YCBYCR_H2V1; break;
549 case kFormatYCbCr420SemiPlanarVenus: *target = MDP_Y_CBCR_H2V2_VENUS; break;
550 case kFormatRGBA8888Ubwc: *target = MDP_RGBA_8888_UBWC; break;
551 case kFormatRGBX8888Ubwc: *target = MDP_RGBX_8888_UBWC; break;
552 case kFormatBGR565Ubwc: *target = MDP_RGB_565_UBWC; break;
553 case kFormatYCbCr420SPVenusUbwc: *target = MDP_Y_CBCR_H2V2_UBWC; break;
554 case kFormatRGBA1010102: *target = MDP_RGBA_1010102; break;
555 case kFormatARGB2101010: *target = MDP_ARGB_2101010; break;
556 case kFormatRGBX1010102: *target = MDP_RGBX_1010102; break;
557 case kFormatXRGB2101010: *target = MDP_XRGB_2101010; break;
558 case kFormatBGRA1010102: *target = MDP_BGRA_1010102; break;
559 case kFormatABGR2101010: *target = MDP_ABGR_2101010; break;
560 case kFormatBGRX1010102: *target = MDP_BGRX_1010102; break;
561 case kFormatXBGR2101010: *target = MDP_XBGR_2101010; break;
562 case kFormatRGBA1010102Ubwc: *target = MDP_RGBA_1010102_UBWC; break;
563 case kFormatRGBX1010102Ubwc: *target = MDP_RGBX_1010102_UBWC; break;
564 case kFormatYCbCr420P010: *target = MDP_Y_CBCR_H2V2_P010; break;
565 case kFormatYCbCr420TP10Ubwc: *target = MDP_Y_CBCR_H2V2_TP10_UBWC; break;
566 default:
567 DLOGE("Unsupported format type %d", source);
568 return kErrorParameters;
569 }
570
571 return kErrorNone;
572 }
573
SetStride(HWDeviceType device_type,LayerBufferFormat format,uint32_t width,uint32_t * target)574 DisplayError HWDevice::SetStride(HWDeviceType device_type, LayerBufferFormat format,
575 uint32_t width, uint32_t *target) {
576 // TODO(user): This SetStride function is a workaround to satisfy the driver expectation for
577 // rotator and virtual devices. Eventually this will be taken care in the driver.
578 if (device_type != kDeviceRotator && device_type != kDeviceVirtual) {
579 *target = width;
580 return kErrorNone;
581 }
582
583 switch (format) {
584 case kFormatARGB8888:
585 case kFormatRGBA8888:
586 case kFormatBGRA8888:
587 case kFormatRGBX8888:
588 case kFormatBGRX8888:
589 case kFormatRGBA8888Ubwc:
590 case kFormatRGBX8888Ubwc:
591 case kFormatRGBA1010102:
592 case kFormatARGB2101010:
593 case kFormatRGBX1010102:
594 case kFormatXRGB2101010:
595 case kFormatBGRA1010102:
596 case kFormatABGR2101010:
597 case kFormatBGRX1010102:
598 case kFormatXBGR2101010:
599 case kFormatRGBA1010102Ubwc:
600 case kFormatRGBX1010102Ubwc:
601 *target = width * 4;
602 break;
603 case kFormatRGB888:
604 case kFormatBGR888:
605 *target = width * 3;
606 break;
607 case kFormatRGB565:
608 case kFormatBGR565:
609 case kFormatBGR565Ubwc:
610 *target = width * 2;
611 break;
612 case kFormatYCbCr420SemiPlanarVenus:
613 case kFormatYCbCr420SPVenusUbwc:
614 case kFormatYCbCr420Planar:
615 case kFormatYCrCb420Planar:
616 case kFormatYCrCb420PlanarStride16:
617 case kFormatYCbCr420SemiPlanar:
618 case kFormatYCrCb420SemiPlanar:
619 case kFormatYCbCr420P010:
620 case kFormatYCbCr420TP10Ubwc:
621 *target = width;
622 break;
623 case kFormatYCbCr422H2V1Packed:
624 case kFormatYCrCb422H2V1SemiPlanar:
625 case kFormatYCrCb422H1V2SemiPlanar:
626 case kFormatYCbCr422H2V1SemiPlanar:
627 case kFormatYCbCr422H1V2SemiPlanar:
628 case kFormatRGBA5551:
629 case kFormatRGBA4444:
630 *target = width * 2;
631 break;
632 default:
633 DLOGE("Unsupported format type %d", format);
634 return kErrorParameters;
635 }
636
637 return kErrorNone;
638 }
639
SetBlending(const LayerBlending & source,mdss_mdp_blend_op * target)640 void HWDevice::SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target) {
641 switch (source) {
642 case kBlendingPremultiplied: *target = BLEND_OP_PREMULTIPLIED; break;
643 case kBlendingOpaque: *target = BLEND_OP_OPAQUE; break;
644 case kBlendingCoverage: *target = BLEND_OP_COVERAGE; break;
645 default: *target = BLEND_OP_NOT_DEFINED; break;
646 }
647 }
648
SetRect(const LayerRect & source,mdp_rect * target)649 void HWDevice::SetRect(const LayerRect &source, mdp_rect *target) {
650 target->x = UINT32(source.left);
651 target->y = UINT32(source.top);
652 target->w = UINT32(source.right) - target->x;
653 target->h = UINT32(source.bottom) - target->y;
654 }
655
SetMDPFlags(const Layer * layer,const bool & is_rotator_used,bool is_cursor_pipe_used,uint32_t * mdp_flags)656 void HWDevice::SetMDPFlags(const Layer *layer, const bool &is_rotator_used,
657 bool is_cursor_pipe_used, uint32_t *mdp_flags) {
658 const LayerBuffer *input_buffer = layer->input_buffer;
659
660 // Flips will be taken care by rotator, if layer uses rotator for downscale/rotation. So ignore
661 // flip flags for MDP.
662 if (!is_rotator_used) {
663 if (layer->transform.flip_vertical) {
664 *mdp_flags |= MDP_LAYER_FLIP_UD;
665 }
666
667 if (layer->transform.flip_horizontal) {
668 *mdp_flags |= MDP_LAYER_FLIP_LR;
669 }
670
671 if (input_buffer->flags.interlace) {
672 *mdp_flags |= MDP_LAYER_DEINTERLACE;
673 }
674 }
675
676 if (input_buffer->flags.secure) {
677 *mdp_flags |= MDP_LAYER_SECURE_SESSION;
678 }
679
680 if (input_buffer->flags.secure_display) {
681 *mdp_flags |= MDP_LAYER_SECURE_DISPLAY_SESSION;
682 }
683
684 if (layer->flags.solid_fill) {
685 *mdp_flags |= MDP_LAYER_SOLID_FILL;
686 }
687
688 if (hw_panel_info_.mode != kModeCommand && layer->flags.cursor && is_cursor_pipe_used) {
689 // command mode panels does not support async position update
690 *mdp_flags |= MDP_LAYER_ASYNC;
691 }
692 }
693
GetFBNodeIndex(HWDeviceType device_type)694 int HWDevice::GetFBNodeIndex(HWDeviceType device_type) {
695 for (int i = 0; i <= kDeviceVirtual; i++) {
696 HWPanelInfo panel_info;
697 GetHWPanelInfoByNode(i, &panel_info);
698 switch (device_type) {
699 case kDevicePrimary:
700 if (panel_info.is_primary_panel) {
701 return i;
702 }
703 break;
704 case kDeviceHDMI:
705 if (panel_info.is_pluggable == true) {
706 return i;
707 }
708 break;
709 case kDeviceVirtual:
710 if (panel_info.port == kPortWriteBack) {
711 return i;
712 }
713 break;
714 default:
715 break;
716 }
717 }
718 return -1;
719 }
720
PopulateHWPanelInfo()721 void HWDevice::PopulateHWPanelInfo() {
722 hw_panel_info_ = HWPanelInfo();
723 GetHWPanelInfoByNode(fb_node_index_, &hw_panel_info_);
724 DLOGI("Device type = %d, Display Port = %d, Display Mode = %d, Device Node = %d, Is Primary = %d",
725 device_type_, hw_panel_info_.port, hw_panel_info_.mode, fb_node_index_,
726 hw_panel_info_.is_primary_panel);
727 DLOGI("Partial Update = %d, Dynamic FPS = %d",
728 hw_panel_info_.partial_update, hw_panel_info_.dynamic_fps);
729 DLOGI("Align: left = %d, width = %d, top = %d, height = %d",
730 hw_panel_info_.left_align, hw_panel_info_.width_align,
731 hw_panel_info_.top_align, hw_panel_info_.height_align);
732 DLOGI("ROI: min_width = %d, min_height = %d, need_merge = %d",
733 hw_panel_info_.min_roi_width, hw_panel_info_.min_roi_height,
734 hw_panel_info_.needs_roi_merge);
735 DLOGI("FPS: min = %d, max =%d", hw_panel_info_.min_fps, hw_panel_info_.max_fps);
736 DLOGI("Left Split = %d, Right Split = %d", hw_panel_info_.split_info.left_split,
737 hw_panel_info_.split_info.right_split);
738 }
739
GetHWPanelNameByNode(int device_node,HWPanelInfo * panel_info)740 void HWDevice::GetHWPanelNameByNode(int device_node, HWPanelInfo *panel_info) {
741 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
742
743 Sys::fstream fs(file_name, fstream::in);
744 if (!fs.is_open()) {
745 DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
746 return;
747 }
748
749 string line;
750 while (Sys::getline_(fs, line)) {
751 uint32_t token_count = 0;
752 const uint32_t max_count = 10;
753 char *tokens[max_count] = { NULL };
754 if (!ParseLine(line.c_str(), "=\n", tokens, max_count, &token_count)) {
755 if (!strncmp(tokens[0], "panel_name", strlen("panel_name"))) {
756 snprintf(panel_info->panel_name, sizeof(panel_info->panel_name), "%s", tokens[1]);
757 break;
758 }
759 }
760 }
761 }
762
GetHWPanelInfoByNode(int device_node,HWPanelInfo * panel_info)763 void HWDevice::GetHWPanelInfoByNode(int device_node, HWPanelInfo *panel_info) {
764 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_panel_info";
765
766 Sys::fstream fs(file_name, fstream::in);
767 if (!fs.is_open()) {
768 DLOGW("Failed to open msm_fb_panel_info node device node %d", device_node);
769 return;
770 }
771
772 string line;
773 while (Sys::getline_(fs, line)) {
774 uint32_t token_count = 0;
775 const uint32_t max_count = 10;
776 char *tokens[max_count] = { NULL };
777 if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
778 if (!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
779 panel_info->partial_update = atoi(tokens[1]);
780 } else if (!strncmp(tokens[0], "xstart", strlen("xstart"))) {
781 panel_info->left_align = atoi(tokens[1]);
782 } else if (!strncmp(tokens[0], "walign", strlen("walign"))) {
783 panel_info->width_align = atoi(tokens[1]);
784 } else if (!strncmp(tokens[0], "ystart", strlen("ystart"))) {
785 panel_info->top_align = atoi(tokens[1]);
786 } else if (!strncmp(tokens[0], "halign", strlen("halign"))) {
787 panel_info->height_align = atoi(tokens[1]);
788 } else if (!strncmp(tokens[0], "min_w", strlen("min_w"))) {
789 panel_info->min_roi_width = atoi(tokens[1]);
790 } else if (!strncmp(tokens[0], "min_h", strlen("min_h"))) {
791 panel_info->min_roi_height = atoi(tokens[1]);
792 } else if (!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
793 panel_info->needs_roi_merge = atoi(tokens[1]);
794 } else if (!strncmp(tokens[0], "dyn_fps_en", strlen("dyn_fps_en"))) {
795 panel_info->dynamic_fps = atoi(tokens[1]);
796 } else if (!strncmp(tokens[0], "min_fps", strlen("min_fps"))) {
797 panel_info->min_fps = UINT32(atoi(tokens[1]));
798 } else if (!strncmp(tokens[0], "max_fps", strlen("max_fps"))) {
799 panel_info->max_fps = UINT32(atoi(tokens[1]));
800 } else if (!strncmp(tokens[0], "primary_panel", strlen("primary_panel"))) {
801 panel_info->is_primary_panel = atoi(tokens[1]);
802 } else if (!strncmp(tokens[0], "is_pluggable", strlen("is_pluggable"))) {
803 panel_info->is_pluggable = atoi(tokens[1]);
804 }
805 }
806 }
807
808 GetHWDisplayPortAndMode(device_node, &panel_info->port, &panel_info->mode);
809 GetSplitInfo(device_node, panel_info);
810 GetHWPanelNameByNode(device_node, panel_info);
811 GetHWPanelMaxBrightnessFromNode(panel_info);
812 }
813
GetHWDisplayPortAndMode(int device_node,HWDisplayPort * port,HWDisplayMode * mode)814 void HWDevice::GetHWDisplayPortAndMode(int device_node, HWDisplayPort *port, HWDisplayMode *mode) {
815 *port = kPortDefault;
816 *mode = kModeDefault;
817
818 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_type";
819
820 Sys::fstream fs(file_name, fstream::in);
821 if (!fs.is_open()) {
822 DLOGW("File not found %s", file_name.c_str());
823 return;
824 }
825
826 string line;
827 if (!Sys::getline_(fs, line)) {
828 return;
829 }
830
831 if ((strncmp(line.c_str(), "mipi dsi cmd panel", strlen("mipi dsi cmd panel")) == 0)) {
832 *port = kPortDSI;
833 *mode = kModeCommand;
834 } else if ((strncmp(line.c_str(), "mipi dsi video panel", strlen("mipi dsi video panel")) == 0)) {
835 *port = kPortDSI;
836 *mode = kModeVideo;
837 } else if ((strncmp(line.c_str(), "lvds panel", strlen("lvds panel")) == 0)) {
838 *port = kPortLVDS;
839 *mode = kModeVideo;
840 } else if ((strncmp(line.c_str(), "edp panel", strlen("edp panel")) == 0)) {
841 *port = kPortEDP;
842 *mode = kModeVideo;
843 } else if ((strncmp(line.c_str(), "dtv panel", strlen("dtv panel")) == 0)) {
844 *port = kPortDTv;
845 *mode = kModeVideo;
846 } else if ((strncmp(line.c_str(), "writeback panel", strlen("writeback panel")) == 0)) {
847 *port = kPortWriteBack;
848 *mode = kModeCommand;
849 }
850
851 return;
852 }
853
GetSplitInfo(int device_node,HWPanelInfo * panel_info)854 void HWDevice::GetSplitInfo(int device_node, HWPanelInfo *panel_info) {
855 // Split info - for MDSS Version 5 - No need to check version here
856 string file_name = fb_path_ + to_string(device_node) + "/msm_fb_split";
857
858 Sys::fstream fs(file_name, fstream::in);
859 if (!fs.is_open()) {
860 DLOGW("File not found %s", file_name.c_str());
861 return;
862 }
863
864 // Format "left right" space as delimiter
865 uint32_t token_count = 0;
866 const uint32_t max_count = 10;
867 char *tokens[max_count] = { NULL };
868 string line;
869 if (Sys::getline_(fs, line)) {
870 if (!ParseLine(line.c_str(), tokens, max_count, &token_count)) {
871 panel_info->split_info.left_split = UINT32(atoi(tokens[0]));
872 panel_info->split_info.right_split = UINT32(atoi(tokens[1]));
873 }
874 }
875 }
876
GetHWPanelMaxBrightnessFromNode(HWPanelInfo * panel_info)877 void HWDevice::GetHWPanelMaxBrightnessFromNode(HWPanelInfo *panel_info) {
878 char brightness[kMaxStringLength] = { 0 };
879 char kMaxBrightnessNode[64] = { 0 };
880
881 snprintf(kMaxBrightnessNode, sizeof(kMaxBrightnessNode), "%s",
882 "/sys/class/leds/lcd-backlight/max_brightness");
883
884 panel_info->panel_max_brightness = 0;
885 int fd = Sys::open_(kMaxBrightnessNode, O_RDONLY);
886 if (fd < 0) {
887 DLOGW("Failed to open max brightness node = %s, error = %s", kMaxBrightnessNode,
888 strerror(errno));
889 return;
890 }
891
892 if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
893 panel_info->panel_max_brightness = atoi(brightness);
894 DLOGI("Max brightness level = %d", panel_info->panel_max_brightness);
895 } else {
896 DLOGW("Failed to read max brightness level. error = %s", strerror(errno));
897 }
898 Sys::close_(fd);
899 }
900
ParseLine(const char * input,char * tokens[],const uint32_t max_token,uint32_t * count)901 int HWDevice::ParseLine(const char *input, char *tokens[], const uint32_t max_token,
902 uint32_t *count) {
903 char *tmp_token = NULL;
904 char *temp_ptr;
905 uint32_t index = 0;
906 const char *delim = ", =\n";
907 if (!input) {
908 return -1;
909 }
910 tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
911 while (tmp_token && index < max_token) {
912 tokens[index++] = tmp_token;
913 tmp_token = strtok_r(NULL, delim, &temp_ptr);
914 }
915 *count = index;
916
917 return 0;
918 }
919
ParseLine(const char * input,const char * delim,char * tokens[],const uint32_t max_token,uint32_t * count)920 int HWDevice::ParseLine(const char *input, const char *delim, char *tokens[],
921 const uint32_t max_token, uint32_t *count) {
922 char *tmp_token = NULL;
923 char *temp_ptr;
924 uint32_t index = 0;
925 if (!input) {
926 return -1;
927 }
928 tmp_token = strtok_r(const_cast<char *>(input), delim, &temp_ptr);
929 while (tmp_token && index < max_token) {
930 tokens[index++] = tmp_token;
931 tmp_token = strtok_r(NULL, delim, &temp_ptr);
932 }
933 *count = index;
934
935 return 0;
936 }
937
EnableHotPlugDetection(int enable)938 bool HWDevice::EnableHotPlugDetection(int enable) {
939 char hpdpath[kMaxStringLength];
940 int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
941 if (hdmi_node_index < 0) {
942 return false;
943 }
944
945 snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
946
947 char value = enable ? '1' : '0';
948 ssize_t length = SysFsWrite(hpdpath, &value, sizeof(value));
949 if (length <= 0) {
950 return false;
951 }
952
953 return true;
954 }
955
ResetDisplayParams()956 void HWDevice::ResetDisplayParams() {
957 memset(&mdp_disp_commit_, 0, sizeof(mdp_disp_commit_));
958 memset(&mdp_in_layers_, 0, sizeof(mdp_in_layers_));
959 memset(&mdp_out_layer_, 0, sizeof(mdp_out_layer_));
960 mdp_out_layer_.buffer.fence = -1;
961 hw_scale_->ResetScaleParams();
962 memset(&pp_params_, 0, sizeof(pp_params_));
963 memset(&igc_lut_data_, 0, sizeof(igc_lut_data_));
964
965 for (size_t i = 0; i < mdp_dest_scalar_data_.size(); i++) {
966 mdp_dest_scalar_data_[i] = {};
967 }
968
969 for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
970 mdp_in_layers_[i].buffer.fence = -1;
971 }
972
973 mdp_disp_commit_.version = MDP_COMMIT_VERSION_1_0;
974 mdp_disp_commit_.commit_v1.input_layers = mdp_in_layers_;
975 mdp_disp_commit_.commit_v1.output_layer = &mdp_out_layer_;
976 mdp_disp_commit_.commit_v1.release_fence = -1;
977 mdp_disp_commit_.commit_v1.retire_fence = -1;
978 mdp_disp_commit_.commit_v1.dest_scaler = mdp_dest_scalar_data_.data();
979 }
980
SetCSC(LayerCSC source,mdp_color_space * color_space)981 void HWDevice::SetCSC(LayerCSC source, mdp_color_space *color_space) {
982 switch (source) {
983 case kCSCLimitedRange601: *color_space = MDP_CSC_ITU_R_601; break;
984 case kCSCFullRange601: *color_space = MDP_CSC_ITU_R_601_FR; break;
985 case kCSCLimitedRange709: *color_space = MDP_CSC_ITU_R_709; break;
986 }
987 }
988
SetIGC(const LayerBuffer * layer_buffer,uint32_t index)989 void HWDevice::SetIGC(const LayerBuffer *layer_buffer, uint32_t index) {
990 mdp_input_layer &mdp_layer = mdp_in_layers_[index];
991 mdp_overlay_pp_params &pp_params = pp_params_[index];
992 mdp_igc_lut_data_v1_7 &igc_lut_data = igc_lut_data_[index];
993
994 switch (layer_buffer->igc) {
995 case kIGCsRGB:
996 igc_lut_data.table_fmt = mdp_igc_srgb;
997 pp_params.igc_cfg.ops = MDP_PP_OPS_WRITE | MDP_PP_OPS_ENABLE;
998 break;
999
1000 default:
1001 pp_params.igc_cfg.ops = MDP_PP_OPS_DISABLE;
1002 break;
1003 }
1004
1005 pp_params.config_ops = MDP_OVERLAY_PP_IGC_CFG;
1006 pp_params.igc_cfg.version = mdp_igc_v1_7;
1007 pp_params.igc_cfg.cfg_payload = &igc_lut_data;
1008
1009 mdp_layer.pp_info = &pp_params;
1010 mdp_layer.flags |= MDP_LAYER_PP;
1011 }
1012
SetCursorPosition(HWLayers * hw_layers,int x,int y)1013 DisplayError HWDevice::SetCursorPosition(HWLayers *hw_layers, int x, int y) {
1014 DTRACE_SCOPED();
1015
1016 HWLayersInfo &hw_layer_info = hw_layers->info;
1017 uint32_t count = hw_layer_info.count;
1018 uint32_t cursor_index = count - 1;
1019 HWPipeInfo *left_pipe = &hw_layers->config[cursor_index].left_pipe;
1020
1021 mdp_async_layer async_layer = {};
1022 async_layer.flags = MDP_LAYER_ASYNC;
1023 async_layer.pipe_ndx = left_pipe->pipe_id;
1024 async_layer.src.x = UINT32(left_pipe->src_roi.left);
1025 async_layer.src.y = UINT32(left_pipe->src_roi.top);
1026 async_layer.dst.x = UINT32(x);
1027 async_layer.dst.y = UINT32(y);
1028
1029 mdp_position_update pos_update = {};
1030 pos_update.input_layer_cnt = 1;
1031 pos_update.input_layers = &async_layer;
1032 if (Sys::ioctl_(device_fd_, INT(MSMFB_ASYNC_POSITION_UPDATE), &pos_update) < 0) {
1033 if (errno == ESHUTDOWN) {
1034 DLOGI_IF(kTagDriverConfig, "Driver is processing shutdown sequence");
1035 return kErrorShutDown;
1036 }
1037 IOCTL_LOGE(MSMFB_ASYNC_POSITION_UPDATE, device_type_);
1038 return kErrorHardware;
1039 }
1040
1041 return kErrorNone;
1042 }
1043
GetPPFeaturesVersion(PPFeatureVersion * vers)1044 DisplayError HWDevice::GetPPFeaturesVersion(PPFeatureVersion *vers) {
1045 return kErrorNotSupported;
1046 }
1047
SetPPFeatures(PPFeaturesConfig * feature_list)1048 DisplayError HWDevice::SetPPFeatures(PPFeaturesConfig *feature_list) {
1049 return kErrorNotSupported;
1050 }
1051
SetVSyncState(bool enable)1052 DisplayError HWDevice::SetVSyncState(bool enable) {
1053 int vsync_on = enable ? 1 : 0;
1054 if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
1055 IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
1056 return kErrorHardware;
1057 }
1058 return kErrorNone;
1059 }
1060
SetIdleTimeoutMs(uint32_t timeout_ms)1061 void HWDevice::SetIdleTimeoutMs(uint32_t timeout_ms) {
1062 }
1063
SetDisplayMode(const HWDisplayMode hw_display_mode)1064 DisplayError HWDevice::SetDisplayMode(const HWDisplayMode hw_display_mode) {
1065 return kErrorNotSupported;
1066 }
1067
SetRefreshRate(uint32_t refresh_rate)1068 DisplayError HWDevice::SetRefreshRate(uint32_t refresh_rate) {
1069 return kErrorNotSupported;
1070 }
1071
SetPanelBrightness(int level)1072 DisplayError HWDevice::SetPanelBrightness(int level) {
1073 return kErrorNotSupported;
1074 }
1075
GetHWScanInfo(HWScanInfo * scan_info)1076 DisplayError HWDevice::GetHWScanInfo(HWScanInfo *scan_info) {
1077 return kErrorNotSupported;
1078 }
1079
GetVideoFormat(uint32_t config_index,uint32_t * video_format)1080 DisplayError HWDevice::GetVideoFormat(uint32_t config_index, uint32_t *video_format) {
1081 return kErrorNotSupported;
1082 }
1083
GetMaxCEAFormat(uint32_t * max_cea_format)1084 DisplayError HWDevice::GetMaxCEAFormat(uint32_t *max_cea_format) {
1085 return kErrorNotSupported;
1086 }
1087
OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level)1088 DisplayError HWDevice::OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level) {
1089 return kErrorNotSupported;
1090 }
1091
GetPanelBrightness(int * level)1092 DisplayError HWDevice::GetPanelBrightness(int *level) {
1093 return kErrorNotSupported;
1094 }
1095
SysFsWrite(const char * file_node,const char * value,ssize_t length)1096 ssize_t HWDevice::SysFsWrite(const char* file_node, const char* value, ssize_t length) {
1097 int fd = Sys::open_(file_node, O_RDWR, 0);
1098 if (fd < 0) {
1099 DLOGW("Open failed = %s", file_node);
1100 return -1;
1101 }
1102 ssize_t len = Sys::pwrite_(fd, value, static_cast<size_t>(length), 0);
1103 if (len <= 0) {
1104 DLOGE("Write failed for path %s with value %s", file_node, value);
1105 }
1106 Sys::close_(fd);
1107
1108 return len;
1109 }
1110
SetS3DMode(HWS3DMode s3d_mode)1111 DisplayError HWDevice::SetS3DMode(HWS3DMode s3d_mode) {
1112 return kErrorNotSupported;
1113 }
1114
SetScaleLutConfig(HWScaleLutInfo * lut_info)1115 DisplayError HWDevice::SetScaleLutConfig(HWScaleLutInfo *lut_info) {
1116 mdp_scale_luts_info mdp_lut_info = {};
1117 mdp_set_cfg cfg = {};
1118
1119 if (!hw_resource_.has_qseed3) {
1120 DLOGV_IF(kTagDriverConfig, "No support for QSEED3 luts");
1121 return kErrorNone;
1122 }
1123
1124 if (!lut_info->dir_lut_size && !lut_info->dir_lut && !lut_info->cir_lut_size &&
1125 !lut_info->cir_lut && !lut_info->sep_lut_size && !lut_info->sep_lut) {
1126 // HWSupports QSEED3, but LutInfo is invalid as scalar is disabled by property or
1127 // its loading failed. Driver will use default settings/filter
1128 return kErrorNone;
1129 }
1130
1131 mdp_lut_info.dir_lut_size = lut_info->dir_lut_size;
1132 mdp_lut_info.dir_lut = lut_info->dir_lut;
1133 mdp_lut_info.cir_lut_size = lut_info->cir_lut_size;
1134 mdp_lut_info.cir_lut = lut_info->cir_lut;
1135 mdp_lut_info.sep_lut_size = lut_info->sep_lut_size;
1136 mdp_lut_info.sep_lut = lut_info->sep_lut;
1137
1138 cfg.flags = MDP_QSEED3_LUT_CFG;
1139 cfg.len = sizeof(mdp_scale_luts_info);
1140 cfg.payload = reinterpret_cast<uint64_t>(&mdp_lut_info);
1141
1142 if (Sys::ioctl_(device_fd_, MSMFB_MDP_SET_CFG, &cfg) < 0) {
1143 IOCTL_LOGE(MSMFB_MDP_SET_CFG, device_type_);
1144 return kErrorHardware;
1145 }
1146
1147 return kErrorNone;
1148 }
1149
SetMixerAttributes(const HWMixerAttributes & mixer_attributes)1150 DisplayError HWDevice::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
1151 if (!hw_resource_.hw_dest_scalar_info.count) {
1152 return kErrorNotSupported;
1153 }
1154
1155 if (mixer_attributes.width > display_attributes_.x_pixels ||
1156 mixer_attributes.height > display_attributes_.y_pixels) {
1157 DLOGW("Input resolution exceeds display resolution! input: res %dx%d display: res %dx%d",
1158 mixer_attributes.width, mixer_attributes.height, display_attributes_.x_pixels,
1159 display_attributes_.y_pixels);
1160 return kErrorNotSupported;
1161 }
1162
1163 uint32_t max_input_width = hw_resource_.hw_dest_scalar_info.max_input_width;
1164 if (display_attributes_.is_device_split) {
1165 max_input_width *= 2;
1166 }
1167
1168 if (mixer_attributes.width > max_input_width) {
1169 DLOGW("Input width exceeds width limit! input_width %d width_limit %d", mixer_attributes.width,
1170 max_input_width);
1171 return kErrorNotSupported;
1172 }
1173
1174 float mixer_aspect_ratio = FLOAT(mixer_attributes.width) / FLOAT(mixer_attributes.height);
1175 float display_aspect_ratio =
1176 FLOAT(display_attributes_.x_pixels) / FLOAT(display_attributes_.y_pixels);
1177
1178 if (display_aspect_ratio != mixer_aspect_ratio) {
1179 DLOGW("Aspect ratio mismatch! input: res %dx%d display: res %dx%d", mixer_attributes.width,
1180 mixer_attributes.height, display_attributes_.x_pixels, display_attributes_.y_pixels);
1181 return kErrorNotSupported;
1182 }
1183
1184 float scale_x = FLOAT(display_attributes_.x_pixels) / FLOAT(mixer_attributes.width);
1185 float scale_y = FLOAT(display_attributes_.y_pixels) / FLOAT(mixer_attributes.height);
1186 float max_scale_up = hw_resource_.hw_dest_scalar_info.max_scale_up;
1187 if (scale_x > max_scale_up || scale_y > max_scale_up) {
1188 DLOGW("Up scaling ratio exceeds for destination scalar upscale limit scale_x %f scale_y %f " \
1189 "max_scale_up %f", scale_x, scale_y, max_scale_up);
1190 return kErrorNotSupported;
1191 }
1192
1193 float mixer_split_ratio = FLOAT(mixer_attributes_.split_left) / FLOAT(mixer_attributes_.width);
1194
1195 mixer_attributes_ = mixer_attributes;
1196 mixer_attributes_.split_left = mixer_attributes_.width;
1197 if (display_attributes_.is_device_split) {
1198 mixer_attributes_.split_left = UINT32(FLOAT(mixer_attributes.width) * mixer_split_ratio);
1199 }
1200
1201 return kErrorNone;
1202 }
1203
GetMixerAttributes(HWMixerAttributes * mixer_attributes)1204 DisplayError HWDevice::GetMixerAttributes(HWMixerAttributes *mixer_attributes) {
1205 if (!mixer_attributes) {
1206 return kErrorParameters;
1207 }
1208
1209 *mixer_attributes = mixer_attributes_;
1210
1211 return kErrorNone;
1212 }
1213
1214 } // namespace sdm
1215
1216