blob: b998a46b6e72ae6fafbf8e57aadfc0fe16e378f6 [file] [log] [blame]
/*
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "hw_info.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <utils/constants.h>
#include <utils/debug.h>
#define __CLASS__ "HWInfo"
namespace sdm {
int HWInfo::ParseLine(char *input, char *tokens[], const uint32_t max_token, uint32_t *count) {
char *tmp_token = NULL;
char *temp_ptr;
uint32_t index = 0;
const char *delim = ", =\n";
if (!input) {
return -1;
}
tmp_token = strtok_r(input, delim, &temp_ptr);
while (tmp_token && index < max_token) {
tokens[index++] = tmp_token;
tmp_token = strtok_r(NULL, delim, &temp_ptr);
}
*count = index;
return 0;
}
DisplayError HWInfoInterface::Create(HWInfoInterface **intf) {
DisplayError error = kErrorNone;
HWInfo *hw_info = NULL;
hw_info = new HWInfo();
if (!hw_info) {
error = kErrorMemory;
} else {
*intf = hw_info;
}
return error;
}
DisplayError HWInfoInterface::Destroy(HWInfoInterface *intf) {
HWInfo *hw_info = static_cast<HWInfo *>(intf);
delete hw_info;
return kErrorNone;
}
DisplayError HWInfo::GetHWResourceInfo(HWResourceInfo *hw_resource) {
if (!hw_resource) {
DLOGE("HWResourceInfo pointer in invalid.");
return kErrorParameters;
}
const char *kHWCapabilitiesPath = "/sys/devices/virtual/graphics/fb";
FILE *fileptr = NULL;
char stringbuffer[kMaxStringLength];
uint32_t token_count = 0;
const uint32_t max_count = 10;
char *tokens[max_count] = { NULL };
snprintf(stringbuffer , sizeof(stringbuffer), "%s%d/mdp/caps",
kHWCapabilitiesPath, kHWCapabilitiesNode);
fileptr = fopen(stringbuffer, "rb");
if (!fileptr) {
DLOGE("File '%s' not found", stringbuffer);
return kErrorHardware;
}
size_t len = kMaxStringLength;
ssize_t read;
char *line = stringbuffer;
hw_resource->hw_version = kHWMdssVersion5;
while ((read = getline(&line, &len, fileptr)) != -1) {
// parse the line and update information accordingly
if (!ParseLine(line, tokens, max_count, &token_count)) {
if (!strncmp(tokens[0], "hw_rev", strlen("hw_rev"))) {
hw_resource->hw_revision = atoi(tokens[1]); // HW Rev, v1/v2
} else if (!strncmp(tokens[0], "rgb_pipes", strlen("rgb_pipes"))) {
hw_resource->num_rgb_pipe = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "vig_pipes", strlen("vig_pipes"))) {
hw_resource->num_vig_pipe = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "dma_pipes", strlen("dma_pipes"))) {
hw_resource->num_dma_pipe = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "cursor_pipes", strlen("cursor_pipes"))) {
hw_resource->num_cursor_pipe = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "blending_stages", strlen("blending_stages"))) {
hw_resource->num_blending_stages = UINT8(atoi(tokens[1]));
} else if (!strncmp(tokens[0], "max_downscale_ratio", strlen("max_downscale_ratio"))) {
hw_resource->max_scale_down = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_upscale_ratio", strlen("max_upscale_ratio"))) {
hw_resource->max_scale_up = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_bandwidth_low", strlen("max_bandwidth_low"))) {
hw_resource->max_bandwidth_low = atol(tokens[1]);
} else if (!strncmp(tokens[0], "max_bandwidth_high", strlen("max_bandwidth_high"))) {
hw_resource->max_bandwidth_high = atol(tokens[1]);
} else if (!strncmp(tokens[0], "max_mixer_width", strlen("max_mixer_width"))) {
hw_resource->max_mixer_width = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_pipe_width", strlen("max_pipe_width"))) {
hw_resource->max_pipe_width = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_pipe_bw", strlen("max_pipe_bw"))) {
hw_resource->max_pipe_bw = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "max_mdp_clk", strlen("max_mdp_clk"))) {
hw_resource->max_sde_clk = atoi(tokens[1]);
} else if (!strncmp(tokens[0], "clk_fudge_factor", strlen("clk_fudge_factor"))) {
hw_resource->clk_fudge_factor = FLOAT(atoi(tokens[1])) / FLOAT(atoi(tokens[2]));
} else if (!strncmp(tokens[0], "features", strlen("features"))) {
for (uint32_t i = 0; i < token_count; i++) {
if (!strncmp(tokens[i], "bwc", strlen("bwc"))) {
hw_resource->has_bwc = true;
} else if (!strncmp(tokens[i], "decimation", strlen("decimation"))) {
hw_resource->has_decimation = true;
} else if (!strncmp(tokens[i], "tile_format", strlen("tile_format"))) {
hw_resource->has_macrotile = true;
} else if (!strncmp(tokens[i], "src_split", strlen("src_split"))) {
hw_resource->is_src_split = true;
} else if (!strncmp(tokens[i], "non_scalar_rgb", strlen("non_scalar_rgb"))) {
hw_resource->has_non_scalar_rgb = true;
} else if (!strncmp(tokens[i], "rotator_downscale", strlen("rotator_downscale"))) {
hw_resource->has_rotator_downscale = true;
}
}
}
}
}
fclose(fileptr);
DLOGI("SDE Version = %d, SDE Revision = %x, RGB = %d, VIG = %d, DMA = %d, Cursor = %d",
hw_resource->hw_version, hw_resource->hw_revision, hw_resource->num_rgb_pipe,
hw_resource->num_vig_pipe, hw_resource->num_dma_pipe, hw_resource->num_cursor_pipe);
DLOGI("Upscale Ratio = %d, Downscale Ratio = %d, Blending Stages = %d", hw_resource->max_scale_up,
hw_resource->max_scale_down, hw_resource->num_blending_stages);
DLOGI("BWC = %d, Decimation = %d, Tile Format = %d, Rotator Downscale = %d", hw_resource->has_bwc,
hw_resource->has_decimation, hw_resource->has_macrotile,
hw_resource->has_rotator_downscale);
DLOGI("SourceSplit = %d", hw_resource->is_src_split);
DLOGI("MaxLowBw = %"PRIu64", MaxHighBw = %"PRIu64"", hw_resource->max_bandwidth_low,
hw_resource->max_bandwidth_high);
DLOGI("MaxPipeBw = %"PRIu64" KBps, MaxSDEClock = %"PRIu64" Hz, ClockFudgeFactor = %f",
hw_resource->max_pipe_bw, hw_resource->max_sde_clk, hw_resource->clk_fudge_factor);
return kErrorNone;
}
} // namespace sdm