1d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin/*
21c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed* Copyright (c) 2015 - 2016, The Linux Foundation. All rights reserved.
3d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*
4d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* Redistribution and use in source and binary forms, with or without
5d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* modification, are permitted provided that the following conditions are
6d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* met:
7d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*     * Redistributions of source code must retain the above copyright
8d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       notice, this list of conditions and the following disclaimer.
9d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*     * Redistributions in binary form must reproduce the above
10d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       copyright notice, this list of conditions and the following
11d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       disclaimer in the documentation and/or other materials provided
12d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       with the distribution.
13d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*     * Neither the name of The Linux Foundation nor the names of its
14d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       contributors may be used to endorse or promote products derived
15d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*       from this software without specific prior written permission.
16d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*
17d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin*/
29d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
30d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <stdio.h>
31d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <unistd.h>
32d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <string.h>
33d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <pthread.h>
34d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <fcntl.h>
35d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <sys/prctl.h>
36d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <sys/ioctl.h>
37d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <sys/time.h>
38d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <sys/resource.h>
39d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <utils/debug.h>
40d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <utils/sys.h>
41d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <core/display_interface.h>
42d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
43d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include <string>
44d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
45d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include "hw_primary.h"
46d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#include "hw_color_manager.h"
47d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
48d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin#define __CLASS__ "HWPrimary"
49d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
50d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinnamespace sdm {
51d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
52d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinusing std::string;
53d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
54d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Create(HWInterface **intf, HWInfoInterface *hw_info_intf,
55d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                               BufferSyncHandler *buffer_sync_handler,
56d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                               HWEventHandler *eventhandler) {
57d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DisplayError error = kErrorNone;
58d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWPrimary *hw_primary = NULL;
59d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
60d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  hw_primary = new HWPrimary(buffer_sync_handler, hw_info_intf);
61d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  error = hw_primary->Init(eventhandler);
62d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (error != kErrorNone) {
63d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    delete hw_primary;
64d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  } else {
65d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    *intf = hw_primary;
66d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
67d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
68d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return error;
69d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
70d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
71d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Destroy(HWInterface *intf) {
72d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWPrimary *hw_primary = static_cast<HWPrimary *>(intf);
73d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  hw_primary->Deinit();
74d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  delete hw_primary;
75d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
76d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
77d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
78d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
79d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinHWPrimary::HWPrimary(BufferSyncHandler *buffer_sync_handler, HWInfoInterface *hw_info_intf)
80d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  : HWDevice(buffer_sync_handler) {
81d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWDevice::device_type_ = kDevicePrimary;
82d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWDevice::device_name_ = "Primary Display Device";
83d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWDevice::hw_info_intf_ = hw_info_intf;
84d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
85d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
86d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Init(HWEventHandler *eventhandler) {
87d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DisplayError error = kErrorNone;
88d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char node_path[kMaxStringLength] = { 0 };
89d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char data[kMaxStringLength] = { 0 };
90d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  const char *event_name[kNumDisplayEvents] = {"vsync_event", "show_blank_event", "idle_notify",
91d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                               "msm_fb_thermal_level"};
92d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
93d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  error = HWDevice::Init(eventhandler);
94d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (error != kErrorNone) {
95d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    goto CleanupOnError;
96d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
97d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
98d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  error = PopulateDisplayAttributes();
99d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (error != kErrorNone) {
100d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    goto CleanupOnError;
101d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
102d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
103d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Open nodes for polling
104d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  for (int event = 0; event < kNumDisplayEvents; event++) {
105d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    poll_fds_[event].fd = -1;
106d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
107d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
108d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!fake_vsync_) {
109d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    for (int event = 0; event < kNumDisplayEvents; event++) {
110d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      pollfd &poll_fd = poll_fds_[event];
111d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
112d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_node_index_,
113d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin               event_name[event]);
114d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
115d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      poll_fd.fd = Sys::open_(node_path, O_RDONLY);
116d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if (poll_fd.fd < 0) {
117d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        DLOGE("open failed for event=%d, error=%s", event, strerror(errno));
118d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        error = kErrorHardware;
119d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        goto CleanupOnError;
120d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
121d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
122d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // Read once on all fds to clear data on all fds.
123d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      Sys::pread_(poll_fd.fd, data , kMaxStringLength, 0);
124d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      poll_fd.events = POLLPRI | POLLERR;
125d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
126d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
127d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
128d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Start the Event thread
129d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
130d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Failed to start %s, error = %s", event_thread_name_);
131d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    error = kErrorResources;
132d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    goto CleanupOnError;
133d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
134d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
135d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Disable HPD at start if HDMI is external, it will be enabled later when the display powers on
136d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // This helps for framework reboot or adb shell stop/start
137d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  EnableHotPlugDetection(0);
138d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  InitializeConfigs();
139d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
140d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
141d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
142d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinCleanupOnError:
143d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Close all poll fds
144d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  for (int event = 0; event < kNumDisplayEvents; event++) {
145d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    int &fd = poll_fds_[event].fd;
146d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (fd >= 0) {
147d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      Sys::close_(fd);
148d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
149d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
150d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
151d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return error;
152d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
153d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
154d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinbool HWPrimary::GetCurrentModeFromSysfs(size_t *curr_x_pixels, size_t *curr_y_pixels) {
155d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  bool ret = false;
156d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  size_t len = kPageSize;
157d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  string mode_path = string(fb_path_) + string("0/mode");
158d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
159d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  FILE *fd = Sys::fopen_(mode_path.c_str(), "r");
160d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd) {
161d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
162d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
163d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (buffer == NULL) {
164d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DLOGW("Failed to allocate memory");
165d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      Sys::fclose_(fd);
166d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      return false;
167d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
168d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
169d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (Sys::getline_(&buffer, &len, fd) > 0) {
170d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // String is of form "U:1600x2560p-0". Documentation/fb/modedb.txt in
171d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // kernel has more info on the format.
172d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      size_t xpos = string(buffer).find(':');
173d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      size_t ypos = string(buffer).find('x');
174d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
175d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if (xpos == string::npos || ypos == string::npos) {
176d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        DLOGI("Resolution switch not supported");
177d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      } else {
1781c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed        *curr_x_pixels = static_cast<size_t>(atoi(buffer + xpos + 1));
1791c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed        *curr_y_pixels = static_cast<size_t>(atoi(buffer + ypos + 1));
180d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        DLOGI("Current Config: %u x %u", *curr_x_pixels, *curr_y_pixels);
181d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        ret = true;
182d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
183d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
184d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
185d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    free(buffer);
186d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    Sys::fclose_(fd);
187d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
188d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
189d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return ret;
190d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
191d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
192d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::InitializeConfigs() {
193d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  size_t curr_x_pixels = 0;
194d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  size_t curr_y_pixels = 0;
195d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  size_t len = kPageSize;
196d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  string modes_path = string(fb_path_) + string("0/modes");
197d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
198d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!GetCurrentModeFromSysfs(&curr_x_pixels, &curr_y_pixels)) {
199d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return;
200d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
201d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
202d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  FILE *fd = Sys::fopen_(modes_path.c_str(), "r");
203d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd) {
204d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    char *buffer = static_cast<char *>(calloc(len, sizeof(char)));
205d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
206d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (buffer == NULL) {
207d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DLOGW("Failed to allocate memory");
208d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      Sys::fclose_(fd);
209d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      return;
210d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
211d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
212d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    while (Sys::getline_(&buffer, &len, fd) > 0) {
213d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DisplayConfigVariableInfo config;
214d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      size_t xpos = string(buffer).find(':');
215d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      size_t ypos = string(buffer).find('x');
216d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
217d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if (xpos == string::npos || ypos == string::npos) {
218d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        continue;
219d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
220d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
2211c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed      config.x_pixels = UINT32(atoi(buffer + xpos + 1));
2221c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed      config.y_pixels = UINT32(atoi(buffer + ypos + 1));
223d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DLOGI("Found mode %d x %d", config.x_pixels, config.y_pixels);
224d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      display_configs_.push_back(config);
225d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      display_config_strings_.push_back(string(buffer));
226d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
227d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if (curr_x_pixels == config.x_pixels && curr_y_pixels == config.y_pixels) {
2281c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed        active_config_index_ = UINT32(display_configs_.size() - 1);
229d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        DLOGI("Active config index %u", active_config_index_);
230d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
231d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
232d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
233d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    free(buffer);
234d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    Sys::fclose_(fd);
235d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  } else {
236d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGI("Unable to process modes");
237d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
238d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
239d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
240d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Deinit() {
241d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  exit_threads_ = true;
242d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::pthread_cancel_(event_thread_);
243d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  pthread_join(event_thread_, NULL);
244d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
245d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  for (int event = 0; event < kNumDisplayEvents; event++) {
246d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    int &fd = poll_fds_[event].fd;
247d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (fd >= 0) {
248d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      Sys::close_(fd);
249d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
250d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
251d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
252d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return HWDevice::Deinit();
253d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
254d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
255d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetNumDisplayAttributes(uint32_t *count) {
2561c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  *count = IsResolutionSwitchEnabled() ? UINT32(display_configs_.size()) : 1;
257d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
258d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
259d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
260d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetActiveConfig(uint32_t *active_config_index) {
261d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  *active_config_index = active_config_index_;
262d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
263d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
264d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
265d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetDisplayAttributes(uint32_t index,
266d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                             HWDisplayAttributes *display_attributes) {
267d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!display_attributes) {
268d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorParameters;
269d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
270d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
271d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (IsResolutionSwitchEnabled() && index >= display_configs_.size()) {
272d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorParameters;
273d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
274d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
275d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  *display_attributes = display_attributes_;
276d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (IsResolutionSwitchEnabled()) {
277d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    // Overwrite only the parent portion of object
278d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    display_attributes->x_pixels = display_configs_.at(index).x_pixels;
279d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    display_attributes->y_pixels = display_configs_.at(index).y_pixels;
280d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
281d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
282d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
283d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
284d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
285d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::PopulateDisplayAttributes() {
286d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DTRACE_SCOPED();
287d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
288d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Variable screen info
289d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  STRUCT_VAR(fb_var_screeninfo, var_screeninfo);
290d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
291d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, FBIOGET_VSCREENINFO, &var_screeninfo) < 0) {
292d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(FBIOGET_VSCREENINFO, device_type_);
293d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
294d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
295d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
296d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Frame rate
297d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  STRUCT_VAR(msmfb_metadata, meta_data);
298d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  meta_data.op = metadata_op_frame_rate;
299d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, MSMFB_METADATA_GET, &meta_data) < 0) {
300d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(MSMFB_METADATA_GET, device_type_);
301d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
302d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
303d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
304d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // If driver doesn't return width/height information, default to 160 dpi
305d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (INT(var_screeninfo.width) <= 0 || INT(var_screeninfo.height) <= 0) {
3061c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    var_screeninfo.width  = UINT32(((FLOAT(var_screeninfo.xres) * 25.4f)/160.0f) + 0.5f);
3071c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    var_screeninfo.height = UINT32(((FLOAT(var_screeninfo.yres) * 25.4f)/160.0f) + 0.5f);
308d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
309d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
310d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.x_pixels = var_screeninfo.xres;
311d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.y_pixels = var_screeninfo.yres;
312d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.v_front_porch = var_screeninfo.lower_margin;
313d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.v_back_porch = var_screeninfo.upper_margin;
314d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.v_pulse_width = var_screeninfo.vsync_len;
315d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  uint32_t h_blanking = var_screeninfo.right_margin + var_screeninfo.left_margin +
316d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      var_screeninfo.hsync_len;
317d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.h_total = var_screeninfo.xres + h_blanking;
318d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.x_dpi =
319d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      (FLOAT(var_screeninfo.xres) * 25.4f) / FLOAT(var_screeninfo.width);
320d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.y_dpi =
321d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      (FLOAT(var_screeninfo.yres) * 25.4f) / FLOAT(var_screeninfo.height);
322d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.fps = meta_data.data.panel_frame_rate;
323d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.vsync_period_ns = UINT32(1000000000L / display_attributes_.fps);
324d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.is_device_split = (hw_panel_info_.split_info.left_split ||
325d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      (var_screeninfo.xres > hw_resource_.max_mixer_width)) ? true : false;
326d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.split_left = hw_panel_info_.split_info.left_split ?
327d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      hw_panel_info_.split_info.left_split : display_attributes_.x_pixels / 2;
328d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  display_attributes_.h_total += display_attributes_.is_device_split ? h_blanking : 0;
329d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
330d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
331d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
332d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
333d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetDisplayAttributes(uint32_t index) {
334d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DisplayError ret = kErrorNone;
335d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
336d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!IsResolutionSwitchEnabled()) {
337d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorNotSupported;
338d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
339d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
340d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (index >= display_configs_.size()) {
341d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorParameters;
342d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
343d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
344d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  string mode_path = string(fb_path_) + string("0/mode");
345d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int fd = Sys::open_(mode_path.c_str(), O_WRONLY);
346d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
347d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd < 0) {
348d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Opening mode failed");
349d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorNotSupported;
350d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
351d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
352d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  ssize_t written = Sys::pwrite_(fd, display_config_strings_.at(index).c_str(),
353d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                 display_config_strings_.at(index).length(), 0);
354d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (written > 0) {
355d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGI("Successfully set config %u", index);
356d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    PopulateHWPanelInfo();
357d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    PopulateDisplayAttributes();
358d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    active_config_index_ = index;
359d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  } else {
360d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Writing config index %u failed with error: %s", index, strerror(errno));
361d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    ret = kErrorParameters;
362d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
363d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
364d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::close_(fd);
365d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
366d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return ret;
367d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
368d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
369d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetRefreshRate(uint32_t refresh_rate) {
370d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char node_path[kMaxStringLength] = {0};
371d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
372d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (refresh_rate == display_attributes_.fps) {
373d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorNone;
374d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
375d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
376d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  snprintf(node_path, sizeof(node_path), "%s%d/dynamic_fps", fb_path_, fb_node_index_);
377d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
378d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int fd = Sys::open_(node_path, O_WRONLY);
379d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd < 0) {
380d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Failed to open %s with error %s", node_path, strerror(errno));
381d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorFileDescriptor;
382d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
383d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
384d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char refresh_rate_string[kMaxStringLength];
385d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  snprintf(refresh_rate_string, sizeof(refresh_rate_string), "%d", refresh_rate);
386d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DLOGI_IF(kTagDriverConfig, "Setting refresh rate = %d", refresh_rate);
387d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  ssize_t len = Sys::pwrite_(fd, refresh_rate_string, strlen(refresh_rate_string), 0);
388d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (len < 0) {
389d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Failed to write %d with error %s", refresh_rate, strerror(errno));
390d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    Sys::close_(fd);
391d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorUndefined;
392d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
393d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::close_(fd);
394d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
395d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DisplayError error = PopulateDisplayAttributes();
396d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (error != kErrorNone) {
397d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return error;
398d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
399d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
400d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
401d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
402d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
403d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetConfigIndex(uint32_t mode, uint32_t *index) {
404d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return HWDevice::GetConfigIndex(mode, index);
405d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
406d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
407d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::PowerOff() {
408d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_POWERDOWN) < 0) {
409d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(FB_BLANK_POWERDOWN, device_type_);
410d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
411d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
412d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
413d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
414d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
415d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
416d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Doze() {
417d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_NORMAL) < 0) {
418d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(FB_BLANK_NORMAL, device_type_);
419d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
420d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
421d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
422d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
423d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
424d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
425d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::DozeSuspend() {
426d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, FBIOBLANK, FB_BLANK_VSYNC_SUSPEND) < 0) {
427d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(FB_BLANK_VSYNC_SUSPEND, device_type_);
428d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
429d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
430d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
431d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
432d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
433d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
434d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::Validate(HWLayers *hw_layers) {
435d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  HWDevice::ResetDisplayParams();
436d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
437d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  mdp_layer_commit_v1 &mdp_commit = mdp_disp_commit_.commit_v1;
438d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
439d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  LayerRect left_roi = hw_layers->info.left_partial_update;
440d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  LayerRect right_roi = hw_layers->info.right_partial_update;
4411c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  mdp_commit.left_roi.x = UINT32(left_roi.left);
4421c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  mdp_commit.left_roi.y = UINT32(left_roi.top);
4431c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  mdp_commit.left_roi.w = UINT32(left_roi.right - left_roi.left);
4441c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  mdp_commit.left_roi.h = UINT32(left_roi.bottom - left_roi.top);
445d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
446d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // SDM treats ROI as one full coordinate system.
447d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // In case source split is disabled, However, Driver assumes Mixer to operate in
448d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // different co-ordinate system.
449d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!hw_resource_.is_src_split) {
4501c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    mdp_commit.right_roi.x = UINT32(right_roi.left) - hw_panel_info_.split_info.left_split;
4511c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    mdp_commit.right_roi.y = UINT32(right_roi.top);
4521c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    mdp_commit.right_roi.w = UINT32(right_roi.right - right_roi.left);
4531c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    mdp_commit.right_roi.h = UINT32(right_roi.bottom - right_roi.top);
454d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
455d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
456d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return HWDevice::Validate(hw_layers);
457d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
458d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
459d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid* HWPrimary::DisplayEventThread(void *context) {
460d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (context) {
461d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return reinterpret_cast<HWPrimary *>(context)->DisplayEventThreadHandler();
462d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
463d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
464d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return NULL;
465d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
466d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
467d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid* HWPrimary::DisplayEventThreadHandler() {
468d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char data[kMaxStringLength] = {0};
469d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
470d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  prctl(PR_SET_NAME, event_thread_name_, 0, 0, 0);
471d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
472d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
473d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fake_vsync_) {
474d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    while (!exit_threads_) {
475d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // Fake vsync is used only when set explicitly through a property(todo) or when
476d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // the vsync timestamp node cannot be opened at bootup. There is no
477d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // fallback to fake vsync from the true vsync loop, ever, as the
478d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // condition can easily escape detection.
479d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // Also, fake vsync is delivered only for the primary display.
480d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      usleep(16666);
481d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      STRUCT_VAR(timeval, time_now);
482d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      gettimeofday(&time_now, NULL);
4831c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed      int64_t ts = int64_t(time_now.tv_sec)*1000000000LL +int64_t(time_now.tv_usec)*1000LL;
484d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
485d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      // Send Vsync event for primary display(0)
486d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      event_handler_->VSync(ts);
487d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
488d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
489d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    pthread_exit(0);
490d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
491d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
492d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  typedef void (HWPrimary::*EventHandler)(char*);
493d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  EventHandler event_handler[kNumDisplayEvents] = { &HWPrimary::HandleVSync,
494d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                                    &HWPrimary::HandleBlank,
495d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                                    &HWPrimary::HandleIdleTimeout,
496d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin                                                    &HWPrimary::HandleThermal };
497d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
498d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  while (!exit_threads_) {
499d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    int error = Sys::poll_(poll_fds_, kNumDisplayEvents, -1);
500d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (error <= 0) {
501d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DLOGW("poll failed. error = %s", strerror(errno));
502d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      continue;
503d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
504d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
505d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    for (int event = 0; event < kNumDisplayEvents; event++) {
506d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      pollfd &poll_fd = poll_fds_[event];
507d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
508d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if (poll_fd.revents & POLLPRI) {
509d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        if (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0) {
510d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin          (this->*event_handler[event])(data);
511d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        }
512d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
513d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
514d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
515d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
516d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  pthread_exit(0);
517d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
518d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return NULL;
519d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
520d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
521d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::HandleVSync(char *data) {
522d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int64_t timestamp = 0;
523d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
5241c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    timestamp = strtoll(data + strlen("VSYNC="), NULL, 0);
525d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
526d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  event_handler_->VSync(timestamp);
527d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
528d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
529d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::HandleBlank(char *data) {
530d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // TODO(user): Need to send blank Event
531d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
532d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
533d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::HandleIdleTimeout(char *data) {
534d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  event_handler_->IdleTimeout();
535d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
536d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
537d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::HandleThermal(char *data) {
538d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int64_t thermal_level = 0;
539d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
5401c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    thermal_level = strtoll(data + strlen("thermal_level="), NULL, 0);
541d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
542d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
543d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DLOGI("Received thermal notification with thermal level = %d", thermal_level);
544d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
545d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  event_handler_->ThermalEvent(thermal_level);
546d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
547d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
548d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjinvoid HWPrimary::SetIdleTimeoutMs(uint32_t timeout_ms) {
549d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char node_path[kMaxStringLength] = {0};
550d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
551d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DLOGI_IF(kTagDriverConfig, "Setting idle timeout to = %d ms", timeout_ms);
552d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
553d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  snprintf(node_path, sizeof(node_path), "%s%d/idle_time", fb_path_, fb_node_index_);
554d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
555d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Open a sysfs node to send the timeout value to driver.
556d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int fd = Sys::open_(node_path, O_WRONLY);
557d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd < 0) {
558d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Unable to open %s, node %s", node_path, strerror(errno));
559d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return;
560d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
561d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
562d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char timeout_string[64];
563d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  snprintf(timeout_string, sizeof(timeout_string), "%d", timeout_ms);
564d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
565d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Notify driver about the timeout value
566d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  ssize_t length = Sys::pwrite_(fd, timeout_string, strlen(timeout_string), 0);
567d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (length <= 0) {
568d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGE("Unable to write into %s, node %s", node_path, strerror(errno));
569d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
570d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
571d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::close_(fd);
572d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
573d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
574d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetVSyncState(bool enable) {
575d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DTRACE_SCOPED();
576d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
577d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int vsync_on = enable ? 1 : 0;
578d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::ioctl_(device_fd_, MSMFB_OVERLAY_VSYNC_CTRL, &vsync_on) < 0) {
579d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(MSMFB_OVERLAY_VSYNC_CTRL, device_type_);
580d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
581d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
582d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
583d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
584d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
585d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
586d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetDisplayMode(const HWDisplayMode hw_display_mode) {
5871c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  uint32_t mode = kModeDefault;
588d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
589d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  switch (hw_display_mode) {
590d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  case kModeVideo:
591d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    mode = kModeLPMVideo;
592d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    break;
593d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  case kModeCommand:
594d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    mode = kModeLPMCommand;
595d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    break;
596d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  default:
597d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGW("Failed to translate SDE display mode %d to a MSMFB_LPM_ENABLE mode",
598d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin          hw_display_mode);
599d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorParameters;
600d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
601d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
6021c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  if (Sys::ioctl_(device_fd_, INT(MSMFB_LPM_ENABLE), &mode) < 0) {
603d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    IOCTL_LOGE(MSMFB_LPM_ENABLE, device_type_);
604d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorHardware;
605d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
606d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
607d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DLOGI("Triggering display mode change to %d on next commit.", hw_display_mode);
608d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  synchronous_commit_ = true;
609d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
610d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
611d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
612d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
613d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetPanelBrightness(int level) {
614d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char buffer[MAX_SYSFS_COMMAND_LENGTH] = {0};
615d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
616d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  DLOGV_IF(kTagDriverConfig, "Set brightness level to %d", level);
617d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int fd = Sys::open_(kBrightnessNode, O_RDWR);
618d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd < 0) {
619d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Failed to open node = %s, error = %s ", kBrightnessNode,
620d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin             strerror(errno));
621d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorFileDescriptor;
622d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
623d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
624d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int32_t bytes = snprintf(buffer, MAX_SYSFS_COMMAND_LENGTH, "%d\n", level);
625d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (bytes < 0) {
626d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Failed to copy new brightness level = %d", level);
627d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    Sys::close_(fd);
628d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorUndefined;
629d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
630d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
6311c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed  ssize_t ret = Sys::pwrite_(fd, buffer, static_cast<size_t>(bytes), 0);
632d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (ret <= 0) {
633d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Failed to write to node = %s, error = %s ", kBrightnessNode,
634d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin             strerror(errno));
635d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    Sys::close_(fd);
636d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorUndefined;
637d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
638d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::close_(fd);
639d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
640d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
641d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
642d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
643d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetPanelBrightness(int *level) {
644d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char brightness[kMaxStringLength] = {0};
645d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
646d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (!level) {
647d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Invalid input, null pointer.");
648d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorParameters;
649d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
650d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
651d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int fd = Sys::open_(kBrightnessNode, O_RDWR);
652d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (fd < 0) {
653d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Failed to open brightness node = %s, error = %s", kBrightnessNode,
654d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin             strerror(errno));
655d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorFileDescriptor;
656d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
657d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
658d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (Sys::pread_(fd, brightness, sizeof(brightness), 0) > 0) {
659d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    *level = atoi(brightness);
660d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    DLOGV_IF(kTagDriverConfig, "Brightness level = %d", *level);
661d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
662d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  Sys::close_(fd);
663d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
664d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
665d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
666d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
667d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetAutoRefresh(bool enable) {
668d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  const int kWriteLength = 2;
669d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  char buffer[kWriteLength] = {'\0'};
670d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  ssize_t bytes = snprintf(buffer, kWriteLength, "%d", enable);
671d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
672829790261efb161bff68251b0a1baceae6610430Mekala Natarajan  if (enable == auto_refresh_) {
673829790261efb161bff68251b0a1baceae6610430Mekala Natarajan    return kErrorNone;
674829790261efb161bff68251b0a1baceae6610430Mekala Natarajan  }
675829790261efb161bff68251b0a1baceae6610430Mekala Natarajan
676d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  if (HWDevice::SysFsWrite(kAutoRefreshNode, buffer, bytes) <= 0) {  // Returns bytes written
677d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    return kErrorUndefined;
678d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
679d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
680829790261efb161bff68251b0a1baceae6610430Mekala Natarajan  auto_refresh_ = enable;
681829790261efb161bff68251b0a1baceae6610430Mekala Natarajan
682d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
683d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
684d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
685d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::GetPPFeaturesVersion(PPFeatureVersion *vers) {
686d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  STRUCT_VAR(mdp_pp_feature_version, version);
687d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
688d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  uint32_t feature_id_mapping[kMaxNumPPFeatures] = { PCC, IGC, GC, GC, PA, DITHER, GAMUT };
689d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
690d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  for (int i(0); i < kMaxNumPPFeatures; i++) {
691d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    version.pp_feature = feature_id_mapping[i];
692d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
6931c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed    if (Sys::ioctl_(device_fd_,  INT(MSMFB_MDP_PP_GET_FEATURE_VERSION), &version) < 0) {
694d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      IOCTL_LOGE(MSMFB_MDP_PP_GET_FEATURE_VERSION, device_type_);
695d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      return kErrorHardware;
696d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
697d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    vers->version[i] = version.version_info;
698d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }
699d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
700d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
701d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
702d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
703d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin// It was entered with PPFeaturesConfig::locker_ being hold.
704d68a2e45260f864503d7bd6da93fd29589afd89ePatrick TjinDisplayError HWPrimary::SetPPFeatures(PPFeaturesConfig *feature_list) {
705d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  STRUCT_VAR(msmfb_mdp_pp, kernel_params);
706d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  int ret = 0;
707d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  PPFeatureInfo *feature = NULL;
708d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
709d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  while (true) {
710d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    ret = feature_list->RetrieveNextFeature(&feature);
711d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (ret)
712d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        break;
713d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
714d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    if (feature) {
715d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      DLOGV_IF(kTagDriverConfig, "feature_id = %d", feature->feature_id_);
716d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
717d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      if ((feature->feature_id_ < kMaxNumPPFeatures)) {
718d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        HWColorManager::SetFeature[feature->feature_id_](*feature, &kernel_params);
7191c83c9c682ae9a6a43bd7e1a199355333c70a8cdNaseer Ahmed        if (Sys::ioctl_(device_fd_, INT(MSMFB_MDP_PP), &kernel_params) < 0) {
720d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin          IOCTL_LOGE(MSMFB_MDP_PP, device_type_);
721d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
722d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin          feature_list->Reset();
723d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin          return kErrorHardware;
724d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin        }
725d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin      }
726d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin    }
727d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  }  // while(true)
728d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
729d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Once all features were consumed, then destroy all feature instance from feature_list,
730d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  // Then mark it as non-dirty of PPFeaturesConfig cache.
731d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  feature_list->Reset();
732d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
733d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin  return kErrorNone;
734d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}
735d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
736d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin}  // namespace sdm
737d68a2e45260f864503d7bd6da93fd29589afd89ePatrick Tjin
738