• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are permitted
5 * provided that the following conditions are met:
6 *    * Redistributions of source code must retain the above copyright notice, this list of
7 *      conditions and the following disclaimer.
8 *    * Redistributions in binary form must reproduce the above copyright notice, this list of
9 *      conditions and the following disclaimer in the documentation and/or other materials provided
10 *      with the distribution.
11 *    * Neither the name of The Linux Foundation nor the names of its contributors may be used to
12 *      endorse or promote products derived from this software without specific prior written
13 *      permission.
14 *
15 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
21 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24 
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <utils/constants.h>
32 #include <utils/debug.h>
33 #include <utils/sys.h>
34 
35 #include <algorithm>
36 #include <iostream>
37 #include <fstream>
38 #include <map>
39 #include <memory>
40 #include <string>
41 #include <utility>
42 #include <vector>
43 
44 #include "hw_info.h"
45 
46 #define __CLASS__ "HWInfo"
47 
48 using std::vector;
49 using std::map;
50 using std::string;
51 using std::ifstream;
52 using std::to_string;
53 
54 namespace sdm {
55 
56 // kDefaultFormatSupport contains the bit map of supported formats for each hw blocks.
57 // For eg: if Cursor supports MDP_RGBA_8888[bit-13] and MDP_RGB_565[bit-0], then cursor pipe array
58 // contains { 0x01[0-3], 0x00[4-7], 0x00[8-12], 0x01[13-16], 0x00[17-20], 0x00[21-24], 0x00[24-28] }
59 const uint8_t HWInfo::kDefaultFormatSupport[kHWSubBlockMax][BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)] = {
60   { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWVIGPipe
61   { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 },  // kHWRGBPipe
62   { 0x33, 0xE0, 0x00, 0x16, 0x00, 0xBF, 0x00, 0x00, 0xFE, 0x07 },  // kHWDMAPipe
63   { 0x12, 0x60, 0x0C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00 },  // kHWCursorPipe
64   { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWRotatorInput
65   { 0xFF, 0xF5, 0x1C, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xFE, 0x1F },  // kHWRotatorOutput
66   { 0x3F, 0xF4, 0x10, 0x1E, 0x20, 0xFF, 0x01, 0x00, 0xAA, 0x16 },  // kHWWBIntfOutput
67 };
68 
ParseString(char * input,char * tokens[],const uint32_t max_token,const char * delim,uint32_t * count)69 int HWInfo::ParseString(char *input, char *tokens[], const uint32_t max_token, const char *delim,
70                         uint32_t *count) {
71   char *tmp_token = NULL;
72   char *temp_ptr;
73   uint32_t index = 0;
74   if (!input) {
75     return -1;
76   }
77   tmp_token = strtok_r(input, delim, &temp_ptr);
78   while (tmp_token && index < max_token) {
79     tokens[index++] = tmp_token;
80     tmp_token = strtok_r(NULL, delim, &temp_ptr);
81   }
82   *count = index;
83 
84   return 0;
85 }
86 
Create(HWInfoInterface ** intf)87 DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
88   DisplayError error = kErrorNone;
89   HWInfo *hw_info = NULL;
90 
91   hw_info = new HWInfo();
92   if (!hw_info) {
93     error = kErrorMemory;
94   } else {
95     *intf = hw_info;
96   }
97 
98   return error;
99 }
100 
Destroy(HWInfoInterface * intf)101 DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
102   HWInfo *hw_info = static_cast<HWInfo *>(intf);
103   delete hw_info;
104 
105   return kErrorNone;
106 }
107 
GetDynamicBWLimits(HWResourceInfo * hw_resource)108 DisplayError HWInfo::GetDynamicBWLimits(HWResourceInfo *hw_resource) {
109   const char *bw_info_node = "/sys/devices/virtual/graphics/fb0/mdp/bw_mode_bitmap";
110   FILE *fileptr = NULL;
111   uint32_t token_count = 0;
112   const uint32_t max_count = kBwModeMax;
113   char *tokens[max_count] = { NULL };
114   fileptr = Sys::fopen_(bw_info_node, "r");
115 
116   if (!fileptr) {
117     DLOGE("File '%s' not found", bw_info_node);
118     return kErrorHardware;
119   }
120 
121   HWDynBwLimitInfo* bw_info = &hw_resource->dyn_bw_info;
122   for (int index = 0; index < kBwModeMax; index++) {
123     bw_info->total_bw_limit[index] = UINT32(hw_resource->max_bandwidth_low);
124     bw_info->pipe_bw_limit[index] = hw_resource->max_pipe_bw;
125   }
126 
127   char *stringbuffer = reinterpret_cast<char *>(malloc(kMaxStringLength));
128   if (stringbuffer == NULL) {
129     DLOGE("Failed to allocate stringbuffer");
130     return kErrorMemory;
131   }
132 
133   size_t len = kMaxStringLength;
134   ssize_t read;
135   char *line = stringbuffer;
136   while ((read = Sys::getline_(&line, &len, fileptr)) != -1) {
137     if (!ParseString(line, tokens, max_count, ":, =\n", &token_count)) {
138       if (!strncmp(tokens[0], "default_pipe", strlen("default_pipe"))) {
139         bw_info->pipe_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
140       } else if (!strncmp(tokens[0], "camera_pipe", strlen("camera_pipe"))) {
141         bw_info->pipe_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
142       } else if (!strncmp(tokens[0], "vflip_pipe", strlen("vflip_pipe"))) {
143         bw_info->pipe_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
144       } else if (!strncmp(tokens[0], "hflip_pipe", strlen("hflip_pipe"))) {
145         bw_info->pipe_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
146       } else if (!strncmp(tokens[0], "default", strlen("default"))) {
147         bw_info->total_bw_limit[kBwDefault] = UINT32(atoi(tokens[1]));
148       } else if (!strncmp(tokens[0], "camera", strlen("camera"))) {
149         bw_info->total_bw_limit[kBwCamera] = UINT32(atoi(tokens[1]));
150       } else if (!strncmp(tokens[0], "vflip", strlen("vflip"))) {
151         bw_info->total_bw_limit[kBwVFlip] = UINT32(atoi(tokens[1]));
152       } else if (!strncmp(tokens[0], "hflip", strlen("hflip"))) {
153         bw_info->total_bw_limit[kBwHFlip] = UINT32(atoi(tokens[1]));
154       }
155     }
156   }
157   free(stringbuffer);
158   Sys::fclose_(fileptr);
159 
160   return kErrorNone;
161 }
162 
GetHWResourceInfo(HWResourceInfo * hw_resource)163 DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
164   if (!hw_resource) {
165     DLOGE("HWResourceInfo pointer in invalid.");
166     return kErrorParameters;
167   }
168   const char *fb_path = "/sys/devices/virtual/graphics/fb";
169   FILE *fileptr = NULL;
170   uint32_t token_count = 0;
171   const uint32_t max_count = 256;
172   char *tokens[max_count] = { NULL };
173   char *stringbuffer = reinterpret_cast<char *>(malloc(kMaxStringLength));
174 
175   if (stringbuffer == NULL) {
176     DLOGE("Failed to allocate stringbuffer");
177     return kErrorMemory;
178   }
179 
180   snprintf(stringbuffer , kMaxStringLength, "%s%d/mdp/caps", fb_path, kHWCapabilitiesNode);
181   fileptr = Sys::fopen_(stringbuffer, "r");
182 
183   if (!fileptr) {
184     DLOGE("File '%s' not found", stringbuffer);
185     free(stringbuffer);
186     return kErrorHardware;
187   }
188 
189   InitSupportedFormatMap(hw_resource);
190 
191   size_t len = kMaxStringLength;
192   ssize_t read;
193   char *line = stringbuffer;
194   hw_resource->hw_version = kHWMdssVersion5;
195   while ((read = Sys::getline_(&line, &len, fileptr)) != -1) {
196     // parse the line and update information accordingly
197     if (!ParseString(line, tokens, max_count, ":, =\n", &token_count)) {
198       if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
199         hw_resource->hw_revision = UINT32(atoi(tokens[1]));  // HW Rev, v1/v2
200       } else if (!strncmp(tokens[0], "rot_input_fmts", strlen("rot_input_fmts"))) {
201         ParseFormats(&tokens[1], (token_count - 1), kHWRotatorInput, hw_resource);
202       } else if (!strncmp(tokens[0], "rot_output_fmts", strlen("rot_output_fmts"))) {
203         ParseFormats(&tokens[1], (token_count - 1), kHWRotatorOutput, hw_resource);
204       } else if (!strncmp(tokens[0], "wb_output_fmts", strlen("wb_output_fmts"))) {
205         ParseFormats(&tokens[1], (token_count - 1), kHWWBIntfOutput, hw_resource);
206       } else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
207         hw_resource->num_blending_stages = UINT8(atoi(tokens[1]));
208       } else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
209         hw_resource->max_scale_down = UINT32(atoi(tokens[1]));
210       } else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
211         hw_resource->max_scale_up = UINT32(atoi(tokens[1]));
212       } else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
213         hw_resource->max_bandwidth_low = UINT64(atol(tokens[1]));
214       } else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
215         hw_resource->max_bandwidth_high = UINT64(atol(tokens[1]));
216       } else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
217         hw_resource->max_mixer_width = UINT32(atoi(tokens[1]));
218       } else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
219         hw_resource->max_pipe_width = UINT32(atoi(tokens[1]));
220       } else if (!strncmp(tokens[0], "max_cursor_size", strlen("max_cursor_size"))) {
221         hw_resource->max_cursor_size = UINT32(atoi(tokens[1]));
222       } else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
223         hw_resource->max_pipe_bw = UINT32(atoi(tokens[1]));
224       } else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
225         hw_resource->max_sde_clk = UINT32(atoi(tokens[1]));
226       } else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
227         hw_resource->clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
228       } else if (!strncmp(tokens[0], "fmt_mt_nv12_factor", strlen("fmt_mt_nv12_factor"))) {
229         hw_resource->macrotile_nv12_factor = UINT32(atoi(tokens[1]));
230       } else if (!strncmp(tokens[0], "fmt_mt_factor", strlen("fmt_mt_factor"))) {
231         hw_resource->macrotile_factor = UINT32(atoi(tokens[1]));
232       } else if (!strncmp(tokens[0], "fmt_linear_factor", strlen("fmt_linear_factor"))) {
233         hw_resource->linear_factor = UINT32(atoi(tokens[1]));
234       } else if (!strncmp(tokens[0], "scale_factor", strlen("scale_factor"))) {
235         hw_resource->scale_factor = UINT32(atoi(tokens[1]));
236       } else if (!strncmp(tokens[0], "xtra_ff_factor", strlen("xtra_ff_factor"))) {
237         hw_resource->extra_fudge_factor = UINT32(atoi(tokens[1]));
238       } else if (!strncmp(tokens[0], "features", strlen("features"))) {
239         for (uint32_t i = 0; i < token_count; i++) {
240           if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
241             hw_resource->has_bwc = true;
242           } else if (!strncmp(tokens[i], "ubwc", strlen("ubwc"))) {
243             hw_resource->has_ubwc = true;
244           } else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
245             hw_resource->has_decimation = true;
246           } else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
247             hw_resource->has_macrotile = true;
248           } else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
249             hw_resource->is_src_split = true;
250           } else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
251             hw_resource->has_non_scalar_rgb = true;
252           } else if (!strncmp(tokens[i], "perf_calc", strlen("perf_calc"))) {
253             hw_resource->perf_calc = true;
254           } else if (!strncmp(tokens[i], "dynamic_bw_limit", strlen("dynamic_bw_limit"))) {
255             hw_resource->has_dyn_bw_support = true;
256           } else if (!strncmp(tokens[i], "separate_rotator", strlen("separate_rotator"))) {
257             hw_resource->separate_rotator = true;
258           }
259         }
260       } else if (!strncmp(tokens[0], "pipe_count", strlen("pipe_count"))) {
261         uint32_t pipe_count = UINT8(atoi(tokens[1]));
262         for (uint32_t i = 0; i < pipe_count; i++) {
263           read = Sys::getline_(&line, &len, fileptr);
264           if (!ParseString(line, tokens, max_count, ": =\n", &token_count)) {
265             HWPipeCaps pipe_caps;
266             pipe_caps.type = kPipeTypeUnused;
267             for (uint32_t j = 0; j < token_count; j += 2) {
268               if (!strncmp(tokens[j], "pipe_type", strlen("pipe_type"))) {
269                 if (!strncmp(tokens[j+1], "vig", strlen("vig"))) {
270                   pipe_caps.type = kPipeTypeVIG;
271                   hw_resource->num_vig_pipe++;
272                 } else if (!strncmp(tokens[j+1], "rgb", strlen("rgb"))) {
273                   pipe_caps.type = kPipeTypeRGB;
274                   hw_resource->num_rgb_pipe++;
275                 } else if (!strncmp(tokens[j+1], "dma", strlen("dma"))) {
276                   pipe_caps.type = kPipeTypeDMA;
277                   hw_resource->num_dma_pipe++;
278                 } else if (!strncmp(tokens[j+1], "cursor", strlen("cursor"))) {
279                   pipe_caps.type = kPipeTypeCursor;
280                   hw_resource->num_cursor_pipe++;
281                 }
282               } else if (!strncmp(tokens[j], "pipe_ndx", strlen("pipe_ndx"))) {
283                 pipe_caps.id = UINT32(atoi(tokens[j+1]));
284               } else if (!strncmp(tokens[j], "rects", strlen("rects"))) {
285                 pipe_caps.max_rects = UINT32(atoi(tokens[j+1]));
286               } else if (!strncmp(tokens[j], "fmts_supported", strlen("fmts_supported"))) {
287                 char *tokens_fmt[max_count] = { NULL };
288                 uint32_t token_fmt_count = 0;
289                 if (!ParseString(tokens[j+1], tokens_fmt, max_count, ",\n", &token_fmt_count)) {
290                   if (pipe_caps.type == kPipeTypeVIG) {
291                     ParseFormats(tokens_fmt, token_fmt_count, kHWVIGPipe, hw_resource);
292                   } else if (pipe_caps.type == kPipeTypeRGB) {
293                     ParseFormats(tokens_fmt, token_fmt_count, kHWRGBPipe, hw_resource);
294                   } else if (pipe_caps.type == kPipeTypeDMA) {
295                     ParseFormats(tokens_fmt, token_fmt_count, kHWDMAPipe, hw_resource);
296                   } else if (pipe_caps.type == kPipeTypeCursor) {
297                     ParseFormats(tokens_fmt, token_fmt_count, kHWCursorPipe, hw_resource);
298                   }
299                 }
300               }
301             }
302             hw_resource->hw_pipes.push_back(pipe_caps);
303           }
304         }
305       }
306     }
307   }
308 
309   Sys::fclose_(fileptr);
310 
311   DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
312         hw_resource->hw_version, hw_resource->hw_revision, hw_resource->num_rgb_pipe,
313         hw_resource->num_vig_pipe, hw_resource->num_dma_pipe, hw_resource->num_cursor_pipe);
314   DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource->max_scale_up,
315         hw_resource->max_scale_down, hw_resource->num_blending_stages);
316   DLOGI("BWC = %d, UBWC = %d, Decimation = %d, Tile Format = %d", hw_resource->has_bwc,
317         hw_resource->has_ubwc, hw_resource->has_decimation, hw_resource->has_macrotile);
318   DLOGI("SourceSplit = %d", hw_resource->is_src_split);
319   DLOGI("MaxLowBw = %" PRIu64 " , MaxHighBw = % " PRIu64 "", hw_resource->max_bandwidth_low,
320         hw_resource->max_bandwidth_high);
321   DLOGI("MaxPipeBw = %" PRIu64 " KBps, MaxSDEClock = % " PRIu64 " Hz, ClockFudgeFactor = %f",
322         hw_resource->max_pipe_bw, hw_resource->max_sde_clk, hw_resource->clk_fudge_factor);
323   DLOGI("Prefill factors: Tiled_NV12 = %d, Tiled = %d, Linear = %d, Scale = %d, Fudge_factor = %d",
324         hw_resource->macrotile_nv12_factor, hw_resource->macrotile_factor,
325         hw_resource->linear_factor, hw_resource->scale_factor, hw_resource->extra_fudge_factor);
326 
327   if (hw_resource->separate_rotator || hw_resource->num_dma_pipe) {
328     GetHWRotatorInfo(hw_resource);
329   }
330 
331   if (hw_resource->has_dyn_bw_support) {
332     DisplayError ret = GetDynamicBWLimits(hw_resource);
333     if (ret != kErrorNone) {
334       DLOGE("Failed to read dynamic band width info");
335       return ret;
336     }
337 
338     DLOGI("Has Support for multiple bw limits shown below");
339     for (int index = 0; index < kBwModeMax; index++) {
340       DLOGI("Mode-index=%d  total_bw_limit=%d and pipe_bw_limit=%d",
341             index, hw_resource->dyn_bw_info.total_bw_limit[index],
342             hw_resource->dyn_bw_info.pipe_bw_limit[index]);
343     }
344   }
345 
346   return kErrorNone;
347 }
348 
GetHWRotatorInfo(HWResourceInfo * hw_resource)349 DisplayError HWInfo::GetHWRotatorInfo(HWResourceInfo *hw_resource) {
350   if (GetMDSSRotatorInfo(hw_resource) != kErrorNone)
351     return GetV4L2RotatorInfo(hw_resource);
352 
353   return kErrorNone;
354 }
355 
GetMDSSRotatorInfo(HWResourceInfo * hw_resource)356 DisplayError HWInfo::GetMDSSRotatorInfo(HWResourceInfo *hw_resource) {
357   FILE *fileptr = NULL;
358   char *stringbuffer = reinterpret_cast<char *>(malloc(sizeof(char) * kMaxStringLength));
359   uint32_t token_count = 0;
360   const uint32_t max_count = 10;
361   char *tokens[max_count] = { NULL };
362   size_t len = kMaxStringLength;
363   ssize_t read = 0;
364 
365   snprintf(stringbuffer, sizeof(char) * kMaxStringLength, "%s", kRotatorCapsPath);
366   fileptr = Sys::fopen_(stringbuffer, "r");
367 
368   if (!fileptr) {
369     DLOGW("File '%s' not found", stringbuffer);
370     free(stringbuffer);
371     return kErrorNotSupported;
372   }
373 
374   hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_MDSS;
375   while ((read = Sys::getline_(&stringbuffer, &len, fileptr)) != -1) {
376     if (!ParseString(stringbuffer, tokens, max_count, ":, =\n", &token_count)) {
377       if (!strncmp(tokens[0], "wb_count", strlen("wb_count"))) {
378         hw_resource->hw_rot_info.num_rotator = UINT8(atoi(tokens[1]));
379         hw_resource->hw_rot_info.device_path = "/dev/mdss_rotator";
380       } else if (!strncmp(tokens[0], "downscale", strlen("downscale"))) {
381         hw_resource->hw_rot_info.has_downscale = UINT8(atoi(tokens[1]));
382       }
383     }
384   }
385 
386   Sys::fclose_(fileptr);
387   free(stringbuffer);
388 
389   DLOGI("MDSS Rotator: Count = %d, Downscale = %d", hw_resource->hw_rot_info.num_rotator,
390         hw_resource->hw_rot_info.has_downscale);
391 
392   return kErrorNone;
393 }
394 
GetV4L2RotatorInfo(HWResourceInfo * hw_resource)395 DisplayError HWInfo::GetV4L2RotatorInfo(HWResourceInfo *hw_resource) {
396   const uint32_t kMaxV4L2Nodes = 64;
397   size_t len = kMaxStringLength;
398   char *line = reinterpret_cast<char *>(malloc(sizeof(char) * len));
399   bool found = false;
400 
401   for (uint32_t i = 0; (i < kMaxV4L2Nodes) && (false == found); i++) {
402     string path = "/sys/class/video4linux/video" + to_string(i) + "/name";
403     FILE *fileptr = Sys::fopen_(path.c_str(), "r");
404     if (fileptr) {
405       if ((Sys::getline_(&line, &len, fileptr) != -1) &&
406           (!strncmp(line, "sde_rotator", strlen("sde_rotator")))) {
407          hw_resource->hw_rot_info.device_path = string("/dev/video" + to_string(i));
408          hw_resource->hw_rot_info.num_rotator++;
409          hw_resource->hw_rot_info.type = HWRotatorInfo::ROT_TYPE_V4L2;
410          hw_resource->hw_rot_info.has_downscale = true;
411          // We support only 1 rotator
412          found = true;
413       }
414       Sys::fclose_(fileptr);
415     }
416   }
417 
418   free(line);
419   DLOGI("V4L2 Rotator: Count = %d, Downscale = %d", hw_resource->hw_rot_info.num_rotator,
420         hw_resource->hw_rot_info.has_downscale);
421 
422   return kErrorNone;
423 }
424 
GetSDMFormat(int mdp_format)425 LayerBufferFormat HWInfo::GetSDMFormat(int mdp_format) {
426   switch (mdp_format) {
427   case MDP_ARGB_8888:              return kFormatARGB8888;
428   case MDP_RGBA_8888:              return kFormatRGBA8888;
429   case MDP_BGRA_8888:              return kFormatBGRA8888;
430   case MDP_XRGB_8888:              return kFormatXRGB8888;
431   case MDP_RGBX_8888:              return kFormatRGBX8888;
432   case MDP_BGRX_8888:              return kFormatBGRX8888;
433   case MDP_RGBA_5551:              return kFormatRGBA5551;
434   case MDP_RGBA_4444:              return kFormatRGBA4444;
435   case MDP_RGB_888:                return kFormatRGB888;
436   case MDP_BGR_888:                return kFormatBGR888;
437   case MDP_RGB_565:                return kFormatRGB565;
438   case MDP_BGR_565:                return kFormatBGR565;
439   case MDP_RGBA_8888_UBWC:         return kFormatRGBA8888Ubwc;
440   case MDP_RGBX_8888_UBWC:         return kFormatRGBX8888Ubwc;
441   case MDP_RGB_565_UBWC:           return kFormatBGR565Ubwc;
442   case MDP_Y_CB_CR_H2V2:           return kFormatYCbCr420Planar;
443   case MDP_Y_CR_CB_H2V2:           return kFormatYCrCb420Planar;
444   case MDP_Y_CR_CB_GH2V2:          return kFormatYCrCb420PlanarStride16;
445   case MDP_Y_CBCR_H2V2:            return kFormatYCbCr420SemiPlanar;
446   case MDP_Y_CRCB_H2V2:            return kFormatYCrCb420SemiPlanar;
447   case MDP_Y_CBCR_H2V2_VENUS:      return kFormatYCbCr420SemiPlanarVenus;
448   case MDP_Y_CBCR_H1V2:            return kFormatYCbCr422H1V2SemiPlanar;
449   case MDP_Y_CRCB_H1V2:            return kFormatYCrCb422H1V2SemiPlanar;
450   case MDP_Y_CBCR_H2V1:            return kFormatYCbCr422H2V1SemiPlanar;
451   case MDP_Y_CRCB_H2V1:            return kFormatYCrCb422H2V1SemiPlanar;
452   case MDP_Y_CBCR_H2V2_UBWC:       return kFormatYCbCr420SPVenusUbwc;
453   case MDP_Y_CRCB_H2V2_VENUS:      return kFormatYCrCb420SemiPlanarVenus;
454   case MDP_YCBYCR_H2V1:            return kFormatYCbCr422H2V1Packed;
455   case MDP_RGBA_1010102:           return kFormatRGBA1010102;
456   case MDP_ARGB_2101010:           return kFormatARGB2101010;
457   case MDP_RGBX_1010102:           return kFormatRGBX1010102;
458   case MDP_XRGB_2101010:           return kFormatXRGB2101010;
459   case MDP_BGRA_1010102:           return kFormatBGRA1010102;
460   case MDP_ABGR_2101010:           return kFormatABGR2101010;
461   case MDP_BGRX_1010102:           return kFormatBGRX1010102;
462   case MDP_XBGR_2101010:           return kFormatXBGR2101010;
463   case MDP_RGBA_1010102_UBWC:      return kFormatRGBA1010102Ubwc;
464   case MDP_RGBX_1010102_UBWC:      return kFormatRGBX1010102Ubwc;
465   case MDP_Y_CBCR_H2V2_P010:       return kFormatYCbCr420P010;
466   case MDP_Y_CBCR_H2V2_TP10_UBWC:  return kFormatYCbCr420TP10Ubwc;
467   default:                         return kFormatInvalid;
468   }
469 }
470 
InitSupportedFormatMap(HWResourceInfo * hw_resource)471 void HWInfo::InitSupportedFormatMap(HWResourceInfo *hw_resource) {
472   hw_resource->supported_formats_map.clear();
473 
474   for (int sub_blk_type = INT(kHWVIGPipe); sub_blk_type < INT(kHWSubBlockMax); sub_blk_type++) {
475     PopulateSupportedFormatMap(kDefaultFormatSupport[sub_blk_type], MDP_IMGTYPE_LIMIT1,
476                                (HWSubBlockType)sub_blk_type, hw_resource);
477   }
478 }
479 
ParseFormats(char * tokens[],uint32_t token_count,HWSubBlockType sub_blk_type,HWResourceInfo * hw_resource)480 void HWInfo::ParseFormats(char *tokens[], uint32_t token_count, HWSubBlockType sub_blk_type,
481                           HWResourceInfo *hw_resource) {
482   if (token_count > BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1)) {
483     return;
484   }
485 
486   std::unique_ptr<uint8_t[]> format_supported(new uint8_t[token_count]);
487   for (uint32_t i = 0; i < token_count; i++) {
488     format_supported[i] = UINT8(atoi(tokens[i]));
489   }
490 
491   PopulateSupportedFormatMap(format_supported.get(), (token_count << 3), sub_blk_type, hw_resource);
492 }
493 
PopulateSupportedFormatMap(const uint8_t * format_supported,uint32_t format_count,HWSubBlockType sub_blk_type,HWResourceInfo * hw_resource)494 void HWInfo::PopulateSupportedFormatMap(const uint8_t *format_supported, uint32_t format_count,
495                                         HWSubBlockType sub_blk_type, HWResourceInfo *hw_resource) {
496   vector <LayerBufferFormat> supported_sdm_formats;
497   for (uint32_t mdp_format = 0; mdp_format < format_count; mdp_format++) {
498     if (IS_BIT_SET(format_supported[mdp_format >> 3], (mdp_format & 7))) {
499       LayerBufferFormat sdm_format = GetSDMFormat(INT(mdp_format));
500       if (sdm_format != kFormatInvalid) {
501         supported_sdm_formats.push_back(sdm_format);
502       }
503     }
504   }
505 
506   hw_resource->supported_formats_map.erase(sub_blk_type);
507   hw_resource->supported_formats_map.insert(make_pair(sub_blk_type, supported_sdm_formats));
508 }
509 
510 }  // namespace sdm
511 
512