blob: 170b1d872a2a9ee14273e773aec80399afd1ee4c [file] [log] [blame]
Ken Zhang61cc6032013-06-02 10:54:16 -04001/*
Ramkumar Radhakrishnanb3d15b62017-01-06 22:35:06 -08002 * Copyright (c) 2013, 2017 The Linux Foundation. All rights reserved.
Ken Zhang61cc6032013-06-02 10:54:16 -04003
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
Saurabh Shahc5b2b702016-10-24 17:16:01 -070030#include <unistd.h>
Ken Zhang61cc6032013-06-02 10:54:16 -040031#include "qd_utils.h"
Ken Zhang61cc6032013-06-02 10:54:16 -040032
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -070033namespace qdutils {
34
Ramkumar Radhakrishnanb3d15b62017-01-06 22:35:06 -080035static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
Ramkumar Radhakrishnan29a36a52015-06-16 20:22:42 -070036 char *tmpToken = NULL;
37 char *tmpPtr;
38 uint32_t index = 0;
39 const char *delim = ", =\n";
40 if (!input) {
41 return -1;
42 }
43 tmpToken = strtok_r(input, delim, &tmpPtr);
44 while (tmpToken && index < maxToken) {
45 tokens[index++] = tmpToken;
46 tmpToken = strtok_r(NULL, delim, &tmpPtr);
47 }
48 *count = index;
49
50 return 0;
51}
52
Ramkumar Radhakrishnanb3d15b62017-01-06 22:35:06 -080053static int getExternalNode(const char *type) {
54 FILE *displayDeviceFP = NULL;
55 char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
56 char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
57 int j = 0;
58
59 for(j = 0; j < HWC_NUM_DISPLAY_TYPES; j++) {
60 snprintf (msmFbTypePath, sizeof(msmFbTypePath),
61 "/sys/class/graphics/fb%d/msm_fb_type", j);
62 displayDeviceFP = fopen(msmFbTypePath, "r");
63 if(displayDeviceFP) {
64 fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
65 displayDeviceFP);
66 if(strncmp(fbType, type, strlen(type)) == 0) {
67 ALOGD("%s: %s is at fb%d", __func__, type, j);
68 fclose(displayDeviceFP);
69 break;
70 }
71 fclose(displayDeviceFP);
72 } else {
73 ALOGE("%s: Failed to open fb node %d", __func__, j);
74 }
75 }
76
77 if (j < HWC_NUM_DISPLAY_TYPES)
78 return j;
79 else
80 ALOGE("%s: Failed to find %s node", __func__, type);
81
82 return -1;
83}
84
Saurabh Shahc5b2b702016-10-24 17:16:01 -070085static int querySDEInfoDRM(HWQueryType type, int *value) {
86 char property[PROPERTY_VALUE_MAX] = {0};
87
88 // TODO(user): If future targets don't support WB UBWC, add separate
89 // properties in target specific system.prop and have clients like WFD
90 // directly rely on those.
91 switch(type) {
92 case HAS_UBWC:
93 case HAS_WB_UBWC: // WFD stack still uses this
94 *value = 1;
95 property_get("debug.gralloc.gfx_ubwc_disable", property, "0");
96 if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
97 !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
98 *value = 0;
99 }
100 break;
101 default:
102 ALOGE("Invalid query type %d", type);
103 return -EINVAL;
104 }
105
106 return 0;
107}
108
109static int querySDEInfoFB(HWQueryType type, int *value) {
Ramkumar Radhakrishnan29a36a52015-06-16 20:22:42 -0700110 FILE *fileptr = NULL;
111 const char *featureName;
112 char stringBuffer[MAX_STRING_LENGTH];
113 uint32_t tokenCount = 0;
114 const uint32_t maxCount = 10;
115 char *tokens[maxCount] = { NULL };
116
117 switch(type) {
Sushil Chauhan01361412016-04-25 16:36:18 -0700118 case HAS_UBWC:
119 featureName = "ubwc";
120 break;
Jeykumar Sankaran9bc1a782015-12-14 18:36:27 -0800121 case HAS_WB_UBWC:
122 featureName = "wb_ubwc";
123 break;
Ramkumar Radhakrishnan29a36a52015-06-16 20:22:42 -0700124 default:
125 ALOGE("Invalid query type %d", type);
126 return -EINVAL;
127 }
128
129 fileptr = fopen("/sys/devices/virtual/graphics/fb0/mdp/caps", "rb");
130 if (!fileptr) {
131 ALOGE("File '%s' not found", stringBuffer);
132 return -EINVAL;
133 }
134
135 size_t len = MAX_STRING_LENGTH;
136 ssize_t read;
137 char *line = stringBuffer;
138 while ((read = getline(&line, &len, fileptr)) != -1) {
139 // parse the line and update information accordingly
140 if (parseLine(line, tokens, maxCount, &tokenCount)) {
141 continue;
142 }
143
144 if (strncmp(tokens[0], "features", strlen("features"))) {
145 continue;
146 }
147
148 for (uint32_t i = 0; i < tokenCount; i++) {
149 if (!strncmp(tokens[i], featureName, strlen(featureName))) {
150 *value = 1;
151 }
152 }
153 }
154 fclose(fileptr);
155
156 return 0;
157}
158
Saurabh Shahc5b2b702016-10-24 17:16:01 -0700159int querySDEInfo(HWQueryType type, int *value) {
160 if (!value) {
161 return -EINVAL;
162 }
163
164 if (getDriverType() == DriverType::DRM) {
165 return querySDEInfoDRM(type, value);
166 }
167
168 return querySDEInfoFB(type, value);
169}
170
Ramkumar Radhakrishnanb3d15b62017-01-06 22:35:06 -0800171int getHDMINode(void) {
172 return getExternalNode("dtv panel");
Ken Zhang61cc6032013-06-02 10:54:16 -0400173}
174
175int getEdidRawData(char *buffer)
176{
177 int size;
178 int edidFile;
179 char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
180 int node_id = getHDMINode();
181
182 if (node_id < 0) {
183 ALOGE("%s no HDMI node found", __func__);
184 return 0;
185 }
186
187 snprintf(msmFbTypePath, sizeof(msmFbTypePath),
188 "/sys/class/graphics/fb%d/edid_raw_data", node_id);
189
Ramkumar Radhakrishnan29a36a52015-06-16 20:22:42 -0700190 edidFile = open(msmFbTypePath, O_RDONLY, 0);
Ken Zhang61cc6032013-06-02 10:54:16 -0400191
192 if (edidFile < 0) {
193 ALOGE("%s no edid raw data found", __func__);
194 return 0;
195 }
196
Dileep Kumar Reddibf333c72014-02-25 14:32:51 +0530197 size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
Ken Zhang61cc6032013-06-02 10:54:16 -0400198 close(edidFile);
199 return size;
200}
201
Ramkumar Radhakrishnanb3d15b62017-01-06 22:35:06 -0800202bool isDPConnected() {
203 char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
204 FILE *connectFile = NULL;
205 size_t len = MAX_STRING_LENGTH;
206 char stringBuffer[MAX_STRING_LENGTH];
207 char *line = stringBuffer;
208
209 int nodeId = getExternalNode("dp panel");
210 if (nodeId < 0) {
211 ALOGE("%s no DP node found", __func__);
212 return false;
213 }
214
215 snprintf(connectPath, sizeof(connectPath),
216 "/sys/class/graphics/fb%d/connected", nodeId);
217
218 connectFile = fopen(connectPath, "rb");
219 if (!connectFile) {
220 ALOGW("Failed to open connect node for device node %d", nodeId);
221 return false;
222 }
223
224 if (getline(&line, &len, connectFile) < 0) {
225 fclose(connectFile);
226 return false;
227 }
228
229 fclose(connectFile);
230
231 return atoi(line);
232}
233
234int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
235 if (!panelBpp || !patternType) {
236 return -1;
237 }
238
239 char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
240 FILE *configFile = NULL;
241 uint32_t tokenCount = 0;
242 const uint32_t maxCount = 10;
243 char *tokens[maxCount] = { NULL };
244 size_t len = MAX_STRING_LENGTH;
245 char stringBuffer[MAX_STRING_LENGTH];
246 char *line = stringBuffer;
247
248 int nodeId = getExternalNode("dp panel");
249 if (nodeId < 0) {
250 ALOGE("%s no DP node found", __func__);
251 return -EINVAL;
252 }
253
254 snprintf(configPath, sizeof(configPath),
255 "/sys/class/graphics/fb%d/config", nodeId);
256
257 configFile = fopen(configPath, "rb");
258 if (!configFile) {
259 ALOGW("Failed to open config node for device node %d", nodeId);
260 return -EINVAL;
261 }
262
263 while (getline(&line, &len, configFile) != -1) {
264 if (!parseLine(line, tokens, maxCount, &tokenCount)) {
265 if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
266 *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
267 } else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
268 *patternType = static_cast<uint32_t>(atoi(tokens[1]));
269 }
270 }
271 }
272
273 fclose(configFile);
274
275 return 0;
276}
277
Saurabh Shahc5b2b702016-10-24 17:16:01 -0700278DriverType getDriverType() {
279 const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
280 // 0 - File exists
281 return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
282}
283
Tatenda Chipeperekwace8d5c42014-08-13 10:53:49 -0700284}; //namespace qdutils