diff --git a/DisplayInfo/CMakeLists.txt b/DisplayInfo/CMakeLists.txt index 346c0987b1..fb5e45f7c7 100644 --- a/DisplayInfo/CMakeLists.txt +++ b/DisplayInfo/CMakeLists.txt @@ -93,6 +93,11 @@ if (USE_DEVICESETTINGS) PRIVATE DeviceSettings/Amlogic/SoC_abstraction.cpp DeviceSettings/Amlogic/kms.c) + elseif (BUILD_RASPBERRYPI) + target_sources(${MODULE_NAME} + PRIVATE + DeviceSettings/RPI/SoC_abstraction.cpp + DeviceSettings/RPI/kms.c) endif() elseif (NXCLIENT_FOUND AND NEXUS_FOUND) diff --git a/DisplayInfo/DeviceSettings/RPI/SoC_abstraction.cpp b/DisplayInfo/DeviceSettings/RPI/SoC_abstraction.cpp new file mode 100644 index 0000000000..058233484c --- /dev/null +++ b/DisplayInfo/DeviceSettings/RPI/SoC_abstraction.cpp @@ -0,0 +1,184 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kms.h" + +#define MEM_PROCFS "/proc/meminfo" +#define TOTAL_MEM_PARAM_STR "MemTotal:" +#define FREE_MEM_PARAM_STR "MemFree:" +#define DEFAULT_DEVICE "/dev/dri/card1" + +using namespace std; + +static uint64_t parseLine(const char * line); +static uint64_t getMemInfo(const char * param); +static void getPrimaryPlane(int drm_fd, kms_ctx *kms, drmModePlane **plane); +static void getGraphicSize(uint32_t &w, uint32_t &h); + +static uint64_t parseLine(const char * line) +{ + string str(line); + uint64_t val = 0; + size_t begin = str.find_first_of("0123456789"); + size_t end = string::npos; + + if (string::npos != begin) + end = str.find_first_not_of("0123456789", begin); + + if (string::npos != begin && string::npos != end) + { + + str = str.substr(begin, end); + val = strtoul(str.c_str(), NULL, 10); + + } + else + { + cout << "Failed to parse: " << line << endl; + } + + return val; +} + +static uint64_t getMemInfo(const char * param) +{ + FILE *meminfoFile = fopen(MEM_PROCFS, "r"); + uint64_t memVal = 0; + if (NULL == meminfoFile) + { + cout << "Failed to open " << MEM_PROCFS << ", error: " << strerror(errno) << endl; + } + else + { + vector buf; + buf.resize(1024); + + while (fgets(buf.data(), buf.size(), meminfoFile)) + { + if ( strstr(buf.data(), param ) == buf.data()) + { + memVal = parseLine(buf.data()) * 1000; + break; + } + } + + fclose(meminfoFile); + } + return memVal; +} + +static void getPrimaryPlane(int drm_fd, kms_ctx *kms, drmModePlane **plane) +{ + kms_get_plane(drm_fd, kms); + cout << "Primary Plane ID : "<< kms->primary_plane_id << endl; + *plane = drmModeGetPlane(drm_fd, kms->primary_plane_id ); + if(*plane) + printf("fb id : %d\n", (*plane)->fb_id); +} + +static void getGraphicSize(uint32_t &w, uint32_t &h) +{ + int drm_fd; + kms_ctx *kms = NULL; + drmModePlane *plane = NULL; + int trytimes = 0; + + do { + /* Setup buffer information */ + drm_fd = open( DEFAULT_DEVICE, O_RDWR | O_CLOEXEC); + + /* Setup KMS */ + kms = kms_setup(drm_fd); + if(!kms || !kms->crtc ) { + cout << "[RPI] kms_setup fail" << endl; + break; + } + + /* Get primary buffer */ + getPrimaryPlane(drm_fd, kms, &plane); + if( !plane) { + cout << "[RPI] fail to getPrimaryPlane" << endl; + break; + } + + /* get fb */ + drmModeFB *fb = drmModeGetFB(drm_fd, plane->fb_id); + while(!fb) { + getPrimaryPlane(drm_fd, kms, &plane); + fb = drmModeGetFB(drm_fd, plane->fb_id); + if (trytimes++ > 100) { + cout << "[RPI] fail to getPrimaryPlane" << endl; + break; + } + } + + /* Get the width and height */ + if(fb) { + w = fb->width; + h = fb->height; + drmModeFreeFB(fb); + } + } while(0); + + /* release */ + /* Cleanup buffer info */ + if(kms) { + kms_cleanup_context(kms); + free(kms); + } + + cout << "[getGraphicSize] width : " << w << endl; + cout << "[getGraphicSize] height : " << h << endl; + if(drm_fd >= 0){ + close(drm_fd); + } +} + + +uint64_t SoC_GetTotalGpuRam() +{ + return getMemInfo(TOTAL_MEM_PARAM_STR); +} + +uint64_t SoC_GetFreeGpuRam() +{ + return getMemInfo(FREE_MEM_PARAM_STR); +} + +uint32_t SoC_GetGraphicsWidth() +{ + uint32_t w, h; + getGraphicSize(w, h); + return w; +} + +uint32_t SoC_GetGraphicsHeight() +{ + uint32_t w, h; + getGraphicSize(w, h); + return h; +} diff --git a/DisplayInfo/DeviceSettings/RPI/kms.c b/DisplayInfo/DeviceSettings/RPI/kms.c new file mode 100644 index 0000000000..cde7d05d7f --- /dev/null +++ b/DisplayInfo/DeviceSettings/RPI/kms.c @@ -0,0 +1,212 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include "kms.h" + +void kms_setup_encoder( int fd, kms_ctx *kms ) +{ + for( int i = 0; i < kms->res->count_encoders; i++ ) { + + kms->encoder = drmModeGetEncoder(fd,kms->res->encoders[i]); + + if(!kms->encoder){ + return; + } + + if ( kms->encoder->encoder_id == kms->connector->encoder_id ) { + + kms->encoder_id = kms->encoder->encoder_id; + return; + } + + + for( int j = 0; j < kms->res->count_crtcs; j++ ) { + + if( kms->encoder->possible_crtcs & ( 1 << j ) ) { + + drmModeFreeEncoder( kms->encoder ); + kms->encoder = drmModeGetEncoder(fd, kms->res->encoders[j]); + + kms->encoder->crtc_id = kms->crtc_id = j; + goto exit; + } + } + } + +exit: + return; +} + + + + +void kms_setup_connector( int fd, kms_ctx *kms ) +{ + int i = 0; + drmModeConnector *connector = NULL; + + for( i = 0; i < kms->res->count_connectors; i++ ) { + + connector = drmModeGetConnector(fd, kms->res->connectors[i]); + if( connector ) { + + if( connector->count_modes && ( connector->connection == DRM_MODE_CONNECTED ) ) { + break; + } + } + } + + if ( connector ) { + + kms->connector = connector; + kms->connector_id = connector->connector_id; + } + + return; +} + + +void kms_setup_crtc( int fd, kms_ctx *kms ) +{ + if( kms->encoder ) { + + kms->crtc = drmModeGetCrtc(fd, kms->encoder->crtc_id); + + if( kms->crtc && kms->crtc->mode_valid ) { + + kms->current_info = kms->crtc->mode; + kms->crtc_id = kms->encoder->crtc_id; + } + } + + return; +} + + +kms_ctx* kms_setup( int fd ) +{ + kms_ctx *kms = NULL; + kms = (kms_ctx*)calloc(1,sizeof(*kms)); + if( !kms ) + assert(0); + + kms->res = drmModeGetResources(fd); + + kms_setup_connector(fd, kms); + kms_setup_encoder(fd, kms); + kms_setup_crtc(fd, kms); + return kms; +} + + +void kms_cleanup_context( kms_ctx *kms ) +{ + if( kms->connector ) + drmModeFreeConnector(kms->connector); + + if( kms->encoder ) + drmModeFreeEncoder(kms->encoder); + + if( kms->crtc ) + drmModeFreeCrtc(kms->crtc); + + if( kms->res ) + drmModeFreeResources(kms->res); +} + + +uint32_t kms_get_properties(int fd, drmModeObjectProperties *props, const char *name) +{ + drmModePropertyPtr property; + uint32_t i, id = 0; + + for (i = 0; i < props->count_props; i++) { + + property = drmModeGetProperty(fd, props->props[i]); + if (!strcmp(property->name, name)) + id = property->prop_id; + + drmModeFreeProperty(property); + + if ( id ) + return id; + } + return id; +} + + + +void kms_get_plane( int fd, kms_ctx *kms ) +{ + int n = 0, j = 0; + + drmModePlane *plane = NULL; + drmModePlaneRes *planeRes = NULL; + drmModePropertyRes *prop = NULL; + drmModeObjectProperties *props = NULL; + + drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + + kms->primary_plane_id = kms->overlay_plane_id = -1; + + planeRes = drmModeGetPlaneResources( fd ); + if ( planeRes ) { + + for( n= 0; n < planeRes->count_planes; ++n ) { + + plane = drmModeGetPlane( fd, planeRes->planes[n] ); + + if ( plane ) { + + props = drmModeObjectGetProperties( fd, planeRes->planes[n], DRM_MODE_OBJECT_PLANE ); + if ( props ) { + + for( j= 0; j < props->count_props; ++j ) { + + prop = drmModeGetProperty( fd, props->props[j] ); + if ( prop ) { + + if ( !strcmp( prop->name, "type") ) { + + if ( ( props->prop_values[j] == DRM_PLANE_TYPE_PRIMARY ) && ( kms->primary_plane_id == -1 ) ) + kms->primary_plane_id = planeRes->planes[n]; + + else if ( ( props->prop_values[j] == DRM_PLANE_TYPE_OVERLAY ) && ( kms->overlay_plane_id == -1 ) ) + kms->overlay_plane_id = planeRes->planes[n]; + } + } + + drmModeFreeProperty( prop ); + } + } + + drmModeFreeObjectProperties( props ); + } + + drmModeFreePlane( plane ); + } + + } + + drmModeFreePlaneResources( planeRes ); +} diff --git a/DisplayInfo/DeviceSettings/RPI/kms.h b/DisplayInfo/DeviceSettings/RPI/kms.h new file mode 100644 index 0000000000..454a59bc5d --- /dev/null +++ b/DisplayInfo/DeviceSettings/RPI/kms.h @@ -0,0 +1,139 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DRM_KMS_H__ +#define __DRM_KMS_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _kms_ctx { + + drmModeRes *res; + drmModeConnector *connector; + drmModeEncoder *encoder; + drmModeCrtc *crtc; + + drmModeCrtc *previous_crtc; + drmModeModeInfo current_info; + + uint32_t connector_id; /**< Connector id which will be use in program */ + uint32_t crtc_id; + uint32_t encoder_id; + uint32_t primary_plane_id; + uint32_t overlay_plane_id; + + /* atomic properties */ + uint32_t active_property; + uint32_t mode_id_property; + uint32_t crtc_id_property; + uint32_t blob_id; + + uint32_t fb_id_property; + uint32_t crtc_x_property; + uint32_t crtc_y_property; + uint32_t crtc_h_property; + uint32_t crtc_w_property; + uint32_t src_x_property; + uint32_t src_y_property; + uint32_t src_w_property; + uint32_t src_h_property; + + drmModeAtomicReq *req; + +} kms_ctx; + +/** + * @brief Create kms context + * + * @param[in] fd drm file descriptor + * + * + * @retval kms context + */ +kms_ctx* kms_setup(int fd); + + + +/** + * @brief Cleanup kms context + * + * @param[in] kms kms context + * + */ +void kms_cleanup_context(kms_ctx *kms); + +/** + * @brief Set and get possible encoder id + * + * @param[in] fd drm file descriptor + * @param[in] kms kms context + * + */ +void kms_setup_encoder(int fd, kms_ctx *kms); + + +/** + * @brief Set and get possible connector id + * + * @param[in] fd drm file descriptor + * @para,[in] kms kms context + * + */ +void kms_setup_connector(int fd, kms_ctx *kms); + +/** + * @brief Set and get possible crtc id + * + * @param[in] fd drm file descriptor + * @param[in] kms kms context + * + */ +void kms_setup_crtc(int fd, kms_ctx *kms); + +/** + * @brief Get the specific object properties + * + * @param[in] fd drm file descriptor + * @param[in] props all object properties + * @param[in] name the property name which want to be queried + * + */ +uint32_t kms_get_properties(int fd, drmModeObjectProperties *props, const char *name); + + +/** + * @brief Get primary and overlay plane. + * The plane id will set to -1 if cannot get. + * + * @param[in] fd drm file descriptor + * @param[in] kms kms context + * + */ +void kms_get_plane( int fd, kms_ctx *kms); + +#ifdef __cplusplus +} +#endif +#endif