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