• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2012-2014, 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 #include <cutils/log.h>
30 #include <linux/msm_mdp.h>
31 #include "mdp_version.h"
32 
33 #define DEBUG 0
34 
35 ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion);
36 namespace qdutils {
37 
38 #define TOKEN_PARAMS_DELIM  "="
39 
40 #ifndef MDSS_MDP_HW_REV_100
41 #define MDSS_MDP_HW_REV_100 0x10000000 //8974 v1
42 #endif
43 #ifndef MDSS_MDP_HW_REV_101
44 #define MDSS_MDP_HW_REV_101 0x10010000 //8x26
45 #endif
46 #ifndef MDSS_MDP_HW_REV_102
47 #define MDSS_MDP_HW_REV_102 0x10020000 //8974 v2
48 #endif
49 #ifndef MDSS_MDP_HW_REV_103
50 #define MDSS_MDP_HW_REV_103 0x10030000 //8084
51 #endif
52 #ifndef MDSS_MDP_HW_REV_104
53 #define MDSS_MDP_HW_REV_104 0x10040000 //Next version
54 #endif
55 #ifndef MDSS_MDP_HW_REV_105
56 #define MDSS_MDP_HW_REV_105 0x10050000 //8994
57 #endif
58 #ifndef MDSS_MDP_HW_REV_106
59 #define MDSS_MDP_HW_REV_106 0x10060000 //8x16
60 #endif
61 #ifndef MDSS_MDP_HW_REV_107
62 #define MDSS_MDP_HW_REV_107 0x10070000 //Next version
63 #endif
64 #ifndef MDSS_MDP_HW_REV_108
65 #define MDSS_MDP_HW_REV_108 0x10080000 //8x39 & 8x36
66 #endif
67 #ifndef MDSS_MDP_HW_REV_109
68 #define MDSS_MDP_HW_REV_109 0x10090000 //Next version
69 #endif
70 #ifndef MDSS_MDP_HW_REV_200
71 #define MDSS_MDP_HW_REV_200 0x20000000 //8092
72 #endif
73 #ifndef MDSS_MDP_HW_REV_206
74 #define MDSS_MDP_HW_REV_206 0x20060000 //Future
75 #endif
76 
MDPVersion()77 MDPVersion::MDPVersion()
78 {
79     mMDPVersion = MDSS_V5;
80     mMdpRev = 0;
81     mRGBPipes = 0;
82     mVGPipes = 0;
83     mDMAPipes = 0;
84     mFeatures = 0;
85     mMDPUpscale = 0;
86     mMDPDownscale = 0;
87     mMacroTileEnabled = false;
88     mLowBw = 0;
89     mHighBw = 0;
90     mSourceSplit = false;
91     mSourceSplitAlways = false;
92     mRGBHasNoScalar = false;
93     mRotDownscale = false;
94 
95     updatePanelInfo();
96 
97     if(!updateSysFsInfo()) {
98         ALOGE("Unable to read display sysfs node");
99     }
100     if (mMdpRev == MDP_V3_0_4){
101         mMDPVersion = MDP_V3_0_4;
102     }
103 
104     mHasOverlay = false;
105     if((mMDPVersion >= MDP_V4_0) ||
106        (mMDPVersion == MDP_V_UNKNOWN) ||
107        (mMDPVersion == MDP_V3_0_4))
108         mHasOverlay = true;
109     if(!updateSplitInfo()) {
110         ALOGE("Unable to read display split node");
111     }
112 }
113 
~MDPVersion()114 MDPVersion::~MDPVersion() {
115     close(mFd);
116 }
117 
tokenizeParams(char * inputParams,const char * delim,char * tokenStr[],int * idx)118 int MDPVersion::tokenizeParams(char *inputParams, const char *delim,
119                                 char* tokenStr[], int *idx) {
120     char *tmp_token = NULL;
121     char *temp_ptr;
122     int index = 0;
123     if (!inputParams) {
124         return -1;
125     }
126     tmp_token = strtok_r(inputParams, delim, &temp_ptr);
127     while (tmp_token != NULL) {
128         tokenStr[index++] = tmp_token;
129         tmp_token = strtok_r(NULL, " ", &temp_ptr);
130     }
131     *idx = index;
132     return 0;
133 }
134 // This function reads the sysfs node to read the primary panel type
135 // and updates information accordingly
updatePanelInfo()136 void  MDPVersion::updatePanelInfo() {
137     FILE *displayDeviceFP = NULL;
138     FILE *panelInfoNodeFP = NULL;
139     const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
140     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
141     const char *strCmdPanel = "mipi dsi cmd panel";
142     const char *strVideoPanel = "mipi dsi video panel";
143     const char *strLVDSPanel = "lvds panel";
144     const char *strEDPPanel = "edp panel";
145 
146     displayDeviceFP = fopen("/sys/class/graphics/fb0/msm_fb_type", "r");
147     if(displayDeviceFP){
148         fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
149                 displayDeviceFP);
150         if(strncmp(fbType, strCmdPanel, strlen(strCmdPanel)) == 0) {
151             mPanelInfo.mType = MIPI_CMD_PANEL;
152         }
153         else if(strncmp(fbType, strVideoPanel, strlen(strVideoPanel)) == 0) {
154             mPanelInfo.mType = MIPI_VIDEO_PANEL;
155         }
156         else if(strncmp(fbType, strLVDSPanel, strlen(strLVDSPanel)) == 0) {
157             mPanelInfo.mType = LVDS_PANEL;
158         }
159         else if(strncmp(fbType, strEDPPanel, strlen(strEDPPanel)) == 0) {
160             mPanelInfo.mType = EDP_PANEL;
161         }
162         fclose(displayDeviceFP);
163     } else {
164         ALOGE("Unable to read Primary Panel Information");
165     }
166 
167     panelInfoNodeFP = fopen("/sys/class/graphics/fb0/msm_fb_panel_info", "r");
168     if(panelInfoNodeFP){
169         size_t len = PAGE_SIZE;
170         ssize_t read;
171         char *readLine = (char *) malloc (len);
172         while((read = getline((char **)&readLine, &len,
173                               panelInfoNodeFP)) != -1) {
174             int token_ct=0;
175             char *tokens[10];
176             memset(tokens, 0, sizeof(tokens));
177 
178             if(!tokenizeParams(readLine, TOKEN_PARAMS_DELIM, tokens,
179                                &token_ct)) {
180                 if(!strncmp(tokens[0], "pu_en", strlen("pu_en"))) {
181                     mPanelInfo.mPartialUpdateEnable = atoi(tokens[1]);
182                     ALOGI("PartialUpdate status: %s",
183                           mPanelInfo.mPartialUpdateEnable? "Enabled" :
184                           "Disabled");
185                 }
186                 if(!strncmp(tokens[0], "xstart", strlen("xstart"))) {
187                     mPanelInfo.mLeftAlign = atoi(tokens[1]);
188                     ALOGI("Left Align: %d", mPanelInfo.mLeftAlign);
189                 }
190                 if(!strncmp(tokens[0], "walign", strlen("walign"))) {
191                     mPanelInfo.mWidthAlign = atoi(tokens[1]);
192                     ALOGI("Width Align: %d", mPanelInfo.mWidthAlign);
193                 }
194                 if(!strncmp(tokens[0], "ystart", strlen("ystart"))) {
195                     mPanelInfo.mTopAlign = atoi(tokens[1]);
196                     ALOGI("Top Align: %d", mPanelInfo.mTopAlign);
197                 }
198                 if(!strncmp(tokens[0], "halign", strlen("halign"))) {
199                     mPanelInfo.mHeightAlign = atoi(tokens[1]);
200                     ALOGI("Height Align: %d", mPanelInfo.mHeightAlign);
201                 }
202                 if(!strncmp(tokens[0], "min_w", strlen("min_w"))) {
203                     mPanelInfo.mMinROIWidth = atoi(tokens[1]);
204                     ALOGI("Min ROI Width: %d", mPanelInfo.mMinROIWidth);
205                 }
206                 if(!strncmp(tokens[0], "min_h", strlen("min_h"))) {
207                     mPanelInfo.mMinROIHeight = atoi(tokens[1]);
208                     ALOGI("Min ROI Height: %d", mPanelInfo.mMinROIHeight);
209                 }
210                 if(!strncmp(tokens[0], "roi_merge", strlen("roi_merge"))) {
211                     mPanelInfo.mNeedsROIMerge = atoi(tokens[1]);
212                     ALOGI("Needs ROI Merge: %d", mPanelInfo.mNeedsROIMerge);
213                 }
214             }
215         }
216         fclose(panelInfoNodeFP);
217     } else {
218         ALOGE("Failed to open msm_fb_panel_info node");
219     }
220 }
221 
222 // This function reads the sysfs node to read MDP capabilities
223 // and parses and updates information accordingly.
updateSysFsInfo()224 bool MDPVersion::updateSysFsInfo() {
225     FILE *sysfsFd;
226     size_t len = PAGE_SIZE;
227     ssize_t read;
228     char *line = NULL;
229     char sysfsPath[255];
230     memset(sysfsPath, 0, sizeof(sysfsPath));
231     snprintf(sysfsPath , sizeof(sysfsPath),
232             "/sys/class/graphics/fb0/mdp/caps");
233     char property[PROPERTY_VALUE_MAX];
234     bool enableMacroTile = false;
235 
236     if((property_get("persist.hwc.macro_tile_enable", property, NULL) > 0) &&
237        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
238         (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
239         enableMacroTile = true;
240     }
241 
242     sysfsFd = fopen(sysfsPath, "rb");
243 
244     if (sysfsFd == NULL) {
245         ALOGE("%s: sysFsFile file '%s' not found",
246                 __FUNCTION__, sysfsPath);
247         return false;
248     } else {
249         line = (char *) malloc(len);
250         while((read = getline(&line, &len, sysfsFd)) != -1) {
251             int index=0;
252             char *tokens[10];
253             memset(tokens, 0, sizeof(tokens));
254 
255             // parse the line and update information accordingly
256             if(!tokenizeParams(line, TOKEN_PARAMS_DELIM, tokens, &index)) {
257                 if(!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
258                     mMdpRev = atoi(tokens[1]);
259                 }
260                 else if(!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
261                     mRGBPipes = (uint8_t)atoi(tokens[1]);
262                 }
263                 else if(!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
264                     mVGPipes = (uint8_t)atoi(tokens[1]);
265                 }
266                 else if(!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
267                     mDMAPipes = (uint8_t)atoi(tokens[1]);
268                 }
269                 else if(!strncmp(tokens[0], "max_downscale_ratio",
270                                 strlen("max_downscale_ratio"))) {
271                     mMDPDownscale = atoi(tokens[1]);
272                 }
273                 else if(!strncmp(tokens[0], "max_upscale_ratio",
274                                 strlen("max_upscale_ratio"))) {
275                     mMDPUpscale = atoi(tokens[1]);
276                 } else if(!strncmp(tokens[0], "max_bandwidth_low",
277                         strlen("max_bandwidth_low"))) {
278                     mLowBw = atol(tokens[1]);
279                 } else if(!strncmp(tokens[0], "max_bandwidth_high",
280                         strlen("max_bandwidth_high"))) {
281                     mHighBw = atol(tokens[1]);
282                 } else if(!strncmp(tokens[0], "features", strlen("features"))) {
283                     for(int i=1; i<index;i++) {
284                         if(!strncmp(tokens[i], "bwc", strlen("bwc"))) {
285                            mFeatures |= MDP_BWC_EN;
286                         } else if(!strncmp(tokens[i], "decimation",
287                                     strlen("decimation"))) {
288                            mFeatures |= MDP_DECIMATION_EN;
289                         } else if(!strncmp(tokens[i], "tile_format",
290                                     strlen("tile_format"))) {
291                            if(enableMacroTile)
292                                mMacroTileEnabled = true;
293                         } else if(!strncmp(tokens[i], "src_split",
294                                     strlen("src_split"))) {
295                             mSourceSplit = true;
296                         } else if(!strncmp(tokens[i], "non_scalar_rgb",
297                                     strlen("non_scalar_rgb"))) {
298                             mRGBHasNoScalar = true;
299                         } else if(!strncmp(tokens[i], "rotator_downscale",
300                                     strlen("rotator_downscale"))) {
301                             mRotDownscale = true;
302                         }
303                     }
304                 }
305             }
306         }
307         free(line);
308         fclose(sysfsFd);
309     }
310 
311     if(mSourceSplit) {
312         memset(sysfsPath, 0, sizeof(sysfsPath));
313         snprintf(sysfsPath , sizeof(sysfsPath),
314                 "/sys/class/graphics/fb0/msm_fb_src_split_info");
315 
316         sysfsFd = fopen(sysfsPath, "rb");
317         if (sysfsFd == NULL) {
318             ALOGE("%s: Opening file %s failed with error %s", __FUNCTION__,
319                     sysfsPath, strerror(errno));
320             return false;
321         } else {
322             line = (char *) malloc(len);
323             if((read = getline(&line, &len, sysfsFd)) != -1) {
324                 if(!strncmp(line, "src_split_always",
325                         strlen("src_split_always"))) {
326                     mSourceSplitAlways = true;
327                 }
328             }
329             free(line);
330             fclose(sysfsFd);
331         }
332     }
333 
334     ALOGD_IF(DEBUG, "%s: mMDPVersion: %d mMdpRev: %x mRGBPipes:%d,"
335                     "mVGPipes:%d", __FUNCTION__, mMDPVersion, mMdpRev,
336                     mRGBPipes, mVGPipes);
337     ALOGD_IF(DEBUG, "%s:mDMAPipes:%d \t mMDPDownscale:%d, mFeatures:%d",
338                      __FUNCTION__,  mDMAPipes, mMDPDownscale, mFeatures);
339     ALOGD_IF(DEBUG, "%s:mLowBw: %lu mHighBw: %lu", __FUNCTION__,  mLowBw,
340             mHighBw);
341 
342     return true;
343 }
344 
345 // This function reads the sysfs node to read MDP capabilities
346 // and parses and updates information accordingly.
updateSplitInfo()347 bool MDPVersion::updateSplitInfo() {
348     if(mMDPVersion >= MDSS_V5) {
349         char split[64] = {0};
350         FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
351         if(fp){
352             //Format "left right" space as delimiter
353             if(fread(split, sizeof(char), 64, fp)) {
354                 split[sizeof(split) - 1] = '\0';
355                 mSplit.mLeft = atoi(split);
356                 ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
357                 char *rght = strpbrk(split, " ");
358                 if(rght)
359                     mSplit.mRight = atoi(rght + 1);
360                 ALOGI_IF(mSplit.mRight, "Right Split=%d", mSplit.mRight);
361             }
362         } else {
363             ALOGE("Failed to open mdss_fb_split node");
364             return false;
365         }
366         if(fp)
367             fclose(fp);
368     }
369     return true;
370 }
371 
372 
supportsDecimation()373 bool MDPVersion::supportsDecimation() {
374     return mFeatures & MDP_DECIMATION_EN;
375 }
376 
getMaxMDPDownscale()377 uint32_t MDPVersion::getMaxMDPDownscale() {
378     return mMDPDownscale;
379 }
380 
getMaxMDPUpscale()381 uint32_t MDPVersion::getMaxMDPUpscale() {
382     return mMDPUpscale;
383 }
384 
supportsBWC()385 bool MDPVersion::supportsBWC() {
386     // BWC - Bandwidth Compression
387     return (mFeatures & MDP_BWC_EN);
388 }
389 
supportsMacroTile()390 bool MDPVersion::supportsMacroTile() {
391     // MACRO TILE support
392     return mMacroTileEnabled;
393 }
394 
isSrcSplit() const395 bool MDPVersion::isSrcSplit() const {
396     return mSourceSplit;
397 }
398 
isSrcSplitAlways() const399 bool MDPVersion::isSrcSplitAlways() const {
400     return mSourceSplitAlways;
401 }
402 
isRGBScalarSupported() const403 bool MDPVersion::isRGBScalarSupported() const {
404     return (!mRGBHasNoScalar);
405 }
406 
is8x26()407 bool MDPVersion::is8x26() {
408     return (mMdpRev >= MDSS_MDP_HW_REV_101 and
409             mMdpRev < MDSS_MDP_HW_REV_102);
410 }
411 
is8x74v2()412 bool MDPVersion::is8x74v2() {
413     return (mMdpRev >= MDSS_MDP_HW_REV_102 and
414             mMdpRev < MDSS_MDP_HW_REV_103);
415 }
416 
is8084()417 bool MDPVersion::is8084() {
418     return (mMdpRev >= MDSS_MDP_HW_REV_103 and
419             mMdpRev < MDSS_MDP_HW_REV_104);
420 }
421 
is8092()422 bool MDPVersion::is8092() {
423     return (mMdpRev >= MDSS_MDP_HW_REV_200 and
424             mMdpRev < MDSS_MDP_HW_REV_206);
425 }
426 
is8994()427 bool MDPVersion::is8994() {
428     return (mMdpRev >= MDSS_MDP_HW_REV_105 and
429             mMdpRev < MDSS_MDP_HW_REV_106);
430 }
431 
is8x16()432 bool MDPVersion::is8x16() {
433     return (mMdpRev >= MDSS_MDP_HW_REV_106 and
434             mMdpRev < MDSS_MDP_HW_REV_107);
435 }
436 
is8x39()437 bool MDPVersion::is8x39() {
438     return (mMdpRev >= MDSS_MDP_HW_REV_108 and
439             mMdpRev < MDSS_MDP_HW_REV_109);
440 }
441 
442 
443 }; //namespace qdutils
444 
445