Skip to content

Commit

Permalink
evdi: add evdi driver into android linux kernel
Browse files Browse the repository at this point in the history
Tracked-On: OAM-119803
Signed-off-by: Fei Li <fei1.li@intel.com>
Signed-off-by: Junjie Mao <junjie.mao@intel.com>
Signed-off-by: Zhong, Fangjian <fangjian.zhong@intel.com>
Signed-off-by: Yuanyuan Zhao <yuanyuan.zhao@intel.com>
  • Loading branch information
YuanyuanZhao609 committed Aug 13, 2024
1 parent 8d0b376 commit e26bd74
Show file tree
Hide file tree
Showing 26 changed files with 5,380 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,4 @@ obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_PECI) += peci/
obj-$(CONFIG_HTE) += hte/
obj-$(CONFIG_X86_TCC_PTCM) += tcc/
obj-y += evdi/
2 changes: 2 additions & 0 deletions drivers/evdi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += evdi_platform_drv.o evdi_platform_dev.o evdi_sysfs.o evdi_modeset.o evdi_connector.o evdi_encoder.o evdi_drm_drv.o evdi_fb.o evdi_gem.o evdi_painter.o evdi_params.o evdi_cursor.o evdi_debug.o evdi_i2c.o evdi_ioc32.o
168 changes: 168 additions & 0 deletions drivers/evdi/evdi_connector.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2012 Red Hat
* Copyright (c) 2015 - 2020 DisplayLink (UK) Ltd.
*
* Based on parts on udlfb.c:
* Copyright (C) 2009 its respective authors
*
* This file is subject to the terms and conditions of the GNU General Public
* License v2. See the file COPYING in the main directory of this archive for
* more details.
*/

#include <linux/version.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_atomic_helper.h>
#include "evdi_drm_drv.h"

#if KERNEL_VERSION(5, 1, 0) <= LINUX_VERSION_CODE || defined(EL8)
#include <drm/drm_probe_helper.h>
#endif

/*
* dummy connector to just get EDID,
* all EVDI appear to have a DVI-D
*/

static int evdi_get_modes(struct drm_connector *connector)
{
struct evdi_device *evdi = connector->dev->dev_private;
struct edid *edid = NULL;
int ret = 0;

edid = (struct edid *)evdi_painter_get_edid_copy(evdi);

if (!edid) {
#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE || defined(EL8)
drm_connector_update_edid_property(connector, NULL);
#else
drm_mode_connector_update_edid_property(connector, NULL);
#endif
return 0;
}

#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE || defined(EL8)
ret = drm_connector_update_edid_property(connector, edid);
#else
ret = drm_mode_connector_update_edid_property(connector, edid);
#endif

if (ret) {
EVDI_ERROR("Failed to set edid property! error: %d", ret);
goto err;
}

ret = drm_add_edid_modes(connector, edid);
EVDI_INFO("(card%d) Edid property set", evdi->dev_index);
err:
kfree(edid);
return ret;
}

static enum drm_mode_status evdi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct evdi_device *evdi = connector->dev->dev_private;
uint32_t area_limit = mode->hdisplay * mode->vdisplay;
uint32_t mode_limit = area_limit * drm_mode_vrefresh(mode);

if (evdi->pixel_per_second_limit == 0)
return MODE_OK;

if (area_limit > evdi->pixel_area_limit ||
mode_limit > evdi->pixel_per_second_limit) {
EVDI_WARN("(card%d) Mode %dx%d@%d rejected\n",
evdi->dev_index,
mode->hdisplay,
mode->vdisplay,
drm_mode_vrefresh(mode));
return MODE_BAD;
}

return MODE_OK;
}

static enum drm_connector_status
evdi_detect(struct drm_connector *connector, __always_unused bool force)
{
struct evdi_device *evdi = connector->dev->dev_private;

EVDI_CHECKPT();
if (evdi_painter_is_connected(evdi->painter)) {
EVDI_INFO("(card%d) Connector state: connected\n",
evdi->dev_index);
return connector_status_connected;
}
EVDI_VERBOSE("(card%d) Connector state: disconnected\n",
evdi->dev_index);
return connector_status_disconnected;
}

static void evdi_connector_destroy(struct drm_connector *connector)
{
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
kfree(connector);
}

static struct drm_encoder *evdi_best_encoder(struct drm_connector *connector)
{
#if KERNEL_VERSION(5, 5, 0) <= LINUX_VERSION_CODE || defined(EL8)
struct drm_encoder *encoder;

drm_connector_for_each_possible_encoder(connector, encoder) {
return encoder;
}

return NULL;
#else
return drm_encoder_find(connector->dev,
NULL,
connector->encoder_ids[0]);
#endif
}

static struct drm_connector_helper_funcs evdi_connector_helper_funcs = {
.get_modes = evdi_get_modes,
.mode_valid = evdi_mode_valid,
.best_encoder = evdi_best_encoder,
};

static const struct drm_connector_funcs evdi_connector_funcs = {
.detect = evdi_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = evdi_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state
};

int evdi_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
{
struct drm_connector *connector;
struct evdi_device *evdi = dev->dev_private;

connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
if (!connector)
return -ENOMEM;

/* TODO: Initialize connector with actual connector type */
drm_connector_init(dev, connector, &evdi_connector_funcs,
DRM_MODE_CONNECTOR_DVII);
drm_connector_helper_add(connector, &evdi_connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_HPD;

drm_connector_register(connector);

evdi->conn = connector;

#if KERNEL_VERSION(4, 19, 0) <= LINUX_VERSION_CODE || defined(EL8)
drm_connector_attach_encoder(connector, encoder);
#else
drm_mode_connector_attach_encoder(connector, encoder);
#endif
return 0;
}
Loading

0 comments on commit e26bd74

Please sign in to comment.