|
|
/* |
|
|
// Copyright (c) 2014 Intel Corporation |
|
|
// |
|
|
// 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 <fcntl.h> |
|
|
#include <errno.h> |
|
|
#include <HwcTrace.h> |
|
|
#include <IDisplayDevice.h> |
|
|
#include <DrmConfig.h> |
|
|
#include <Drm.h> |
|
|
#include <Hwcomposer.h> |
|
|
|
|
|
namespace android { |
|
|
namespace intel { |
|
|
|
|
|
Drm::Drm() |
|
|
: mDrmFd(0), |
|
|
mLock(), |
|
|
mInitialized(false) |
|
|
{ |
|
|
memset(&mOutputs, 0, sizeof(mOutputs)); |
|
|
} |
|
|
|
|
|
Drm::~Drm() |
|
|
{ |
|
|
WARN_IF_NOT_DEINIT(); |
|
|
} |
|
|
|
|
|
bool Drm::initialize() |
|
|
{ |
|
|
if (mInitialized) { |
|
|
WTRACE("Drm object has been initialized"); |
|
|
return true; |
|
|
} |
|
|
|
|
|
const char *path = DrmConfig::getDrmPath(); |
|
|
mDrmFd = open(path, O_RDWR, 0); |
|
|
if (mDrmFd < 0) { |
|
|
ETRACE("failed to open Drm, error: %s", strerror(errno)); |
|
|
return false; |
|
|
} |
|
|
DTRACE("mDrmFd = %d", mDrmFd); |
|
|
|
|
|
memset(&mOutputs, 0, sizeof(mOutputs)); |
|
|
mInitialized = true; |
|
|
return true; |
|
|
} |
|
|
|
|
|
void Drm::deinitialize() |
|
|
{ |
|
|
for (int i = 0; i < OUTPUT_MAX; i++) { |
|
|
resetOutput(i); |
|
|
} |
|
|
|
|
|
if (mDrmFd) { |
|
|
close(mDrmFd); |
|
|
mDrmFd = 0; |
|
|
} |
|
|
mInitialized = false; |
|
|
} |
|
|
|
|
|
bool Drm::detect(int device) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
|
|
|
Mutex::Autolock _l(mLock); |
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0 ) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
resetOutput(outputIndex); |
|
|
|
|
|
// get drm resources |
|
|
drmModeResPtr resources = drmModeGetResources(mDrmFd); |
|
|
if (!resources) { |
|
|
ETRACE("fail to get drm resources, error: %s", strerror(errno)); |
|
|
return false; |
|
|
} |
|
|
|
|
|
drmModeConnectorPtr connector = NULL; |
|
|
DrmOutput *output = &mOutputs[outputIndex]; |
|
|
bool ret = false; |
|
|
|
|
|
// find connector for the given device |
|
|
for (int i = 0; i < resources->count_connectors; i++) { |
|
|
if (!resources->connectors || !resources->connectors[i]) { |
|
|
ETRACE("fail to get drm resources connectors, error: %s", strerror(errno)); |
|
|
continue; |
|
|
} |
|
|
|
|
|
connector = drmModeGetConnector(mDrmFd, resources->connectors[i]); |
|
|
if (!connector) { |
|
|
ETRACE("drmModeGetConnector failed"); |
|
|
continue; |
|
|
} |
|
|
|
|
|
if (connector->connector_type != DrmConfig::getDrmConnector(device)) { |
|
|
drmModeFreeConnector(connector); |
|
|
continue; |
|
|
} |
|
|
|
|
|
if (connector->connection != DRM_MODE_CONNECTED) { |
|
|
ITRACE("device %d is not connected", device); |
|
|
drmModeFreeConnector(connector); |
|
|
ret = true; |
|
|
break; |
|
|
} |
|
|
|
|
|
output->connector = connector; |
|
|
output->connected = true; |
|
|
|
|
|
// get proper encoder for the given connector |
|
|
if (connector->encoder_id) { |
|
|
ITRACE("Drm connector has encoder attached on device %d", device); |
|
|
output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id); |
|
|
if (!output->encoder) { |
|
|
ETRACE("failed to get encoder from a known encoder id"); |
|
|
// fall through to get an encoder |
|
|
} |
|
|
} |
|
|
if (!output->encoder) { |
|
|
ITRACE("getting encoder for device %d", device); |
|
|
drmModeEncoderPtr encoder; |
|
|
for (int j = 0; j < resources->count_encoders; j++) { |
|
|
if (!resources->encoders || !resources->encoders[j]) { |
|
|
ETRACE("fail to get drm resources encoders, error: %s", strerror(errno)); |
|
|
continue; |
|
|
} |
|
|
|
|
|
encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]); |
|
|
if (!encoder) { |
|
|
ETRACE("drmModeGetEncoder failed"); |
|
|
continue; |
|
|
} |
|
|
if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) { |
|
|
output->encoder = encoder; |
|
|
break; |
|
|
} |
|
|
drmModeFreeEncoder(encoder); |
|
|
encoder = NULL; |
|
|
} |
|
|
} |
|
|
if (!output->encoder) { |
|
|
ETRACE("failed to get drm encoder"); |
|
|
break; |
|
|
} |
|
|
|
|
|
// get an attached crtc or spare crtc |
|
|
if (output->encoder->crtc_id) { |
|
|
ITRACE("Drm encoder has crtc attached on device %d", device); |
|
|
output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id); |
|
|
if (!output->crtc) { |
|
|
ETRACE("failed to get crtc from a known crtc id"); |
|
|
// fall through to get a spare crtc |
|
|
} |
|
|
} |
|
|
if (!output->crtc) { |
|
|
ITRACE("getting crtc for device %d", device); |
|
|
drmModeCrtcPtr crtc; |
|
|
for (int j = 0; j < resources->count_crtcs; j++) { |
|
|
if (!resources->crtcs || !resources->crtcs[j]) { |
|
|
ETRACE("fail to get drm resources crtcs, error: %s", strerror(errno)); |
|
|
continue; |
|
|
} |
|
|
|
|
|
crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]); |
|
|
if (!crtc) { |
|
|
ETRACE("drmModeGetCrtc failed"); |
|
|
continue; |
|
|
} |
|
|
if (crtc->buffer_id == 0) { |
|
|
output->crtc = crtc; |
|
|
break; |
|
|
} |
|
|
drmModeFreeCrtc(crtc); |
|
|
} |
|
|
} |
|
|
if (!output->crtc) { |
|
|
ETRACE("failed to get drm crtc"); |
|
|
break; |
|
|
} |
|
|
|
|
|
// current mode |
|
|
if (output->crtc->mode_valid) { |
|
|
ITRACE("mode is valid, kernel mode settings"); |
|
|
memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo)); |
|
|
ret = true; |
|
|
} else { |
|
|
ITRACE("mode is invalid, setting preferred mode"); |
|
|
ret = initDrmMode(outputIndex); |
|
|
} |
|
|
|
|
|
if (outputIndex == OUTPUT_PRIMARY) { |
|
|
if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) { |
|
|
ETRACE("failed to get device %d orientation", device); |
|
|
output->panelOrientation = PANEL_ORIENTATION_0; |
|
|
} |
|
|
} else { |
|
|
output->panelOrientation = PANEL_ORIENTATION_0; |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
|
if (!ret) { |
|
|
if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) { |
|
|
// a fatal failure on primary device |
|
|
// non fatal on secondary device |
|
|
WTRACE("device %d is disabled?", device); |
|
|
ret = true; |
|
|
} |
|
|
resetOutput(outputIndex); |
|
|
} else if (output->connected) { |
|
|
ITRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh); |
|
|
} |
|
|
|
|
|
drmModeFreeResources(resources); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
bool Drm::isSameDrmMode(drmModeModeInfoPtr value, |
|
|
drmModeModeInfoPtr base) const |
|
|
{ |
|
|
if (base->hdisplay == value->hdisplay && |
|
|
base->vdisplay == value->vdisplay && |
|
|
base->vrefresh == value->vrefresh && |
|
|
(base->flags & value->flags) == value->flags) { |
|
|
VTRACE("Drm mode is not changed"); |
|
|
return true; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
bool Drm::setDrmMode(int device, drmModeModeInfo& value) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
if (device != IDisplayDevice::DEVICE_EXTERNAL) { |
|
|
WTRACE("Setting mode on invalid device %d", device); |
|
|
return false; |
|
|
} |
|
|
|
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0 ) { |
|
|
ETRACE("invalid device"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (!output->connected) { |
|
|
ETRACE("device is not connected"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (output->connector->count_modes <= 0) { |
|
|
ETRACE("invalid count of modes"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
drmModeModeInfoPtr mode; |
|
|
int index = 0; |
|
|
for (int i = 0; i < output->connector->count_modes; i++) { |
|
|
mode = &output->connector->modes[i]; |
|
|
if (mode->type & DRM_MODE_TYPE_PREFERRED) { |
|
|
index = i; |
|
|
} |
|
|
if (isSameDrmMode(&value, mode)) { |
|
|
index = i; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
mode = &output->connector->modes[index]; |
|
|
return setDrmMode(outputIndex, mode); |
|
|
} |
|
|
|
|
|
bool Drm::setRefreshRate(int device, int hz) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
if (device != IDisplayDevice::DEVICE_EXTERNAL) { |
|
|
WTRACE("Setting mode on invalid device %d", device); |
|
|
return false; |
|
|
} |
|
|
|
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0 ) { |
|
|
ETRACE("invalid device"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (!output->connected) { |
|
|
ETRACE("device is not connected"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (output->connector->count_modes <= 0) { |
|
|
ETRACE("invalid count of modes"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
drmModeModeInfoPtr mode; |
|
|
int index = 0; |
|
|
for (int i = 0; i < output->connector->count_modes; i++) { |
|
|
mode = &output->connector->modes[i]; |
|
|
if (mode->type & DRM_MODE_TYPE_PREFERRED) { |
|
|
index = i; |
|
|
} |
|
|
if (mode->hdisplay == output->mode.hdisplay && |
|
|
mode->vdisplay == output->mode.vdisplay && |
|
|
mode->vrefresh == (uint32_t)hz) { |
|
|
index = i; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
mode = &output->connector->modes[index]; |
|
|
return setDrmMode(outputIndex, mode); |
|
|
} |
|
|
|
|
|
bool Drm::writeReadIoctl(unsigned long cmd, void *data, |
|
|
unsigned long size) |
|
|
{ |
|
|
int err; |
|
|
|
|
|
if (mDrmFd <= 0) { |
|
|
ETRACE("drm is not initialized"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (!data || !size) { |
|
|
ETRACE("invalid parameters"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
err = drmCommandWriteRead(mDrmFd, cmd, data, size); |
|
|
if (err) { |
|
|
WTRACE("failed to call %ld ioctl with failure %d", cmd, err); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool Drm::writeIoctl(unsigned long cmd, void *data, |
|
|
unsigned long size) |
|
|
{ |
|
|
int err; |
|
|
|
|
|
if (mDrmFd <= 0) { |
|
|
ETRACE("drm is not initialized"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (!data || !size) { |
|
|
ETRACE("invalid parameters"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
err = drmCommandWrite(mDrmFd, cmd, data, size); |
|
|
if (err) { |
|
|
WTRACE("failed to call %ld ioctl with failure %d", cmd, err); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
bool Drm::readIoctl(unsigned long cmd, void *data, |
|
|
unsigned long size) |
|
|
{ |
|
|
int err; |
|
|
|
|
|
if (mDrmFd <= 0) { |
|
|
ETRACE("drm is not initialized"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (!data || !size) { |
|
|
ETRACE("invalid parameters"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
err = drmCommandRead(mDrmFd, cmd, data, size); |
|
|
if (err) { |
|
|
WTRACE("failed to call %ld ioctl with failure %d", cmd, err); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
int Drm::getDrmFd() const |
|
|
{ |
|
|
return mDrmFd; |
|
|
} |
|
|
|
|
|
bool Drm::getModeInfo(int device, drmModeModeInfo& mode) |
|
|
{ |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0 ) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (output->connected == false) { |
|
|
ETRACE("device is not connected"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) { |
|
|
ETRACE("invalid width or height"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
memcpy(&mode, &output->mode, sizeof(drmModeModeInfo)); |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height) |
|
|
{ |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0 ) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (output->connected == false) { |
|
|
ETRACE("device is not connected"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
width = output->connector->mmWidth; |
|
|
height = output->connector->mmHeight; |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool Drm::isConnected(int device) |
|
|
{ |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
int output = getOutputIndex(device); |
|
|
if (output < 0 ) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
return mOutputs[output].connected; |
|
|
} |
|
|
|
|
|
bool Drm::setDpmsMode(int device, int mode) |
|
|
{ |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
int output = getOutputIndex(device); |
|
|
if (output < 0 ) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF && |
|
|
mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY && |
|
|
mode != IDisplayDevice::DEVICE_DISPLAY_ON) { |
|
|
ETRACE("invalid mode %d", mode); |
|
|
return false; |
|
|
} |
|
|
|
|
|
DrmOutput *out = &mOutputs[output]; |
|
|
if (!out->connected) { |
|
|
ETRACE("device is not connected"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
drmModePropertyPtr props; |
|
|
for (int i = 0; i < out->connector->count_props; i++) { |
|
|
props = drmModeGetProperty(mDrmFd, out->connector->props[i]); |
|
|
if (!props) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
if (strcmp(props->name, "DPMS") == 0) { |
|
|
int ret = drmModeConnectorSetProperty( |
|
|
mDrmFd, |
|
|
out->connector->connector_id, |
|
|
props->prop_id, |
|
|
(mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON : |
|
|
IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ? |
|
|
DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF); |
|
|
drmModeFreeProperty(props); |
|
|
if (ret != 0) { |
|
|
ETRACE("unable to set DPMS %d", mode); |
|
|
return false; |
|
|
} else { |
|
|
return true; |
|
|
} |
|
|
} |
|
|
drmModeFreeProperty(props); |
|
|
} |
|
|
return false; |
|
|
} |
|
|
|
|
|
void Drm::resetOutput(int index) |
|
|
{ |
|
|
DrmOutput *output = &mOutputs[index]; |
|
|
|
|
|
output->connected = false; |
|
|
memset(&output->mode, 0, sizeof(drmModeModeInfo)); |
|
|
|
|
|
if (output->connector) { |
|
|
drmModeFreeConnector(output->connector); |
|
|
output->connector = 0; |
|
|
} |
|
|
if (output->encoder) { |
|
|
drmModeFreeEncoder(output->encoder); |
|
|
output->encoder = 0; |
|
|
} |
|
|
if (output->crtc) { |
|
|
drmModeFreeCrtc(output->crtc); |
|
|
output->crtc = 0; |
|
|
} |
|
|
if (output->fbId) { |
|
|
drmModeRmFB(mDrmFd, output->fbId); |
|
|
output->fbId = 0; |
|
|
} |
|
|
if (output->fbHandle) { |
|
|
Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer( |
|
|
(buffer_handle_t)output->fbHandle); |
|
|
output->fbHandle = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
bool Drm::initDrmMode(int outputIndex) |
|
|
{ |
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (output->connector->count_modes <= 0) { |
|
|
ETRACE("invalid count of modes"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
drmModeModeInfoPtr mode; |
|
|
int index = 0; |
|
|
for (int i = 0; i < output->connector->count_modes; i++) { |
|
|
mode = &output->connector->modes[i]; |
|
|
if (mode->type & DRM_MODE_TYPE_PREFERRED) { |
|
|
index = i; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
return setDrmMode(outputIndex, &output->connector->modes[index]); |
|
|
} |
|
|
|
|
|
bool Drm::setDrmMode(int index, drmModeModeInfoPtr mode) |
|
|
{ |
|
|
DrmOutput *output = &mOutputs[index]; |
|
|
|
|
|
int oldFbId =0; |
|
|
buffer_handle_t oldFbHandle = 0; |
|
|
|
|
|
drmModeModeInfo currentMode; |
|
|
memcpy(¤tMode, &output->mode, sizeof(drmModeModeInfo)); |
|
|
|
|
|
if (isSameDrmMode(mode, ¤tMode)) |
|
|
return true; |
|
|
|
|
|
|
|
|
if (output->fbId) { |
|
|
oldFbId = output->fbId; |
|
|
output->fbId = 0; |
|
|
} |
|
|
|
|
|
if (output->fbHandle) { |
|
|
oldFbHandle = output->fbHandle; |
|
|
output->fbHandle = 0; |
|
|
} |
|
|
|
|
|
// allocate frame buffer |
|
|
int stride = 0; |
|
|
output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer( |
|
|
mode->hdisplay, mode->vdisplay, &stride); |
|
|
if (output->fbHandle == 0) { |
|
|
ETRACE("failed to allocate frame buffer"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
uint32_t bo_handles[4] = {0}; |
|
|
uint32_t pitches[4] = {0}; |
|
|
uint32_t offsets[4] = {0}; |
|
|
int ret = 0; |
|
|
|
|
|
// We use bo_handles[0] and bo_handles[1] to store buffer_handle_t |
|
|
// to support 32 and 64 platforms. |
|
|
bo_handles[0] = ((unsigned long)(output->fbHandle)) & 0xffffffff; |
|
|
bo_handles[1] = ((unsigned long)(output->fbHandle) >> 32) & 0xffffffff; |
|
|
pitches[0] = stride * DrmConfig::getFrameBufferBpp() / 8; |
|
|
|
|
|
ret = drmModeAddFB2( |
|
|
mDrmFd, |
|
|
mode->hdisplay, |
|
|
mode->vdisplay, |
|
|
DrmConfig::convertHalFormatToDrmFormat(DrmConfig::getFrameBufferFormat()), |
|
|
bo_handles, |
|
|
pitches, |
|
|
offsets, |
|
|
&output->fbId, |
|
|
0); |
|
|
if (ret != 0) { |
|
|
ETRACE("drmModeAddFB2 failed, error: %d", ret); |
|
|
return false; |
|
|
} |
|
|
|
|
|
ITRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh); |
|
|
|
|
|
ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, output->fbId, 0, 0, |
|
|
&output->connector->connector_id, 1, mode); |
|
|
if (ret == 0) { |
|
|
//save mode |
|
|
memcpy(&output->mode, mode, sizeof(drmModeModeInfo)); |
|
|
} else { |
|
|
ETRACE("drmModeSetCrtc failed. error: %d", ret); |
|
|
} |
|
|
|
|
|
if (oldFbId) { |
|
|
drmModeRmFB(mDrmFd, oldFbId); |
|
|
} |
|
|
|
|
|
if (oldFbHandle) { |
|
|
Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer((buffer_handle_t)oldFbHandle); |
|
|
} |
|
|
|
|
|
return ret == 0; |
|
|
} |
|
|
|
|
|
int Drm::getOutputIndex(int device) |
|
|
{ |
|
|
switch (device) { |
|
|
case IDisplayDevice::DEVICE_PRIMARY: |
|
|
return OUTPUT_PRIMARY; |
|
|
case IDisplayDevice::DEVICE_EXTERNAL: |
|
|
return OUTPUT_EXTERNAL; |
|
|
default: |
|
|
ETRACE("invalid display device"); |
|
|
break; |
|
|
} |
|
|
|
|
|
return -1; |
|
|
} |
|
|
|
|
|
int Drm::getPanelOrientation(int device) |
|
|
{ |
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0) { |
|
|
ETRACE("invalid device"); |
|
|
return PANEL_ORIENTATION_0; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (output->connected == false) { |
|
|
ETRACE("device is not connected"); |
|
|
return PANEL_ORIENTATION_0; |
|
|
} |
|
|
|
|
|
return output->panelOrientation; |
|
|
} |
|
|
|
|
|
// HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs |
|
|
// this is needed so getActiveConfig/setActiveConfig work correctly. It is up to the |
|
|
// user space to decide what speed to send. |
|
|
drmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount) |
|
|
{ |
|
|
RETURN_NULL_IF_NOT_INIT(); |
|
|
Mutex::Autolock _l(mLock); |
|
|
|
|
|
if (modeCount != NULL) |
|
|
*modeCount = 0; |
|
|
else |
|
|
return NULL; |
|
|
|
|
|
int outputIndex = getOutputIndex(device); |
|
|
if (outputIndex < 0) { |
|
|
ETRACE("invalid device"); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
DrmOutput *output= &mOutputs[outputIndex]; |
|
|
if (!output->connected) { |
|
|
ETRACE("device is not connected"); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
if (output->connector->count_modes <= 0) { |
|
|
ETRACE("invalid count of modes"); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
*modeCount = output->connector->count_modes; |
|
|
return output->connector->modes; |
|
|
} |
|
|
|
|
|
} // namespace intel |
|
|
} // namespace android |
|
|
|
|
|
|