• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2015 - 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 #include <stdio.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <pthread.h>
34 #include <fcntl.h>
35 #include <sys/prctl.h>
36 #include <sys/ioctl.h>
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <utils/debug.h>
40 #include <utils/sys.h>
41 #include <core/display_interface.h>
42 #include <linux/msm_mdp_ext.h>
43 #include <utils/rect.h>
44 
45 #include <string>
46 
47 #include "hw_primary.h"
48 #include "hw_color_manager.h"
49 
50 #define __CLASS__ "HWPrimary"
51 
52 #ifndef MDP_COMMIT_CWB_EN
53 #define MDP_COMMIT_CWB_EN 0x800
54 #endif
55 
56 #ifndef MDP_COMMIT_CWB_DSPP
57 #define MDP_COMMIT_CWB_DSPP 0x1000
58 #endif
59 
60 namespace sdm {
61 
62 using std::string;
63 using std::to_string;
64 using std::fstream;
65 
Create(HWInterface ** intf,HWInfoInterface * hw_info_intf,BufferSyncHandler * buffer_sync_handler)66 DisplayError HWPrimary::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
67                                BufferSyncHandler *buffer_sync_handler) {
68   DisplayError error = kErrorNone;
69   HWPrimary *hw_primary = NULL;
70 
71   hw_primary = new HWPrimary(buffer_sync_handler, hw_info_intf);
72   error = hw_primary->Init();
73   if (error != kErrorNone) {
74     delete hw_primary;
75   } else {
76     *intf = hw_primary;
77   }
78 
79   return error;
80 }
81 
Destroy(HWInterface * intf)82 DisplayError HWPrimary::Destroy(HWInterface *intf) {
83   HWPrimary *hw_primary = static_cast<HWPrimary *>(intf);
84   hw_primary->Deinit();
85   delete hw_primary;
86 
87   return kErrorNone;
88 }
89 
HWPrimary(BufferSyncHandler * buffer_sync_handler,HWInfoInterface * hw_info_intf)90 HWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
91   : HWDevice(buffer_sync_handler) {
92   HWDevice::device_type_ = kDevicePrimary;
93   HWDevice::device_name_ = "Primary Display Device";
94   HWDevice::hw_info_intf_ = hw_info_intf;
95 }
96 
Init()97 DisplayError HWPrimary::Init() {
98   DisplayError error = kErrorNone;
99 
100   error = HWDevice::Init();
101   if (error != kErrorNone) {
102     return error;
103   }
104 
105   mdp_dest_scalar_data_.resize(hw_resource_.hw_dest_scalar_info.count);
106 
107   error = PopulateDisplayAttributes();
108   if (error != kErrorNone) {
109     return error;
110   }
111 
112   UpdateMixerAttributes();
113 
114   // Need to enable HPD, but toggle at start when HDMI is external
115   // This helps for framework reboot or adb shell stop/start
116   EnableHotPlugDetection(0);
117   EnableHotPlugDetection(1);
118   InitializeConfigs();
119 
120   return error;
121 }
122 
GetCurrentModeFromSysfs(size_t * curr_x_pixels,size_t * curr_y_pixels)123 bool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) {
124   bool ret = false;
125   string mode_path = fb_path_ + string("0/mode");
126 
127   Sys::fstream fs(mode_path, fstream::in);
128   if (!fs.is_open()) {
129     return false;
130   }
131 
132   string line;
133   if (Sys::getline_(fs, line)) {
134     // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
135     // kernel has more info on the format.
136     size_t xpos = line.find(':');
137     size_t ypos = line.find('x');
138 
139     if (xpos == string::npos || ypos == string::npos) {
140       DLOGI("Resolution switch not supported");
141     } else {
142       *curr_x_pixels = static_cast<size_t>(atoi(line.c_str() + xpos + 1));
143       *curr_y_pixels = static_cast<size_t>(atoi(line.c_str() + ypos + 1));
144       DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels);
145       ret = true;
146     }
147   }
148 
149   return ret;
150 }
151 
InitializeConfigs()152 void HWPrimary::InitializeConfigs() {
153   size_t curr_x_pixels = 0;
154   size_t curr_y_pixels = 0;
155 
156   if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) {
157     return;
158   }
159 
160   string modes_path = string(fb_path_) + string("0/modes");
161 
162   Sys::fstream fs(modes_path, fstream::in);
163   if (!fs.is_open()) {
164     DLOGI("Unable to process modes");
165     return;
166   }
167 
168   string line;
169   while (Sys::getline_(fs, line)) {
170     DisplayConfigVariableInfo config;
171     size_t xpos = line.find(':');
172     size_t ypos = line.find('x');
173 
174     if (xpos == string::npos || ypos == string::npos) {
175       continue;
176     }
177 
178     config.x_pixels = UINT32(atoi(line.c_str() + xpos + 1));
179     config.y_pixels = UINT32(atoi(line.c_str() + ypos + 1));
180     DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels);
181     display_configs_.push_back(config);
182     display_config_strings_.push_back(string(line.c_str()));
183 
184     if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) {
185       active_config_index_ = UINT32(display_configs_.size() - 1);
186       DLOGI("Active config index %u", active_config_index_);
187     }
188   }
189 }
190 
Deinit()191 DisplayError HWPrimary::Deinit() {
192   return HWDevice::Deinit();
193 }
194 
GetNumDisplayAttributes(uint32_t * count)195 DisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
196   *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1;
197   return kErrorNone;
198 }
199 
GetActiveConfig(uint32_t * active_config_index)200 DisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) {
201   *active_config_index = active_config_index_;
202   return kErrorNone;
203 }
204 
GetDisplayAttributes(uint32_t index,HWDisplayAttributes * display_attributes)205 DisplayError HWPrimary::GetDisplayAttributes(uint32_t index,
206                                              HWDisplayAttributes *display_attributes) {
207   if (!display_attributes) {
208     return kErrorParameters;
209   }
210 
211   if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) {
212     return kErrorParameters;
213   }
214 
215   *display_attributes = display_attributes_;
216   if (IsResolutionSwitchEnabled()) {
217     // Overwrite only the parent portion of object
218     display_attributes->x_pixels = display_configs_.at(index).x_pixels;
219     display_attributes->y_pixels = display_configs_.at(index).y_pixels;
220   }
221 
222   return kErrorNone;
223 }
224 
PopulateDisplayAttributes()225 DisplayError HWPrimary::PopulateDisplayAttributes() {
226   DTRACE_SCOPED();
227 
228   // Variable screen info
229   fb_var_screeninfo var_screeninfo = {};
230 
231   if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
232     IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
233     return kErrorHardware;
234   }
235 
236   // Frame rate
237   msmfb_metadata meta_data = {};
238   meta_data.op = metadata_op_frame_rate;
239   if (Sys::ioctl_(device_fd_, MSMFB_METADATA_GET, &meta_data) < 0) {
240     IOCTL_LOGE(MSMFB_METADATA_GET, device_type_);
241     return kErrorHardware;
242   }
243 
244   // If driver doesn't return width/height information, default to 160 dpi
245   if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
246     var_screeninfo.width  = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
247     var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
248   }
249 
250   display_attributes_.x_pixels = var_screeninfo.xres;
251   display_attributes_.y_pixels = var_screeninfo.yres;
252   display_attributes_.v_front_porch = var_screeninfo.lower_margin;
253   display_attributes_.v_back_porch = var_screeninfo.upper_margin;
254   display_attributes_.v_pulse_width = var_screeninfo.vsync_len;
255   uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
256       var_screeninfo.hsync_len;
257   display_attributes_.h_total = var_screeninfo.xres + h_blanking;
258   display_attributes_.x_dpi =
259       (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
260   display_attributes_.y_dpi =
261       (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
262   display_attributes_.fps = meta_data.data.panel_frame_rate;
263   display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
264   display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
265       (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
266   display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
267 
268   return kErrorNone;
269 }
270 
SetDisplayAttributes(uint32_t index)271 DisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
272   DisplayError ret = kErrorNone;
273 
274   if (!IsResolutionSwitchEnabled()) {
275     return kErrorNotSupported;
276   }
277 
278   if (index >= display_configs_.size()) {
279     return kErrorParameters;
280   }
281 
282   string mode_path = string(fb_path_) + string("0/mode");
283   int fd = Sys::open_(mode_path.c_str(), O_WRONLY);
284 
285   if (fd < 0) {
286     DLOGE("Opening mode failed");
287     return kErrorNotSupported;
288   }
289 
290   ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(),
291                                  display_config_strings_.at(index).length(), 0);
292   if (written > 0) {
293     DLOGI("Successfully set config %u", index);
294     PopulateHWPanelInfo();
295     PopulateDisplayAttributes();
296     UpdateMixerAttributes();
297     active_config_index_ = index;
298   } else {
299     DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
300     ret = kErrorParameters;
301   }
302 
303   Sys::close_(fd);
304 
305   return ret;
306 }
307 
SetRefreshRate(uint32_t refresh_rate)308 DisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
309   char node_path[kMaxStringLength] = {0};
310 
311   if (refresh_rate == display_attributes_.fps) {
312     return kErrorNone;
313   }
314 
315   snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
316 
317   int fd = Sys::open_(node_path, O_WRONLY);
318   if (fd < 0) {
319     DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
320     return kErrorFileDescriptor;
321   }
322 
323   char refresh_rate_string[kMaxStringLength];
324   snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
325   DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
326   ssize_t len = Sys::pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
327   if (len < 0) {
328     DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
329     Sys::close_(fd);
330     return kErrorUndefined;
331   }
332   Sys::close_(fd);
333 
334   DisplayError error = PopulateDisplayAttributes();
335   if (error != kErrorNone) {
336     return error;
337   }
338 
339   return kErrorNone;
340 }
341 
GetConfigIndex(uint32_t mode,uint32_t * index)342 DisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
343   return HWDevice::GetConfigIndex(mode, index);
344 }
345 
PowerOff()346 DisplayError HWPrimary::PowerOff() {
347   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
348     IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
349     return kErrorHardware;
350   }
351 
352   return kErrorNone;
353 }
354 
Doze()355 DisplayError HWPrimary::Doze() {
356   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
357     IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
358     return kErrorHardware;
359   }
360 
361   return kErrorNone;
362 }
363 
DozeSuspend()364 DisplayError HWPrimary::DozeSuspend() {
365   if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
366     IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
367     return kErrorHardware;
368   }
369 
370   return kErrorNone;
371 }
372 
Validate(HWLayers * hw_layers)373 DisplayError HWPrimary::Validate(HWLayers *hw_layers) {
374   HWLayersInfo &hw_layer_info = hw_layers->info;
375   LayerStack *stack = hw_layer_info.stack;
376 
377   HWDevice::ResetDisplayParams();
378 
379   mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
380 
381   LayerRect left_roi = hw_layer_info.left_partial_update;
382   LayerRect right_roi = hw_layer_info.right_partial_update;
383   mdp_commit.left_roi.x = UINT32(left_roi.left);
384   mdp_commit.left_roi.y = UINT32(left_roi.top);
385   mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
386   mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top);
387 
388   // SDM treats ROI as one full coordinate system.
389   // In case source split is disabled, However, Driver assumes Mixer to operate in
390   // different co-ordinate system.
391   if (!hw_resource_.is_src_split && IsValid(right_roi)) {
392     mdp_commit.right_roi.x = UINT32(right_roi.left) - mixer_attributes_.split_left;
393     mdp_commit.right_roi.y = UINT32(right_roi.top);
394     mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
395     mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
396   }
397 
398   if (stack->output_buffer && hw_resource_.has_concurrent_writeback) {
399     LayerBuffer *output_buffer = stack->output_buffer;
400     mdp_out_layer_.writeback_ndx = hw_resource_.writeback_index;
401     mdp_out_layer_.buffer.width = output_buffer->width;
402     mdp_out_layer_.buffer.height = output_buffer->height;
403     mdp_out_layer_.buffer.comp_ratio.denom = 1000;
404     mdp_out_layer_.buffer.comp_ratio.numer = UINT32(hw_layers->output_compression * 1000);
405     mdp_out_layer_.buffer.fence = -1;
406 #ifdef OUT_LAYER_COLOR_SPACE
407     SetCSC(output_buffer->csc, &mdp_out_layer_.color_space);
408 #endif
409     SetFormat(output_buffer->format, &mdp_out_layer_.buffer.format);
410     mdp_commit.flags |= MDP_COMMIT_CWB_EN;
411     mdp_commit.flags |= (stack->flags.post_processed_output) ? MDP_COMMIT_CWB_DSPP : 0;
412     DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ******************");
413     DLOGI_IF(kTagDriverConfig, "out_w %d, out_h %d, out_f %d, wb_id %d DSPP output %d",
414              mdp_out_layer_.buffer.width, mdp_out_layer_.buffer.height,
415              mdp_out_layer_.buffer.format, mdp_out_layer_.writeback_ndx,
416              stack->flags.post_processed_output);
417     DLOGI_IF(kTagDriverConfig, "****************************************************************");
418   }
419 
420   return HWDevice::Validate(hw_layers);
421 }
422 
Commit(HWLayers * hw_layers)423 DisplayError HWPrimary::Commit(HWLayers *hw_layers) {
424   LayerBuffer *output_buffer = hw_layers->info.stack->output_buffer;
425 
426   if (hw_resource_.has_concurrent_writeback && output_buffer) {
427     if (output_buffer->planes[0].fd >= 0) {
428       mdp_out_layer_.buffer.planes[0].fd = output_buffer->planes[0].fd;
429       mdp_out_layer_.buffer.planes[0].offset = output_buffer->planes[0].offset;
430       SetStride(device_type_, output_buffer->format, output_buffer->planes[0].stride,
431                 &mdp_out_layer_.buffer.planes[0].stride);
432       mdp_out_layer_.buffer.plane_count = 1;
433       mdp_out_layer_.buffer.fence = -1;
434 
435       DLOGI_IF(kTagDriverConfig, "****************** Conc WB Output buffer Info ****************");
436       DLOGI_IF(kTagDriverConfig, "out_fd %d, out_offset %d, out_stride %d",
437                mdp_out_layer_.buffer.planes[0].fd, mdp_out_layer_.buffer.planes[0].offset,
438                mdp_out_layer_.buffer.planes[0].stride);
439       DLOGI_IF(kTagDriverConfig, "**************************************************************");
440     } else {
441       DLOGE("Invalid output buffer fd");
442       return kErrorParameters;
443     }
444   }
445 
446   DisplayError ret = HWDevice::Commit(hw_layers);
447 
448   if (ret == kErrorNone && hw_resource_.has_concurrent_writeback && output_buffer) {
449     output_buffer->release_fence_fd = mdp_out_layer_.buffer.fence;
450   }
451 
452   return ret;
453 }
454 
SetIdleTimeoutMs(uint32_t timeout_ms)455 void HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
456   char node_path[kMaxStringLength] = {0};
457 
458   DLOGI_IF(kTagDriverConfig, "Setting idle timeout to = %d ms", timeout_ms);
459 
460   snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
461 
462   // Open a sysfs node to send the timeout value to driver.
463   int fd = Sys::open_(node_path, O_WRONLY);
464   if (fd < 0) {
465     DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
466     return;
467   }
468 
469   char timeout_string[64];
470   snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
471 
472   // Notify driver about the timeout value
473   ssize_t length = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0);
474   if (length <= 0) {
475     DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
476   }
477 
478   Sys::close_(fd);
479 }
480 
SetVSyncState(bool enable)481 DisplayError HWPrimary::SetVSyncState(bool enable) {
482   DTRACE_SCOPED();
483   return HWDevice::SetVSyncState(enable);
484 }
485 
SetDisplayMode(const HWDisplayMode hw_display_mode)486 DisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
487   uint32_t mode = kModeDefault;
488 
489   switch (hw_display_mode) {
490   case kModeVideo:
491     mode = kModeLPMVideo;
492     break;
493   case kModeCommand:
494     mode = kModeLPMCommand;
495     break;
496   default:
497     DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
498           hw_display_mode);
499     return kErrorParameters;
500   }
501 
502   if (Sys::ioctl_(device_fd_, INT(MSMFB_LPM_ENABLE), &mode) < 0) {
503     IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
504     return kErrorHardware;
505   }
506 
507   DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
508   synchronous_commit_ = true;
509 
510   return kErrorNone;
511 }
512 
SetPanelBrightness(int level)513 DisplayError HWPrimary::SetPanelBrightness(int level) {
514   char buffer[MAX_SYSFS_COMMAND_LENGTH] = {0};
515 
516   DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
517   int fd = Sys::open_(kBrightnessNode, O_RDWR);
518   if (fd < 0) {
519     DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
520              strerror(errno));
521     return kErrorFileDescriptor;
522   }
523 
524   int32_t bytes = snprintf(buffer, MAX_SYSFS_COMMAND_LENGTH, "%d\n", level);
525   if (bytes < 0) {
526     DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
527     Sys::close_(fd);
528     return kErrorUndefined;
529   }
530 
531   ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
532   if (ret <= 0) {
533     DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
534              strerror(errno));
535     Sys::close_(fd);
536     return kErrorUndefined;
537   }
538   Sys::close_(fd);
539 
540   return kErrorNone;
541 }
542 
GetPanelBrightness(int * level)543 DisplayError HWPrimary::GetPanelBrightness(int *level) {
544   char brightness[kMaxStringLength] = {0};
545 
546   if (!level) {
547     DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
548     return kErrorParameters;
549   }
550 
551   int fd = Sys::open_(kBrightnessNode, O_RDWR);
552   if (fd < 0) {
553     DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
554              strerror(errno));
555     return kErrorFileDescriptor;
556   }
557 
558   if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
559     *level = atoi(brightness);
560     DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
561   }
562   Sys::close_(fd);
563 
564   return kErrorNone;
565 }
566 
SetAutoRefresh(bool enable)567 DisplayError HWPrimary::SetAutoRefresh(bool enable) {
568   const int kWriteLength = 2;
569   char buffer[kWriteLength] = {'\0'};
570   ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable);
571 
572   if (enable == auto_refresh_) {
573     return kErrorNone;
574   }
575 
576   if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) {  // Returns bytes written
577     return kErrorUndefined;
578   }
579 
580   auto_refresh_ = enable;
581 
582   return kErrorNone;
583 }
584 
GetPPFeaturesVersion(PPFeatureVersion * vers)585 DisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
586   mdp_pp_feature_version version = {};
587 
588   uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
589 
590   for (int i(0); i < kMaxNumPPFeatures; i++) {
591     version.pp_feature = feature_id_mapping[i];
592 
593     if (Sys::ioctl_(device_fd_,  INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
594       IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
595       return kErrorHardware;
596     }
597     vers->version[i] = version.version_info;
598   }
599 
600   return kErrorNone;
601 }
602 
603 // It was entered with PPFeaturesConfig::locker_ being hold.
SetPPFeatures(PPFeaturesConfig * feature_list)604 DisplayError HWPrimary::SetPPFeatures(PPFeaturesConfig *feature_list) {
605   msmfb_mdp_pp kernel_params = {};
606   int ret = 0;
607   PPFeatureInfo *feature = NULL;
608 
609   while (true) {
610     ret = feature_list->RetrieveNextFeature(&feature);
611     if (ret)
612         break;
613 
614     if (feature) {
615       DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
616 
617       if ((feature->feature_id_ < kMaxNumPPFeatures)) {
618         HWColorManager::SetFeature[feature->feature_id_](*feature, &kernel_params);
619         if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP), &kernel_params) < 0) {
620           IOCTL_LOGE(MSMFB_MDP_PP, device_type_);
621 
622           feature_list->Reset();
623           return kErrorHardware;
624         }
625       }
626     }
627   }  // while(true)
628 
629   // Once all features were consumed, then destroy all feature instance from feature_list,
630   // Then mark it as non-dirty of PPFeaturesConfig cache.
631   feature_list->Reset();
632 
633   return kErrorNone;
634 }
635 
SetMixerAttributes(const HWMixerAttributes & mixer_attributes)636 DisplayError HWPrimary::SetMixerAttributes(const HWMixerAttributes &mixer_attributes) {
637   if (IsResolutionSwitchEnabled()) {
638     return kErrorNotSupported;
639   }
640 
641   return HWDevice::SetMixerAttributes(mixer_attributes);
642 }
643 
UpdateMixerAttributes()644 void HWPrimary::UpdateMixerAttributes() {
645   mixer_attributes_.width = display_attributes_.x_pixels;
646   mixer_attributes_.height = display_attributes_.y_pixels;
647   mixer_attributes_.split_left = display_attributes_.is_device_split ?
648       hw_panel_info_.split_info.left_split : mixer_attributes_.width;
649 }
650 
651 }  // namespace sdm
652 
653