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