1218 lines
44 KiB
C++
1218 lines
44 KiB
C++
/*
|
||
* Copyright 2014 The Android Open Source Project
|
||
*
|
||
* 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.
|
||
*/
|
||
#define LOG_TAG "hw_output"
|
||
|
||
#include <errno.h>
|
||
#include <fcntl.h>
|
||
#include <inttypes.h>
|
||
#include <malloc.h>
|
||
#include <stdio.h>
|
||
#include <stdint.h>
|
||
#include <drm_fourcc.h>
|
||
|
||
#include <string>
|
||
#include <map>
|
||
#include <vector>
|
||
#include <iostream>
|
||
|
||
#include <cutils/native_handle.h>
|
||
#include <cutils/properties.h>
|
||
#include <log/log.h>
|
||
|
||
#include "hw_output.h"
|
||
#include "baseparameter_api.h"
|
||
#include "hw_types.h"
|
||
|
||
#include "rkdisplay/drmresources.h"
|
||
#include "rkdisplay/drmmode.h"
|
||
#include "rkdisplay/drmconnector.h"
|
||
#include "rkdisplay/drmgamma.h"
|
||
#include "rockchip/baseparameter.h"
|
||
|
||
using namespace android;
|
||
|
||
#define LOG_LEVEL_ERROR 0
|
||
#define LOG_LEVEL_WARN 1
|
||
#define LOG_LEVEL_INFO 2
|
||
#define LOG_LEVEL_DEBUG 3
|
||
|
||
static int mHwcVersion = 0;
|
||
std::map<int,DrmConnector*> mGlobalConns;
|
||
static int dbgLevel = 3;
|
||
#define LOG_INFO(format, ...) \
|
||
do {\
|
||
if (dbgLevel < LOG_LEVEL_INFO)\
|
||
break;\
|
||
ALOGD("%s[%d]" format, __FUNCTION__, __LINE__, ##_VA_ARGS__); \
|
||
} while(0)
|
||
|
||
/*****************************************************************************/
|
||
|
||
typedef struct hw_output_private {
|
||
hw_output_device_t device;
|
||
|
||
// Callback related data
|
||
void* callback_data;
|
||
DrmResources *drm_;
|
||
DrmConnector* primary;
|
||
DrmConnector* extend;
|
||
BaseParameter* mBaseParmeter;
|
||
struct lut_info* mlut;
|
||
}hw_output_private_t;
|
||
|
||
static int hw_output_device_open(const struct hw_module_t* module,
|
||
const char* name, struct hw_device_t** device);
|
||
|
||
static struct hw_module_methods_t hw_output_module_methods = {
|
||
.open = hw_output_device_open
|
||
};
|
||
|
||
hw_output_module_t HAL_MODULE_INFO_SYM = {
|
||
.common = {
|
||
.tag = HARDWARE_MODULE_TAG,
|
||
.version_major = 1,
|
||
.version_minor = 0,
|
||
.id = HW_OUTPUT_HARDWARE_MODULE_ID,
|
||
.name = "Sample hw output module",
|
||
.author = "The Android Open Source Project",
|
||
.methods = &hw_output_module_methods,
|
||
.dso = NULL,
|
||
.reserved = {0},
|
||
}
|
||
};
|
||
|
||
static bool builtInHdmi(int type){
|
||
return type == DRM_MODE_CONNECTOR_HDMIA || type == DRM_MODE_CONNECTOR_HDMIB;
|
||
}
|
||
|
||
static void checkBcshInfo(uint32_t* mBcsh)
|
||
{
|
||
if (mBcsh[0] < 0)
|
||
mBcsh[0] = 0;
|
||
else if (mBcsh[0] > 100)
|
||
mBcsh[0] = 100;
|
||
|
||
if (mBcsh[1] < 0)
|
||
mBcsh[1] = 0;
|
||
else if (mBcsh[1] > 100)
|
||
mBcsh[1] = 100;
|
||
|
||
if (mBcsh[2] < 0)
|
||
mBcsh[2] = 0;
|
||
else if (mBcsh[2] > 100)
|
||
mBcsh[2] = 100;
|
||
|
||
if (mBcsh[3] < 0)
|
||
mBcsh[3] = 0;
|
||
else if (mBcsh[3] > 100)
|
||
mBcsh[3] = 100;
|
||
}
|
||
|
||
static void updateTimeline()
|
||
{
|
||
std::string strTimeline;
|
||
char property[100];
|
||
int timeline = property_get_int32("vendor.display.timeline", 1);
|
||
|
||
timeline++;
|
||
strTimeline = std::to_string(timeline);
|
||
property_set("vendor.display.timeline", strTimeline.c_str());
|
||
|
||
property_get("vendor.hw_output.debug", property, "3");
|
||
dbgLevel = atoi(property);
|
||
}
|
||
|
||
DrmConnector* getValidDrmConnector(hw_output_private_t *priv, int dpy)
|
||
{
|
||
std::map<int, DrmConnector*> mConns = mGlobalConns;
|
||
std::map<int, DrmConnector*>::iterator iter;
|
||
DrmConnector* mConnector = nullptr;
|
||
(void)priv;
|
||
|
||
iter = mConns.find(dpy);
|
||
if (iter != mConns.end()) {
|
||
mConnector = iter->second;
|
||
}
|
||
|
||
return mConnector;
|
||
}
|
||
|
||
static std::string getPropertySuffix(hw_output_private_t *priv, std::string header, int dpy)
|
||
{
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
std::string suffix;
|
||
|
||
suffix = header;
|
||
if (mHwcVersion == 2) {
|
||
if (conn != nullptr) {
|
||
const char* connTypeStr = priv->drm_->connector_type_str(conn->get_type());
|
||
int id = conn->connector_id();
|
||
suffix += connTypeStr;
|
||
suffix += '-';
|
||
ALOGD("id=%d", id);
|
||
suffix += std::to_string(id);
|
||
}
|
||
} else {
|
||
std::string propertyStr = "vendor.hwc.device.primary";
|
||
char mainProperty[100];
|
||
property_get(propertyStr.c_str(), mainProperty, "");
|
||
ALOGE("mainProperty = %s\n", mainProperty);
|
||
if ((conn->get_type() == DRM_MODE_CONNECTOR_HDMIA && strstr(mainProperty, "HDMI-A"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_HDMIB && strstr(mainProperty, "HDMI-B"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_TV && strstr(mainProperty, "TV"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_VGA && strstr(mainProperty, "VGA"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_DisplayPort && strstr(mainProperty, "DP"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_eDP && strstr(mainProperty, "eDP"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_VIRTUAL && strstr(mainProperty, "Virtual"))
|
||
|| (conn->get_type() == DRM_MODE_CONNECTOR_DSI && strstr(mainProperty, "DSI")))
|
||
suffix += "main";
|
||
else
|
||
suffix += "aux";
|
||
}
|
||
ALOGD("suffix=%s", suffix.c_str());
|
||
return suffix;
|
||
}
|
||
|
||
static int findSuitableInfoSlot(struct disp_info* info, int type, int id)
|
||
{
|
||
int found=0;
|
||
for (int i=0;i<4;i++) {
|
||
if (info->screen_info[i].type !=0 && info->screen_info[i].type == type &&
|
||
info->screen_info[i].id == id) {
|
||
found = i;
|
||
break;
|
||
} else if (info->screen_info[i].type !=0 && found == false){
|
||
found++;
|
||
}
|
||
}
|
||
if (found == -1) {
|
||
found = 0;
|
||
ALOGD("noting saved, used the first slot");
|
||
}
|
||
ALOGD("findSuitableInfoSlot: %d type=%d", found, type);
|
||
return found;
|
||
}
|
||
|
||
static bool getResolutionInfo(hw_output_private_t *priv, int dpy, char* resolution)
|
||
{
|
||
drmModePropertyBlobPtr blob;
|
||
drmModeObjectPropertiesPtr props;
|
||
DrmConnector* mCurConnector = NULL;
|
||
DrmCrtc *crtc = NULL;
|
||
struct drm_mode_modeinfo *drm_mode;
|
||
struct disp_info info;
|
||
BaseParameter* mBaseParmeter = priv->mBaseParmeter;
|
||
int value;
|
||
bool found = false;
|
||
|
||
mCurConnector = getValidDrmConnector(priv, dpy);
|
||
if (mCurConnector == nullptr) {
|
||
sprintf(resolution, "%s", "Auto");
|
||
return false;
|
||
}
|
||
|
||
if (mBaseParmeter && mBaseParmeter->have_baseparameter()) {
|
||
if (mCurConnector)
|
||
mBaseParmeter->get_disp_info(mCurConnector->get_type(), mCurConnector->connector_id(), &info);
|
||
int slot = findSuitableInfoSlot(&info, mCurConnector->get_type(), mCurConnector->connector_id());
|
||
if (!info.screen_info[slot].resolution.hdisplay ||
|
||
!info.screen_info[slot].resolution.clock ||
|
||
!info.screen_info[slot].resolution.vdisplay) {
|
||
sprintf(resolution, "%s", "Auto");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (mCurConnector != NULL) {
|
||
crtc = priv->drm_->GetCrtcFromConnector(mCurConnector);
|
||
if (crtc == NULL) {
|
||
return false;
|
||
}
|
||
props = drmModeObjectGetProperties(priv->drm_->fd(), crtc->id(), DRM_MODE_OBJECT_CRTC);
|
||
for (int i = 0; !found && (size_t)i < props->count_props; ++i) {
|
||
drmModePropertyPtr p = drmModeGetProperty(priv->drm_->fd(), props->props[i]);
|
||
if (!strcmp(p->name, "MODE_ID")) {
|
||
found = true;
|
||
if (!drm_property_type_is(p, DRM_MODE_PROP_BLOB)) {
|
||
ALOGE("%s:line=%d,is not blob",__FUNCTION__,__LINE__);
|
||
drmModeFreeProperty(p);
|
||
drmModeFreeObjectProperties(props);
|
||
return false;
|
||
}
|
||
if (!p->count_blobs)
|
||
value = props->prop_values[i];
|
||
else
|
||
value = p->blob_ids[0];
|
||
blob = drmModeGetPropertyBlob(priv->drm_->fd(), value);
|
||
if (!blob) {
|
||
ALOGE("%s:line=%d, blob is null",__FUNCTION__,__LINE__);
|
||
drmModeFreeProperty(p);
|
||
drmModeFreeObjectProperties(props);
|
||
return false;
|
||
}
|
||
|
||
float vfresh;
|
||
drm_mode = (struct drm_mode_modeinfo *)blob->data;
|
||
if (drm_mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||
vfresh = drm_mode->clock *2/ (float)(drm_mode->vtotal * drm_mode->htotal) * 1000.0f;
|
||
else
|
||
vfresh = drm_mode->clock / (float)(drm_mode->vtotal * drm_mode->htotal) * 1000.0f;
|
||
ALOGD("nativeGetCurMode: crtc_id=%d clock=%d w=%d %d %d %d %d %d flag=0x%x vfresh %.2f drm.vrefresh=%.2f",
|
||
crtc->id(), drm_mode->clock, drm_mode->htotal, drm_mode->hsync_start,
|
||
drm_mode->hsync_end, drm_mode->vtotal, drm_mode->vsync_start, drm_mode->vsync_end, drm_mode->flags,
|
||
vfresh, (float)drm_mode->vrefresh);
|
||
sprintf(resolution, "%dx%d@%.2f-%d-%d-%d-%d-%d-%d-%x-%d", drm_mode->hdisplay, drm_mode->vdisplay, vfresh,
|
||
drm_mode->hsync_start, drm_mode->hsync_end, drm_mode->htotal,
|
||
drm_mode->vsync_start, drm_mode->vsync_end, drm_mode->vtotal,
|
||
(drm_mode->flags&0xFFFF), drm_mode->clock);
|
||
drmModeFreePropertyBlob(blob);
|
||
}
|
||
drmModeFreeProperty(p);
|
||
}
|
||
drmModeFreeObjectProperties(props);
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
static void updateConnectors(hw_output_private_t *priv){
|
||
if (priv->drm_->connectors().size() == 2) {
|
||
bool foundHdmi=false;
|
||
int cnt=0,crtcId1=0,crtcId2=0;
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if (cnt == 0 && priv->drm_->GetCrtcFromConnector(conn.get())) {
|
||
ALOGD("encoderId1: %d", conn->encoder()->id());
|
||
crtcId1 = priv->drm_->GetCrtcFromConnector(conn.get())->id();
|
||
} else if (priv->drm_->GetCrtcFromConnector(conn.get())){
|
||
ALOGD("encoderId2: %d", conn->encoder()->id());
|
||
crtcId2 = priv->drm_->GetCrtcFromConnector(conn.get())->id();
|
||
}
|
||
|
||
if (builtInHdmi(conn->get_type()))
|
||
foundHdmi=true;
|
||
cnt++;
|
||
}
|
||
ALOGD("crtc: %d %d foundHdmi %d 2222", crtcId1, crtcId2, foundHdmi);
|
||
char property[PROPERTY_VALUE_MAX];
|
||
property_get("vendor.hwc.device.primary", property, "null");
|
||
if (crtcId1 == crtcId2 && foundHdmi && strstr(property, "HDMI-A") == NULL) {
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if (builtInHdmi(conn->get_type()) && conn->state() == DRM_MODE_CONNECTED) {
|
||
priv->extend = conn.get();
|
||
conn->set_display(1);
|
||
} else if(!builtInHdmi(conn->get_type()) && conn->state() == DRM_MODE_CONNECTED) {
|
||
priv->primary = conn.get();
|
||
conn->set_display(0);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
static int hw_output_update_disp_header(struct hw_output_device *dev)
|
||
{
|
||
bool found = false;
|
||
int ret = 0, firstEmptyHeader = -1;
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParmeter = priv->mBaseParmeter;
|
||
struct disp_header * headers = (disp_header *)malloc(sizeof(disp_header) * 8);
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if(conn->state() == DRM_MODE_CONNECTED){
|
||
found = false;
|
||
firstEmptyHeader = -1;
|
||
ret = mBaseParmeter->get_all_disp_header(headers);
|
||
if(ret != 0) {
|
||
break;
|
||
}
|
||
for(int i = 0; i < 8; i++){
|
||
if(headers[i].connector_type == conn->get_type() && headers[i].connector_id == conn->connector_id()){
|
||
found = true;
|
||
}
|
||
if(firstEmptyHeader == -1 && headers[i].connector_type == 0 && headers[i].connector_id == 0){
|
||
firstEmptyHeader = i;
|
||
}
|
||
}
|
||
if(!found){
|
||
ret = mBaseParmeter->set_disp_header(firstEmptyHeader, conn->get_type(), conn->connector_id());
|
||
}
|
||
}
|
||
}
|
||
free(headers);
|
||
return ret;
|
||
}
|
||
|
||
/*****************************************************************************/
|
||
static void hw_output_save_config(struct hw_output_device* dev){
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
if (priv->mBaseParmeter)
|
||
priv->mBaseParmeter->saveConfig();
|
||
}
|
||
|
||
static void hw_output_hotplug_update(struct hw_output_device* dev){
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
|
||
DrmConnector *mextend = NULL;
|
||
DrmConnector *mprimary = NULL;
|
||
int dpy = 0;
|
||
int index = 0;
|
||
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
drmModeConnection old_state = conn->state();
|
||
|
||
conn->UpdateModes();
|
||
|
||
drmModeConnection cur_state = conn->state();
|
||
ALOGD("old_state %d cur_state %d conn->get_type() %d", old_state, cur_state, conn->get_type());
|
||
|
||
if (cur_state == old_state) {
|
||
index++;
|
||
continue;
|
||
}
|
||
ALOGI("%s event for connector %u\n",
|
||
cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", conn->id());
|
||
|
||
for (DrmEncoder *enc : conn->possible_encoders()) {
|
||
for (DrmCrtc *crtc : enc->possible_crtcs()) {
|
||
if(conn->state() == DRM_MODE_CONNECTED) {
|
||
enc->set_crtc(crtc);
|
||
conn->set_encoder(enc);
|
||
} else {
|
||
enc->set_crtc(NULL);
|
||
conn->set_encoder(NULL);
|
||
}
|
||
}
|
||
}
|
||
mGlobalConns[index] = conn.get();
|
||
if (cur_state == DRM_MODE_CONNECTED) {
|
||
if (conn->possible_displays() & HWC_DISPLAY_EXTERNAL_BIT) {
|
||
mextend = conn.get();
|
||
} else if (conn->possible_displays() & HWC_DISPLAY_PRIMARY_BIT) {
|
||
mprimary = conn.get();
|
||
}
|
||
}
|
||
index++;
|
||
}
|
||
|
||
/*
|
||
* status changed?
|
||
*/
|
||
priv->drm_->DisplayChanged();
|
||
dpy = mGlobalConns.size();
|
||
|
||
DrmConnector *old_primary = priv->drm_->GetConnectorFromType(HWC_DISPLAY_PRIMARY);
|
||
mprimary = mprimary ? mprimary : old_primary;
|
||
if (!mprimary || mprimary->state() != DRM_MODE_CONNECTED) {
|
||
mprimary = NULL;
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if (!(conn->possible_displays() & HWC_DISPLAY_PRIMARY_BIT))
|
||
continue;
|
||
if (conn->state() == DRM_MODE_CONNECTED) {
|
||
mprimary = conn.get();
|
||
//mGlobalConns[HWC_DISPLAY_PRIMARY] = conn.get();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!mprimary) {
|
||
ALOGE("%s %d Failed to find primary display\n", __FUNCTION__, __LINE__);
|
||
//return;
|
||
}
|
||
if (mprimary && mprimary != old_primary) {
|
||
priv->drm_->SetPrimaryDisplay(mprimary);
|
||
}
|
||
|
||
DrmConnector *old_extend = priv->drm_->GetConnectorFromType(HWC_DISPLAY_EXTERNAL);
|
||
mextend = mextend ? mextend : old_extend;
|
||
dpy = 1;
|
||
if (!mextend || mextend->state() != DRM_MODE_CONNECTED) {
|
||
mextend = NULL;
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if (!(conn->possible_displays() & HWC_DISPLAY_EXTERNAL_BIT))
|
||
continue;
|
||
if (mprimary && conn->id() == mprimary->id())
|
||
continue;
|
||
if (conn->state() == DRM_MODE_CONNECTED) {
|
||
mextend = conn.get();
|
||
//mGlobalConns[dpy] = conn.get();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
priv->drm_->SetExtendDisplay(mextend);
|
||
priv->drm_->DisplayChanged();
|
||
priv->drm_->UpdateDisplayRoute();
|
||
priv->drm_->ClearDisplay();
|
||
|
||
updateConnectors(priv);
|
||
hw_output_update_disp_header(dev);
|
||
}
|
||
|
||
static int hw_output_init_baseparameter(BaseParameter** mBaseParmeter)
|
||
{
|
||
char property[100];
|
||
property_get("vendor.ghwc.version", property, NULL);
|
||
if (strstr(property, "HWC2") != NULL) {
|
||
*mBaseParmeter = new BaseParameterV2();
|
||
mHwcVersion = 2;
|
||
} else {
|
||
*mBaseParmeter = new BaseParameterV1();
|
||
mHwcVersion = 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_initialize(struct hw_output_device* dev, void* data)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
|
||
priv->drm_ = NULL;
|
||
priv->primary = NULL;
|
||
priv->extend = NULL;
|
||
priv->mlut = NULL;
|
||
priv->callback_data = data;
|
||
hw_output_init_baseparameter(&priv->mBaseParmeter);
|
||
|
||
if (priv->drm_ == NULL) {
|
||
priv->drm_ = new DrmResources();
|
||
priv->drm_->Init();
|
||
ALOGD("nativeInit: ");
|
||
if (mHwcVersion >= 2) {
|
||
int id=0;
|
||
for (auto &conn : priv->drm_->connectors())
|
||
mGlobalConns.insert(std::make_pair(id++, conn.get()));
|
||
} else {
|
||
int id=0;
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
// 同Hwc2相同处理方式,不区分主副屏
|
||
mGlobalConns.insert(std::make_pair(id++, conn.get()));
|
||
/* if (conn->possible_displays() & HWC_DISPLAY_PRIMARY_BIT)
|
||
mGlobalConns.insert(std::make_pair(HWC_DISPLAY_PRIMARY, conn.get()));
|
||
else
|
||
mGlobalConns.insert(std::make_pair(id++, conn.get())); */
|
||
}
|
||
}
|
||
priv->mBaseParmeter->set_drm_connectors(mGlobalConns);
|
||
hw_output_hotplug_update(dev);
|
||
if (priv->primary == NULL) {
|
||
for (auto &conn : priv->drm_->connectors()) {
|
||
if ((conn->possible_displays() & HWC_DISPLAY_PRIMARY_BIT)) {
|
||
// mGlobalConns[HWC_DISPLAY_PRIMARY] = conn.get();
|
||
}
|
||
if ((conn->possible_displays() & HWC_DISPLAY_EXTERNAL_BIT) && conn->state() == DRM_MODE_CONNECTED) {
|
||
priv->drm_->SetExtendDisplay(conn.get());
|
||
priv->extend = conn.get();
|
||
}
|
||
}
|
||
}
|
||
ALOGD("primary: %p extend: %p ", priv->primary, priv->extend);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*****************************************************************************/
|
||
|
||
static int hw_output_set_mode(struct hw_output_device* dev, int dpy, const char* mode)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
char property[PROPERTY_VALUE_MAX];
|
||
std::string propertyStr;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.resolution.", dpy);
|
||
|
||
ALOGD("nativeSetMode %s display %d", mode, dpy);
|
||
|
||
if (strcmp(mode, property) !=0) {
|
||
property_set(propertyStr.c_str(), mode);
|
||
updateTimeline();
|
||
struct disp_info info;
|
||
float vfresh=0.0f;
|
||
int slot = 0;
|
||
|
||
mBaseParameter->get_disp_info(conn->get_type(), conn->connector_id(), &info);
|
||
slot = findSuitableInfoSlot(&info, conn->get_type(), conn->connector_id());
|
||
info.screen_info[slot].type = conn->get_type();
|
||
info.screen_info[slot].id = conn->connector_id();
|
||
if (strncmp(mode, "Auto", 4) != 0 && strncmp(mode, "0x0p0-0", 7) !=0) {
|
||
sscanf(mode,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x-%d",
|
||
&info.screen_info[slot].resolution.hdisplay, &info.screen_info[slot].resolution.vdisplay,
|
||
&vfresh, &info.screen_info[slot].resolution.hsync_start,&info.screen_info[slot].resolution.hsync_end,
|
||
&info.screen_info[slot].resolution.htotal,&info.screen_info[slot].resolution.vsync_start,
|
||
&info.screen_info[slot].resolution.vsync_end, &info.screen_info[slot].resolution.vtotal,
|
||
&info.screen_info[slot].resolution.flags, &info.screen_info[slot].resolution.clock);
|
||
info.screen_info[slot].resolution.vrefresh = (int)vfresh;
|
||
} else {
|
||
info.screen_info[slot].feature|= RESOLUTION_AUTO;
|
||
memset(&info.screen_info[slot].resolution, 0, sizeof(info.screen_info[slot].resolution));
|
||
}
|
||
mBaseParameter->set_disp_info(conn->get_type(), conn->connector_id(), &info);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_3d_mode(struct hw_output_device*, const char* mode)
|
||
{
|
||
char property[PROPERTY_VALUE_MAX];
|
||
|
||
property_get("vendor.3d_resolution.main", property, "null");
|
||
if (strcmp(mode, property) !=0) {
|
||
property_set("vendor.3d_resolution.main", mode);
|
||
updateTimeline();
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_gamma(struct hw_output_device* dev, int dpy, uint32_t size, uint16_t* r, uint16_t* g, uint16_t* b)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* mConnector = getValidDrmConnector(priv, dpy);
|
||
int ret = -1;
|
||
int crtc_id = 0;
|
||
|
||
if (mConnector)
|
||
crtc_id = priv->drm_->GetCrtcFromConnector(mConnector)->id();
|
||
|
||
ret = DrmGamma::set_3x1d_gamma(priv->drm_->fd(), crtc_id, size, r, g, b);
|
||
if (ret < 0)
|
||
ALOGE("fail to SetGamma %d(%s)", ret, strerror(errno));
|
||
if(ret == 0){
|
||
struct gamma_lut_data data;
|
||
data.size = size;
|
||
for(int i = 0; i< size; i++){
|
||
data.lred[i] = r[i];
|
||
data.lgreen[i] = g[i];
|
||
data.lblue[i] = b[i];
|
||
}
|
||
mBaseParameter->set_gamma_lut_data(mConnector->get_type(), mConnector->connector_id(), &data);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
static int hw_output_set_3d_lut(struct hw_output_device* dev, int dpy, uint32_t size, uint16_t* r, uint16_t* g, uint16_t* b)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* mConnector = getValidDrmConnector(priv, dpy);
|
||
int ret = -1;
|
||
int crtc_id = 0;
|
||
|
||
if (mConnector)
|
||
crtc_id = priv->drm_->GetCrtcFromConnector(mConnector)->id();
|
||
ret = DrmGamma::set_cubic_lut(priv->drm_->fd(), crtc_id, size, r, g, b);
|
||
if (ret < 0)
|
||
ALOGE("fail to set 3d lut %d(%s)", ret, strerror(errno));
|
||
if(ret == 0){
|
||
struct cubic_lut_data data;
|
||
data.size = size;
|
||
for(int i = 0; i< size; i++){
|
||
data.lred[i] = r[i];
|
||
data.lgreen[i] = g[i];
|
||
data.lblue[i] = b[i];
|
||
}
|
||
mBaseParameter->set_cubic_lut_data(mConnector->get_type(), mConnector->connector_id(), &data);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
static int hw_output_set_brightness(struct hw_output_device* dev, int dpy, int brightness)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char tmp[128];
|
||
std::string propertyStr;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.brightness.", dpy);
|
||
sprintf(tmp, "%d", brightness);
|
||
property_get(propertyStr.c_str(), property, "50");
|
||
|
||
if (atoi(property) != brightness) {
|
||
property_set(propertyStr.c_str(), tmp);
|
||
updateTimeline();
|
||
mBaseParameter->set_brightness(conn->get_type(), conn->connector_id(), brightness);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_contrast(struct hw_output_device* dev, int dpy, int contrast)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char tmp[128];
|
||
std::string propertyStr;
|
||
|
||
sprintf(tmp, "%d", contrast);
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.contrast.", dpy);
|
||
property_get(propertyStr.c_str(), property, "50");
|
||
|
||
if (atoi(property) != contrast) {
|
||
property_set(propertyStr.c_str(), tmp);
|
||
updateTimeline();
|
||
mBaseParameter->set_contrast(conn->get_type(), conn->connector_id(), contrast);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_sat(struct hw_output_device* dev, int dpy, int sat)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char tmp[128];
|
||
std::string propertyStr;
|
||
|
||
sprintf(tmp, "%d", sat);
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.saturation.", dpy);
|
||
property_get(propertyStr.c_str(), property, "50");
|
||
|
||
if (atoi(property) != sat) {
|
||
property_set(propertyStr.c_str(), tmp);
|
||
updateTimeline();
|
||
mBaseParameter->set_saturation(conn->get_type(), conn->connector_id(), sat);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_hue(struct hw_output_device* dev, int dpy, int hue)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char tmp[128];
|
||
std::string propertyStr;
|
||
|
||
sprintf(tmp, "%d", hue);
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.hue.", dpy);
|
||
property_get(propertyStr.c_str(), property, "50");
|
||
|
||
if (atoi(property) != hue) {
|
||
property_set(propertyStr.c_str(), tmp);
|
||
updateTimeline();
|
||
mBaseParameter->set_hue(conn->get_type(), conn->connector_id(), hue);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_screen_scale(struct hw_output_device* dev, int dpy, int direction, int value)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
std::string propertyStr;
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char overscan[128];
|
||
int left,top,right,bottom;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.overscan.", dpy);
|
||
property_get(propertyStr.c_str(), property, "overscan 100,100,100,100");
|
||
sscanf(property, "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
|
||
|
||
if (direction == OVERSCAN_LEFT)
|
||
left = value;
|
||
else if (direction == OVERSCAN_TOP)
|
||
top = value;
|
||
else if (direction == OVERSCAN_RIGHT)
|
||
right = value;
|
||
else if (direction == OVERSCAN_BOTTOM)
|
||
bottom = value;
|
||
|
||
sprintf(overscan, "overscan %d,%d,%d,%d", left, top, right, bottom);
|
||
|
||
if (strcmp(property, overscan) != 0) {
|
||
property_set(propertyStr.c_str(), overscan);
|
||
updateTimeline();
|
||
struct overscan_info overscan;
|
||
overscan.maxvalue = 100;
|
||
overscan.leftscale = left;
|
||
overscan.topscale = top;
|
||
overscan.rightscale = right;
|
||
overscan.bottomscale = bottom;
|
||
mBaseParameter->set_overscan_info(conn->get_type(), conn->id(), &overscan);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_hdr_mode(struct hw_output_device* dev, int dpy, int hdr_mode)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
std::string propertyStr, hdrStr;
|
||
char property[PROPERTY_VALUE_MAX];
|
||
char tmp[128];
|
||
|
||
sprintf(tmp, "%d", hdr_mode);
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.hdr_mode.", dpy);
|
||
property_get(propertyStr.c_str(), property, "50");
|
||
|
||
if (atoi(property) != hdr_mode) {
|
||
property_set(propertyStr.c_str(), tmp);
|
||
updateTimeline();
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_color_mode(struct hw_output_device* dev, int dpy, const char* color_mode)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParameter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
std::string propertyStr;
|
||
struct disp_info info;
|
||
char property[PROPERTY_VALUE_MAX];
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.color.", dpy);
|
||
property_get(propertyStr.c_str(), property, NULL);
|
||
ALOGD("hw_output_set_color_mode %s display %d property=%s", color_mode, dpy, property);
|
||
|
||
if (strcmp(color_mode, property) !=0) {
|
||
property_set(propertyStr.c_str(), color_mode);
|
||
property_get(propertyStr.c_str(), property, NULL);
|
||
updateTimeline();
|
||
}
|
||
if (conn) {
|
||
mBaseParameter->get_disp_info(conn->get_type(), conn->connector_id(), &info);
|
||
int slot = findSuitableInfoSlot(&info, conn->get_type(), conn->connector_id());
|
||
if (strncmp(property, "Auto", 4) != 0){
|
||
if (strstr(property, "RGB") != 0)
|
||
info.screen_info[slot].format = output_rgb;
|
||
else if (strstr(property, "YCBCR444") != 0)
|
||
info.screen_info[slot].format = output_ycbcr444;
|
||
else if (strstr(property, "YCBCR422") != 0)
|
||
info.screen_info[slot].format = output_ycbcr422;
|
||
else if (strstr(property, "YCBCR420") != 0)
|
||
info.screen_info[slot].format = output_ycbcr420;
|
||
else {
|
||
info.screen_info[slot].feature |= COLOR_AUTO;
|
||
info.screen_info[slot].format = output_ycbcr_high_subsampling;
|
||
}
|
||
|
||
if (strstr(property, "8bit") != NULL)
|
||
info.screen_info[slot].depthc = depth_24bit;
|
||
else if (strstr(property, "10bit") != NULL)
|
||
info.screen_info[slot].depthc = depth_30bit;
|
||
else
|
||
info.screen_info[slot].depthc = Automatic;
|
||
} else {
|
||
info.screen_info[slot].depthc = Automatic;
|
||
info.screen_info[slot].format = output_ycbcr_high_subsampling;
|
||
info.screen_info[slot].feature |= COLOR_AUTO;
|
||
}
|
||
ALOGD("saveConfig: color=%d-%d", info.screen_info[slot].format, info.screen_info[slot].depthc);
|
||
mBaseParameter->set_disp_info(conn->get_type(), conn->connector_id(), &info);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_cur_mode(struct hw_output_device* dev, int dpy, char* curMode)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
bool found=false;
|
||
|
||
if (curMode != NULL)
|
||
found = getResolutionInfo(priv, dpy, curMode);
|
||
else
|
||
return -1;
|
||
|
||
if (!found) {
|
||
sprintf(curMode, "%s", "Auto");
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_cur_color_mode(struct hw_output_device* dev, int dpy, char* curColorMode)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
DrmConnector* mCurConnector = getValidDrmConnector(priv, dpy);
|
||
BaseParameter* mBaseParmeter = priv->mBaseParmeter;
|
||
struct disp_info dispInfo;
|
||
std::string propertyStr;
|
||
char colorMode[PROPERTY_VALUE_MAX];
|
||
|
||
int len=0;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.color.", dpy);
|
||
len = property_get(propertyStr.c_str(), colorMode, NULL);
|
||
|
||
ALOGD("nativeGetCurCorlorMode: property=%s", colorMode);
|
||
if (!len && mBaseParmeter && mBaseParmeter->have_baseparameter()) {
|
||
mBaseParmeter->get_disp_info(mCurConnector->get_type(), mCurConnector->connector_id(), &dispInfo);
|
||
int slot = findSuitableInfoSlot(&dispInfo, mCurConnector->get_type(), mCurConnector->connector_id());
|
||
if (dispInfo.screen_info[slot].depthc == Automatic &&
|
||
dispInfo.screen_info[slot].format == output_ycbcr_high_subsampling)
|
||
sprintf(colorMode, "%s", "Auto");
|
||
}
|
||
|
||
sprintf(curColorMode, "%s", colorMode);
|
||
ALOGD("nativeGetCurCorlorMode: colorMode=%s", colorMode);
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_num_connectors(struct hw_output_device* dev, int, int* numConnectors)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
(void)priv;
|
||
|
||
*numConnectors = mGlobalConns.size();//priv->drm_->connectors().size();
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_connector_state(struct hw_output_device* dev, int dpy, int* state)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
int ret = 0;
|
||
DrmConnector* mConn = getValidDrmConnector(priv, dpy);
|
||
|
||
if (mConn != nullptr) {
|
||
*state = mConn->state();
|
||
} else {
|
||
ret = -1;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
static int hw_output_get_color_configs(struct hw_output_device* dev, int dpy, int* configs)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
DrmConnector* mCurConnector = getValidDrmConnector(priv, dpy);;
|
||
uint64_t color_capacity=0;
|
||
uint64_t depth_capacity=0;
|
||
|
||
if (mCurConnector != NULL) {
|
||
if (mCurConnector->hdmi_output_mode_capacity_property().id())
|
||
mCurConnector->hdmi_output_mode_capacity_property().value( &color_capacity);
|
||
|
||
if (mCurConnector->hdmi_output_depth_capacity_property().id())
|
||
mCurConnector->hdmi_output_depth_capacity_property().value(&depth_capacity);
|
||
|
||
configs[0] = (int)color_capacity;
|
||
configs[1] = (int)depth_capacity;
|
||
ALOGD("nativeGetCorlorModeConfigs: corlor=%d depth=%d configs:%d %d",(int)color_capacity,(int)depth_capacity, configs[0], configs[1]);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_overscan(struct hw_output_device* dev, int dpy, uint32_t* overscans)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
char property[PROPERTY_VALUE_MAX];
|
||
std::string propertyStr;
|
||
int left,top,right,bottom;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.overscan.", dpy);
|
||
property_get(propertyStr.c_str(), property, "overscan 100,100,100,100");
|
||
|
||
sscanf(property, "overscan %d,%d,%d,%d", &left, &top, &right, &bottom);
|
||
overscans[0] = left;
|
||
overscans[1] = top;
|
||
overscans[2] = right;
|
||
overscans[3] = bottom;
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_bcsh(struct hw_output_device* dev, int dpy, uint32_t* bcshs)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
BaseParameter* mBaseParmeter = priv->mBaseParmeter;
|
||
DrmConnector* conn = getValidDrmConnector(priv, dpy);
|
||
char mBcshProperty[PROPERTY_VALUE_MAX];
|
||
std::string propertyStr;
|
||
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.brightness.", dpy);
|
||
if (property_get(propertyStr.c_str(), mBcshProperty, NULL) > 0) {
|
||
bcshs[0] = atoi(mBcshProperty);
|
||
} else if (mBaseParmeter&&mBaseParmeter->have_baseparameter()) {
|
||
bcshs[0] = mBaseParmeter->get_brightness(conn->get_type(), conn->connector_id());
|
||
} else {
|
||
bcshs[0] = DEFAULT_BRIGHTNESS;
|
||
}
|
||
|
||
memset(mBcshProperty, 0, sizeof(mBcshProperty));
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.contrast.", dpy);
|
||
if (property_get(propertyStr.c_str(), mBcshProperty, NULL) > 0) {
|
||
bcshs[1] = atoi(mBcshProperty);
|
||
} else if (mBaseParmeter&&mBaseParmeter->have_baseparameter()) {
|
||
bcshs[1] = mBaseParmeter->get_contrast(conn->get_type(), conn->connector_id());
|
||
} else {
|
||
bcshs[1] = DEFAULT_CONTRAST;
|
||
}
|
||
|
||
memset(mBcshProperty, 0, sizeof(mBcshProperty));
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.saturation.", dpy);
|
||
if (property_get(propertyStr.c_str(), mBcshProperty, NULL) > 0) {
|
||
bcshs[2] = atoi(mBcshProperty);
|
||
} else if (mBaseParmeter&&mBaseParmeter->have_baseparameter()) {
|
||
bcshs[2] = mBaseParmeter->get_contrast(conn->get_type(), conn->connector_id());
|
||
} else {
|
||
bcshs[2] = DEFAULT_SATURATION;
|
||
}
|
||
|
||
memset(mBcshProperty, 0, sizeof(mBcshProperty));
|
||
propertyStr = getPropertySuffix(priv, "persist.vendor.hue.", dpy);
|
||
if (property_get(propertyStr.c_str(), mBcshProperty, NULL) > 0) {
|
||
bcshs[3] = atoi(mBcshProperty);
|
||
} else if (mBaseParmeter&&mBaseParmeter->have_baseparameter()) {
|
||
bcshs[3] = mBaseParmeter->get_hue(conn->get_type(), conn->connector_id());
|
||
} else {
|
||
bcshs[3] = DEFAULT_SATURATION;
|
||
}
|
||
|
||
checkBcshInfo(bcshs);
|
||
ALOGD("Bcsh: %d %d %d %d ", bcshs[0], bcshs[1], bcshs[2], bcshs[3]);
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_get_builtin(struct hw_output_device* dev, int dpy, int* builtin)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
DrmConnector* mConnector = getValidDrmConnector(priv, dpy);
|
||
if (mConnector) {
|
||
*builtin = mConnector->get_type();
|
||
} else {
|
||
*builtin = 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static drm_mode_t* hw_output_get_display_modes(struct hw_output_device* dev, int dpy, uint32_t* size)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
std::vector<DrmMode> mModes;
|
||
DrmConnector* mCurConnector;
|
||
drm_mode_t* drm_modes = NULL;
|
||
int idx=0;
|
||
|
||
*size = 0;
|
||
mCurConnector = getValidDrmConnector(priv, dpy);
|
||
if (mCurConnector) {
|
||
mModes = mCurConnector->modes();
|
||
} else {
|
||
return NULL;
|
||
}
|
||
|
||
if (mModes.size() == 0)
|
||
return NULL;
|
||
|
||
drm_modes = (drm_mode_t*)malloc(sizeof(drm_mode_t) * mModes.size());
|
||
|
||
for (size_t c = 0; c < mModes.size(); ++c) {
|
||
const DrmMode& info = mModes[c];
|
||
float vfresh;
|
||
|
||
if (info.flags() & DRM_MODE_FLAG_INTERLACE)
|
||
vfresh = info.clock()*2 / (float)(info.v_total()* info.h_total()) * 1000.0f;
|
||
else
|
||
vfresh = info.clock()/ (float)(info.v_total()* info.h_total()) * 1000.0f;
|
||
drm_modes[c].width = info.h_display();
|
||
drm_modes[c].height = info.v_display();
|
||
drm_modes[c].refreshRate = vfresh;
|
||
drm_modes[c].clock = info.clock();
|
||
drm_modes[c].flags = info.flags();
|
||
drm_modes[c].interlaceFlag = info.flags()&(1<<4);
|
||
drm_modes[c].yuvFlag = (info.flags()&(1<<24) || info.flags()&(1<<23));
|
||
drm_modes[c].connectorId = mCurConnector->id();
|
||
drm_modes[c].mode_type = info.type();
|
||
drm_modes[c].idx = idx;
|
||
drm_modes[c].hsync_start = info.h_sync_start();
|
||
drm_modes[c].hsync_end = info.h_sync_end();
|
||
drm_modes[c].htotal = info.h_total();
|
||
drm_modes[c].hskew = info.h_skew();
|
||
drm_modes[c].vsync_start = info.v_sync_start();
|
||
drm_modes[c].vsync_end = info.v_sync_end();
|
||
drm_modes[c].vtotal = info.v_total();
|
||
drm_modes[c].vscan = info.v_scan();
|
||
idx++;
|
||
ALOGV("display%d mode[%d] %dx%d fps %f clk %d h_start %d h_enc %d htotal %d hskew %d",
|
||
dpy,(int)c, info.h_display(), info.v_display(), info.v_refresh(),
|
||
info.clock(), info.h_sync_start(),info.h_sync_end(),
|
||
info.h_total(), info.h_skew());
|
||
ALOGV("vsync_start %d vsync_end %d vtotal %d vscan %d flags 0x%x",
|
||
info.v_sync_start(), info.v_sync_end(), info.v_total(), info.v_scan(),
|
||
info.flags());
|
||
}
|
||
*size = idx;
|
||
return drm_modes;
|
||
}
|
||
|
||
/*****************************************************************************/
|
||
static int hw_output_device_close(struct hw_device_t *dev)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
|
||
if (priv->mBaseParmeter) {
|
||
delete priv->mBaseParmeter;
|
||
}
|
||
if (priv) {
|
||
free(priv);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static connector_info_t* hw_output_get_connector_info(struct hw_output_device* dev, uint32_t* size)
|
||
{
|
||
hw_output_private_t* priv = (hw_output_private_t*)dev;
|
||
*size = 0;
|
||
connector_info_t* connector_info = NULL;
|
||
connector_info = (connector_info_t*)malloc(sizeof(connector_info_t) * priv->drm_->connectors().size());
|
||
int i = 0;
|
||
for (auto &conn : mGlobalConns) {
|
||
DrmConnector* mConn = conn.second;
|
||
connector_info[i].type = mConn->get_type();
|
||
connector_info[i].id = (uint32_t)mConn->connector_id();
|
||
connector_info[i].state = (uint32_t)mConn->state();
|
||
i++;
|
||
}
|
||
*size = i;
|
||
ALOGE("%s:%d i=%d", __FUNCTION__, __LINE__, i);
|
||
return connector_info;
|
||
}
|
||
|
||
static int hw_output_get_mode_state(struct hw_output_device *, const char* mode, char *state)
|
||
{
|
||
property_get(mode, state, "");
|
||
ALOGD("%s:%d mode = %s, state = %s\n", __FUNCTION__, __LINE__, mode, state);
|
||
return 0;
|
||
}
|
||
|
||
static int hw_output_set_mode_state(struct hw_output_device *, const char* mode, const char* state)
|
||
{
|
||
int ret = property_set(mode, state);
|
||
updateTimeline();
|
||
ALOGD("%s:%d mode = %s, state = %s, ret = %d\n", __FUNCTION__, __LINE__, mode, state, ret);
|
||
return ret;
|
||
}
|
||
|
||
static int hw_output_get_hdr_resolution_supported(struct hw_output_device *dev, int dpy, const char *mode, uint32_t* hdr_state)
|
||
{
|
||
hw_output_private_t *priv = (hw_output_private_t *)dev;
|
||
DrmConnector *mCurConnector = getValidDrmConnector(priv, dpy);
|
||
drmModeObjectPropertiesPtr props;
|
||
drmModePropertyBlobPtr blob;
|
||
struct hdr_static_metadata* blob_data = nullptr;
|
||
bool found = false;
|
||
int value;
|
||
|
||
*hdr_state = 0;
|
||
|
||
if (mCurConnector == NULL)
|
||
return -1;
|
||
props = drmModeObjectGetProperties(priv->drm_->fd(), mCurConnector->id(), DRM_MODE_OBJECT_CONNECTOR);
|
||
for (int i = 0; !found && (size_t)i < props->count_props; ++i)
|
||
{
|
||
drmModePropertyPtr p = drmModeGetProperty(priv->drm_->fd(), props->props[i]);
|
||
if (p && !strcmp(p->name, "HDR_PANEL_METADATA"))
|
||
{
|
||
if (!drm_property_type_is(p, DRM_MODE_PROP_BLOB))
|
||
{
|
||
ALOGE("%s:%d HDR_PANEL_METADATA property is not blob type", __FUNCTION__, __LINE__);
|
||
drmModeFreeProperty(p);
|
||
drmModeFreeObjectProperties(props);
|
||
return -1;
|
||
}
|
||
|
||
if (!p->count_blobs)
|
||
value = props->prop_values[i];
|
||
else
|
||
value = p->blob_ids[0];
|
||
|
||
blob = drmModeGetPropertyBlob(priv->drm_->fd(), value);
|
||
if (!blob)
|
||
{
|
||
ALOGE("%s:line=%d, blob is null", __FUNCTION__, __LINE__);
|
||
drmModeFreeProperty(p);
|
||
drmModeFreeObjectProperties(props);
|
||
return -1;
|
||
}
|
||
|
||
blob_data = (struct hdr_static_metadata *)blob->data;
|
||
found = true;
|
||
*hdr_state = blob_data->eotf & HW_OUTPUT_VALUE_HDR10_MASK ? *hdr_state | HW_OUTPUT_FOR_FRAMEWORK_HDR10_MASK : *hdr_state;
|
||
*hdr_state = blob_data->eotf & HW_OUTPUT_VALUE_HLG_MASK ? *hdr_state | HW_OUTPUT_FOR_FRAMEWORK_HLG_MASK : *hdr_state;
|
||
ALOGD("%s:%d HDR_PANEL_METADATA property is found , mode = %s, hdr_static_metadata.eotf = %d, hdr_state = %d", __FUNCTION__, __LINE__, mode, blob_data->eotf, *hdr_state);
|
||
|
||
drmModeFreePropertyBlob(blob);
|
||
}
|
||
drmModeFreeProperty(p);
|
||
if (found)
|
||
break;
|
||
}
|
||
drmModeFreeObjectProperties(props);
|
||
return found ? 0 : -1;
|
||
}
|
||
|
||
static int hw_output_device_open(const struct hw_module_t* module,
|
||
const char* name, struct hw_device_t** device)
|
||
{
|
||
int status = -EINVAL;
|
||
if (!strcmp(name, HW_OUTPUT_DEFAULT_DEVICE)) {
|
||
hw_output_private_t* dev = (hw_output_private_t*)malloc(sizeof(*dev));
|
||
|
||
/* initialize our state here */
|
||
//memset(dev, 0, sizeof(*dev));
|
||
|
||
/* initialize the procs */
|
||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||
dev->device.common.version = HW_OUTPUT_DEVICE_API_VERSION_0_1;
|
||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||
dev->device.common.close = hw_output_device_close;
|
||
|
||
dev->device.initialize = hw_output_initialize;
|
||
dev->device.setMode = hw_output_set_mode;
|
||
dev->device.set3DMode = hw_output_set_3d_mode;
|
||
dev->device.setBrightness = hw_output_set_brightness;
|
||
dev->device.setContrast = hw_output_set_contrast;
|
||
dev->device.setSat = hw_output_set_sat;
|
||
dev->device.setHue = hw_output_set_hue;
|
||
dev->device.setColorMode = hw_output_set_color_mode;
|
||
dev->device.setHdrMode = hw_output_set_hdr_mode;
|
||
dev->device.setGamma = hw_output_set_gamma;
|
||
dev->device.setScreenScale = hw_output_set_screen_scale;
|
||
|
||
dev->device.getCurColorMode = hw_output_get_cur_color_mode;
|
||
dev->device.getBcsh = hw_output_get_bcsh;
|
||
dev->device.getBuiltIn = hw_output_get_builtin;
|
||
dev->device.getColorConfigs = hw_output_get_color_configs;
|
||
dev->device.getConnectorState = hw_output_get_connector_state;
|
||
dev->device.getCurMode = hw_output_get_cur_mode;
|
||
dev->device.getDisplayModes = hw_output_get_display_modes;
|
||
dev->device.getNumConnectors = hw_output_get_num_connectors;
|
||
dev->device.getOverscan = hw_output_get_overscan;
|
||
|
||
dev->device.hotplug = hw_output_hotplug_update;
|
||
dev->device.saveConfig = hw_output_save_config;
|
||
dev->device.set3DLut = hw_output_set_3d_lut;
|
||
dev->device.getConnectorInfo = hw_output_get_connector_info;
|
||
dev->device.updateDispHeader = hw_output_update_disp_header;
|
||
dev->device.getModeState = hw_output_get_mode_state;
|
||
dev->device.setModeState = hw_output_set_mode_state;
|
||
dev->device.getHdrResolutionSupported = hw_output_get_hdr_resolution_supported;
|
||
*device = &dev->device.common;
|
||
status = 0;
|
||
}
|
||
return status;
|
||
}
|