1 /*
2 * Copyright (c) 2013, 2018 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 <unistd.h>
31 #include <gralloc_priv.h>
32 #include "qd_utils.h"
33
34 static const int kFBNodeMax = 4;
35 namespace qdutils {
36
parseLine(char * input,char * tokens[],const uint32_t maxToken,uint32_t * count)37 static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) {
38 char *tmpToken = NULL;
39 char *tmpPtr;
40 uint32_t index = 0;
41 const char *delim = ", =\n";
42 if (!input) {
43 return -1;
44 }
45 tmpToken = strtok_r(input, delim, &tmpPtr);
46 while (tmpToken && index < maxToken) {
47 tokens[index++] = tmpToken;
48 tmpToken = strtok_r(NULL, delim, &tmpPtr);
49 }
50 *count = index;
51
52 return 0;
53 }
54
getExternalNode(const char * type)55 static int getExternalNode(const char *type) {
56 FILE *displayDeviceFP = NULL;
57 char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
58 char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
59 int j = 0;
60
61 for(j = 0; j < kFBNodeMax; j++) {
62 snprintf (msmFbTypePath, sizeof(msmFbTypePath),
63 "/sys/devices/virtual/graphics/fb%d/msm_fb_type", j);
64 displayDeviceFP = fopen(msmFbTypePath, "r");
65 if(displayDeviceFP) {
66 fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
67 displayDeviceFP);
68 if(strncmp(fbType, type, strlen(type)) == 0) {
69 ALOGD("%s: %s is at fb%d", __func__, type, j);
70 fclose(displayDeviceFP);
71 break;
72 }
73 fclose(displayDeviceFP);
74 } else {
75 ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath);
76 }
77 }
78
79 if (j < kFBNodeMax)
80 return j;
81 else
82 ALOGE("%s: Failed to find %s node", __func__, type);
83
84 return -1;
85 }
86
querySDEInfoDRM(HWQueryType type,int * value)87 static int querySDEInfoDRM(HWQueryType type, int *value) {
88 char property[PROPERTY_VALUE_MAX] = {0};
89
90 // TODO(user): If future targets don't support WB UBWC, add separate
91 // properties in target specific system.prop and have clients like WFD
92 // directly rely on those.
93 switch(type) {
94 case HAS_UBWC:
95 case HAS_WB_UBWC: // WFD stack still uses this
96 *value = 1;
97 property_get(DISABLE_UBWC_PROP, property, "0");
98 if(!(strncmp(property, "1", PROPERTY_VALUE_MAX)) ||
99 !(strncmp(property, "true", PROPERTY_VALUE_MAX))) {
100 *value = 0;
101 }
102 break;
103 default:
104 ALOGE("Invalid query type %d", type);
105 return -EINVAL;
106 }
107
108 return 0;
109 }
110
querySDEInfoFB(HWQueryType type,int * value)111 static int querySDEInfoFB(HWQueryType type, int *value) {
112 FILE *fileptr = NULL;
113 const char *featureName;
114 char stringBuffer[MAX_STRING_LENGTH];
115 uint32_t tokenCount = 0;
116 const uint32_t maxCount = 10;
117 char *tokens[maxCount] = { NULL };
118
119 switch(type) {
120 case HAS_UBWC:
121 featureName = "ubwc";
122 break;
123 case HAS_WB_UBWC:
124 featureName = "wb_ubwc";
125 break;
126 default:
127 ALOGE("Invalid query type %d", type);
128 return -EINVAL;
129 }
130
131 fileptr = fopen("/sys/devices/virtual/graphics/fb0/mdp/caps", "rb");
132 if (!fileptr) {
133 ALOGE("File '%s' not found", stringBuffer);
134 return -EINVAL;
135 }
136
137 size_t len = MAX_STRING_LENGTH;
138 ssize_t read;
139 char *line = stringBuffer;
140 while ((read = getline(&line, &len, fileptr)) != -1) {
141 // parse the line and update information accordingly
142 if (parseLine(line, tokens, maxCount, &tokenCount)) {
143 continue;
144 }
145
146 if (strncmp(tokens[0], "features", strlen("features"))) {
147 continue;
148 }
149
150 for (uint32_t i = 0; i < tokenCount; i++) {
151 if (!strncmp(tokens[i], featureName, strlen(featureName))) {
152 *value = 1;
153 }
154 }
155 }
156 fclose(fileptr);
157
158 return 0;
159 }
160
querySDEInfo(HWQueryType type,int * value)161 int querySDEInfo(HWQueryType type, int *value) {
162 if (!value) {
163 return -EINVAL;
164 }
165
166 if (getDriverType() == DriverType::DRM) {
167 return querySDEInfoDRM(type, value);
168 }
169
170 return querySDEInfoFB(type, value);
171 }
172
getHDMINode(void)173 int getHDMINode(void) {
174 return getExternalNode("dtv panel");
175 }
176
getEdidRawData(char * buffer)177 int getEdidRawData(char *buffer)
178 {
179 int size;
180 int edidFile;
181 char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
182 int node_id = getHDMINode();
183
184 if (node_id < 0) {
185 ALOGE("%s no HDMI node found", __func__);
186 return 0;
187 }
188
189 snprintf(msmFbTypePath, sizeof(msmFbTypePath),
190 "/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id);
191
192 edidFile = open(msmFbTypePath, O_RDONLY, 0);
193
194 if (edidFile < 0) {
195 ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath);
196 return 0;
197 }
198
199 size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE);
200 close(edidFile);
201 return size;
202 }
203
isDPConnected()204 bool isDPConnected() {
205 char connectPath[MAX_FRAME_BUFFER_NAME_SIZE];
206 FILE *connectFile = NULL;
207 size_t len = MAX_STRING_LENGTH;
208 char stringBuffer[MAX_STRING_LENGTH];
209 char *line = stringBuffer;
210
211 int nodeId = getExternalNode("dp panel");
212 if (nodeId < 0) {
213 ALOGE("%s no DP node found", __func__);
214 return false;
215 }
216
217 snprintf(connectPath, sizeof(connectPath),
218 "/sys/devices/virtual/graphics/fb%d/connected", nodeId);
219
220 connectFile = fopen(connectPath, "rb");
221 if (!connectFile) {
222 ALOGW("Failed to open connect node for device node %s", connectPath);
223 return false;
224 }
225
226 if (getline(&line, &len, connectFile) < 0) {
227 fclose(connectFile);
228 return false;
229 }
230
231 fclose(connectFile);
232
233 return atoi(line);
234 }
235
getDPTestConfig(uint32_t * panelBpp,uint32_t * patternType)236 int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) {
237 if (!panelBpp || !patternType) {
238 return -1;
239 }
240
241 char configPath[MAX_FRAME_BUFFER_NAME_SIZE];
242 FILE *configFile = NULL;
243 uint32_t tokenCount = 0;
244 const uint32_t maxCount = 10;
245 char *tokens[maxCount] = { NULL };
246 size_t len = MAX_STRING_LENGTH;
247 char stringBuffer[MAX_STRING_LENGTH];
248 char *line = stringBuffer;
249
250 int nodeId = getExternalNode("dp panel");
251 if (nodeId < 0) {
252 ALOGE("%s no DP node found", __func__);
253 return -EINVAL;
254 }
255
256 snprintf(configPath, sizeof(configPath),
257 "/sys/devices/virtual/graphics/fb%d/config", nodeId);
258
259 configFile = fopen(configPath, "rb");
260 if (!configFile) {
261 ALOGW("Failed to open config node for device node %s", configPath);
262 return -EINVAL;
263 }
264
265 while (getline(&line, &len, configFile) != -1) {
266 if (!parseLine(line, tokens, maxCount, &tokenCount)) {
267 if (tokens[0] != NULL) {
268 if (!strncmp(tokens[0], "bpp", strlen("bpp"))) {
269 *panelBpp = static_cast<uint32_t>(atoi(tokens[1]));
270 } else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) {
271 *patternType = static_cast<uint32_t>(atoi(tokens[1]));
272 }
273 }
274 }
275 }
276
277 fclose(configFile);
278
279 return 0;
280 }
281
getDriverType()282 DriverType getDriverType() {
283 const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps";
284 // 0 - File exists
285 return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB;
286 }
287
GetHALPixelFormatString(int format)288 const char *GetHALPixelFormatString(int format) {
289 switch (format) {
290 case HAL_PIXEL_FORMAT_RGBA_8888:
291 return "RGBA_8888";
292 case HAL_PIXEL_FORMAT_RGBX_8888:
293 return "RGBX_8888";
294 case HAL_PIXEL_FORMAT_RGB_888:
295 return "RGB_888";
296 case HAL_PIXEL_FORMAT_RGB_565:
297 return "RGB_565";
298 case HAL_PIXEL_FORMAT_BGR_565:
299 return "BGR_565";
300 case HAL_PIXEL_FORMAT_BGRA_8888:
301 return "BGRA_8888";
302 case HAL_PIXEL_FORMAT_RGBA_5551:
303 return "RGBA_5551";
304 case HAL_PIXEL_FORMAT_RGBA_4444:
305 return "RGBA_4444";
306 case HAL_PIXEL_FORMAT_YV12:
307 return "YV12";
308 case HAL_PIXEL_FORMAT_YCbCr_422_SP:
309 return "YCbCr_422_SP_NV16";
310 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
311 return "YCrCb_420_SP_NV21";
312 case HAL_PIXEL_FORMAT_YCbCr_422_I:
313 return "YCbCr_422_I_YUY2";
314 case HAL_PIXEL_FORMAT_YCrCb_422_I:
315 return "YCrCb_422_I_YVYU";
316 case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
317 return "NV12_ENCODEABLE";
318 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
319 return "YCbCr_420_SP_TILED_TILE_4x2";
320 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
321 return "YCbCr_420_SP";
322 case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
323 return "YCrCb_420_SP_ADRENO";
324 case HAL_PIXEL_FORMAT_YCrCb_422_SP:
325 return "YCrCb_422_SP";
326 case HAL_PIXEL_FORMAT_R_8:
327 return "R_8";
328 case HAL_PIXEL_FORMAT_RG_88:
329 return "RG_88";
330 case HAL_PIXEL_FORMAT_INTERLACE:
331 return "INTERLACE";
332 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
333 return "YCbCr_420_SP_VENUS";
334 case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
335 return "YCrCb_420_SP_VENUS";
336 case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
337 return "YCbCr_420_SP_VENUS_UBWC";
338 case HAL_PIXEL_FORMAT_RGBA_1010102:
339 return "RGBA_1010102";
340 case HAL_PIXEL_FORMAT_ARGB_2101010:
341 return "ARGB_2101010";
342 case HAL_PIXEL_FORMAT_RGBX_1010102:
343 return "RGBX_1010102";
344 case HAL_PIXEL_FORMAT_XRGB_2101010:
345 return "XRGB_2101010";
346 case HAL_PIXEL_FORMAT_BGRA_1010102:
347 return "BGRA_1010102";
348 case HAL_PIXEL_FORMAT_ABGR_2101010:
349 return "ABGR_2101010";
350 case HAL_PIXEL_FORMAT_BGRX_1010102:
351 return "BGRX_1010102";
352 case HAL_PIXEL_FORMAT_XBGR_2101010:
353 return "XBGR_2101010";
354 case HAL_PIXEL_FORMAT_YCbCr_420_P010:
355 return "YCbCr_420_P010";
356 case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
357 return "YCbCr_420_TP10_UBWC";
358 case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
359 return "YCbCr_420_P010_VENUS";
360 default:
361 return "Unknown_format";
362 }
363 }
364
365 }; //namespace qdutils
366