nvidia-open-gpu-kernel-modules/kernel-open/nvidia-drm/nvidia-drm-utils.c

232 lines
7.3 KiB
C

/*
* Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "nvidia-drm-conftest.h" /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
#if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
#if defined(NV_DRM_DRMP_H_PRESENT)
#include <drm/drmP.h>
#endif
#if defined(NV_DRM_DRM_PLANE_H_PRESENT)
#include <drm/drm_plane.h>
#endif
#include <drm/drm_modes.h>
#include <uapi/drm/drm_fourcc.h>
#include "nvidia-drm-priv.h"
#include "nvidia-drm-utils.h"
struct NvKmsKapiConnectorInfo*
nvkms_get_connector_info(struct NvKmsKapiDevice *pDevice,
NvKmsKapiConnector hConnector)
{
struct NvKmsKapiConnectorInfo *connectorInfo =
nv_drm_calloc(1, sizeof(*connectorInfo));
if (connectorInfo == NULL) {
return ERR_PTR(-ENOMEM);
}
if (!nvKms->getConnectorInfo(pDevice, hConnector, connectorInfo)) {
nv_drm_free(connectorInfo);
return ERR_PTR(-EINVAL);
}
return connectorInfo;
}
int
nvkms_connector_signal_to_drm_encoder_signal(NvKmsConnectorSignalFormat format)
{
switch (format) {
default:
case NVKMS_CONNECTOR_SIGNAL_FORMAT_UNKNOWN:
return DRM_MODE_ENCODER_NONE;
case NVKMS_CONNECTOR_SIGNAL_FORMAT_TMDS:
case NVKMS_CONNECTOR_SIGNAL_FORMAT_DP:
return DRM_MODE_ENCODER_TMDS;
case NVKMS_CONNECTOR_SIGNAL_FORMAT_LVDS:
return DRM_MODE_ENCODER_LVDS;
case NVKMS_CONNECTOR_SIGNAL_FORMAT_VGA:
return DRM_MODE_ENCODER_DAC;
case NVKMS_CONNECTOR_SIGNAL_FORMAT_DSI:
return DRM_MODE_ENCODER_DSI;
}
}
int nvkms_connector_type_to_drm_connector_type(NvKmsConnectorType type,
NvBool internal)
{
switch (type) {
default:
case NVKMS_CONNECTOR_TYPE_UNKNOWN:
return DRM_MODE_CONNECTOR_Unknown;
case NVKMS_CONNECTOR_TYPE_DP:
return
internal ?
DRM_MODE_CONNECTOR_eDP : DRM_MODE_CONNECTOR_DisplayPort;
case NVKMS_CONNECTOR_TYPE_HDMI:
return DRM_MODE_CONNECTOR_HDMIA;
case NVKMS_CONNECTOR_TYPE_DVI_D:
return DRM_MODE_CONNECTOR_DVID;
case NVKMS_CONNECTOR_TYPE_DVI_I:
return DRM_MODE_CONNECTOR_DVII;
case NVKMS_CONNECTOR_TYPE_LVDS:
return DRM_MODE_CONNECTOR_LVDS;
case NVKMS_CONNECTOR_TYPE_VGA:
return DRM_MODE_CONNECTOR_VGA;
case NVKMS_CONNECTOR_TYPE_DSI:
return DRM_MODE_CONNECTOR_DSI;
case NVKMS_CONNECTOR_TYPE_DP_SERIALIZER:
return DRM_MODE_CONNECTOR_DisplayPort;
}
}
void
nvkms_display_mode_to_drm_mode(const struct NvKmsKapiDisplayMode *displayMode,
struct drm_display_mode *mode)
{
#if defined(NV_DRM_DISPLAY_MODE_HAS_VREFRESH)
mode->vrefresh = (displayMode->timings.refreshRate + 500) / 1000; /* In Hz */
#endif
mode->clock = (displayMode->timings.pixelClockHz + 500) / 1000; /* In Hz */
mode->hdisplay = displayMode->timings.hVisible;
mode->hsync_start = displayMode->timings.hSyncStart;
mode->hsync_end = displayMode->timings.hSyncEnd;
mode->htotal = displayMode->timings.hTotal;
mode->hskew = displayMode->timings.hSkew;
mode->vdisplay = displayMode->timings.vVisible;
mode->vsync_start = displayMode->timings.vSyncStart;
mode->vsync_end = displayMode->timings.vSyncEnd;
mode->vtotal = displayMode->timings.vTotal;
if (displayMode->timings.flags.interlaced) {
mode->flags |= DRM_MODE_FLAG_INTERLACE;
}
if (displayMode->timings.flags.doubleScan) {
mode->flags |= DRM_MODE_FLAG_DBLSCAN;
}
if (displayMode->timings.flags.hSyncPos) {
mode->flags |= DRM_MODE_FLAG_PHSYNC;
}
if (displayMode->timings.flags.hSyncNeg) {
mode->flags |= DRM_MODE_FLAG_NHSYNC;
}
if (displayMode->timings.flags.vSyncPos) {
mode->flags |= DRM_MODE_FLAG_PVSYNC;
}
if (displayMode->timings.flags.vSyncNeg) {
mode->flags |= DRM_MODE_FLAG_NVSYNC;
}
mode->width_mm = displayMode->timings.widthMM;
mode->height_mm = displayMode->timings.heightMM;
if (strlen(displayMode->name) != 0) {
memcpy(
mode->name, displayMode->name,
min(sizeof(mode->name), sizeof(displayMode->name)));
mode->name[sizeof(mode->name) - 1] = '\0';
} else {
drm_mode_set_name(mode);
}
}
void drm_mode_to_nvkms_display_mode(const struct drm_display_mode *src,
struct NvKmsKapiDisplayMode *dst)
{
#if defined(NV_DRM_DISPLAY_MODE_HAS_VREFRESH)
dst->timings.refreshRate = src->vrefresh * 1000;
#else
dst->timings.refreshRate = drm_mode_vrefresh(src) * 1000;
#endif
dst->timings.pixelClockHz = src->clock * 1000; /* In Hz */
dst->timings.hVisible = src->hdisplay;
dst->timings.hSyncStart = src->hsync_start;
dst->timings.hSyncEnd = src->hsync_end;
dst->timings.hTotal = src->htotal;
dst->timings.hSkew = src->hskew;
dst->timings.vVisible = src->vdisplay;
dst->timings.vSyncStart = src->vsync_start;
dst->timings.vSyncEnd = src->vsync_end;
dst->timings.vTotal = src->vtotal;
if (src->flags & DRM_MODE_FLAG_INTERLACE) {
dst->timings.flags.interlaced = NV_TRUE;
} else {
dst->timings.flags.interlaced = NV_FALSE;
}
if (src->flags & DRM_MODE_FLAG_DBLSCAN) {
dst->timings.flags.doubleScan = NV_TRUE;
} else {
dst->timings.flags.doubleScan = NV_FALSE;
}
if (src->flags & DRM_MODE_FLAG_PHSYNC) {
dst->timings.flags.hSyncPos = NV_TRUE;
} else {
dst->timings.flags.hSyncPos = NV_FALSE;
}
if (src->flags & DRM_MODE_FLAG_NHSYNC) {
dst->timings.flags.hSyncNeg = NV_TRUE;
} else {
dst->timings.flags.hSyncNeg = NV_FALSE;
}
if (src->flags & DRM_MODE_FLAG_PVSYNC) {
dst->timings.flags.vSyncPos = NV_TRUE;
} else {
dst->timings.flags.vSyncPos = NV_FALSE;
}
if (src->flags & DRM_MODE_FLAG_NVSYNC) {
dst->timings.flags.vSyncNeg = NV_TRUE;
} else {
dst->timings.flags.vSyncNeg = NV_FALSE;
}
dst->timings.widthMM = src->width_mm;
dst->timings.heightMM = src->height_mm;
memcpy(dst->name, src->name, min(sizeof(dst->name), sizeof(src->name)));
}
#endif