Skip to content

Commit

Permalink
Support for full EDIDs with multiple extension blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
displaylink-mlukaszek committed Feb 3, 2016
1 parent 24c66d7 commit 09b525b
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 30 deletions.
8 changes: 4 additions & 4 deletions library/evdi_lib.c 100644 → 100755
Expand Up @@ -272,13 +272,13 @@ void evdi_close(evdi_handle handle)
}
}

void evdi_connect(evdi_handle handle, const unsigned char* edid)
void evdi_connect(evdi_handle handle, const unsigned char* edid, const unsigned edid_length)
{
struct drm_evdi_connect cmd = { 1 };
cmd.dev_index = handle->device_index;
if (edid) {
memcpy(cmd.edid, edid, 128);
}
cmd.edid = edid;
cmd.edid_length = edid_length;

do_ioctl(handle->fd, DRM_IOCTL_EVDI_CONNECT, &cmd, "connect");
}

Expand Down
2 changes: 1 addition & 1 deletion library/evdi_lib.h
Expand Up @@ -56,7 +56,7 @@ evdi_device_status evdi_check_device(int device);
evdi_handle evdi_open(int device);
int evdi_add_device();
void evdi_close(evdi_handle handle);
void evdi_connect(evdi_handle handle, const unsigned char* edid);
void evdi_connect(evdi_handle handle, const unsigned char* edid, const unsigned edid_length);
void evdi_disconnect(evdi_handle handle);
int evdi_poll_dirty_pixels(evdi_handle handle,
unsigned char* buf,
Expand Down
26 changes: 12 additions & 14 deletions module/evdi_connector.c
Expand Up @@ -23,28 +23,26 @@
static int evdi_get_modes(struct drm_connector *connector)
{
struct evdi_device *evdi = connector->dev->dev_private;
struct edid *edid;
int ret;
struct edid *edid = NULL;
int errorCode = 0;

edid = (struct edid *)evdi_painter_get_edid(evdi);
edid = (struct edid *)evdi_painter_get_edid_copy(evdi);
if (!edid) {
drm_mode_connector_update_edid_property(connector, NULL);
return 0;
}

/*
* We only read the main block, but if the monitor reports extension
* blocks then the drm edid code expects them to be present, so patch
* the extension count to 0.
*/
edid->checksum += edid->extensions;
edid->extensions = 0;
errorCode = drm_mode_connector_update_edid_property(connector, edid);
if (!errorCode) {
if (!drm_add_edid_modes(connector, edid)) {
EVDI_WARN("No modes added from edid\n");
}
} else {
EVDI_ERROR("Failed to set edid modes! error: %d\n", errorCode);
}

drm_mode_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
kfree(edid);

return ret;
return errorCode;
}

static int evdi_mode_valid(struct drm_connector *connector,
Expand Down
3 changes: 2 additions & 1 deletion module/evdi_drm.h
Expand Up @@ -52,7 +52,8 @@ struct drm_evdi_event_crtc_state {
struct drm_evdi_connect {
int32_t connected;
int32_t dev_index;
unsigned char edid[128];
const unsigned char* __user edid;
unsigned int edid_length;
};

struct drm_evdi_mapfifo {
Expand Down
2 changes: 1 addition & 1 deletion module/evdi_drv.h
Expand Up @@ -114,7 +114,7 @@ void evdi_stats_cleanup(struct evdi_device *evdi);

bool evdi_painter_is_connected(struct evdi_device *evdi);
void evdi_painter_close(struct evdi_device *evdi, struct drm_file *file);
u8 *evdi_painter_get_edid(struct evdi_device *evdi);
u8 *evdi_painter_get_edid_copy(struct evdi_device *evdi);
void evdi_painter_mark_dirty(struct evdi_device *evdi,
struct evdi_framebuffer *fb,
const struct drm_clip_rect* rect);
Expand Down
1 change: 1 addition & 0 deletions module/evdi_main.c
Expand Up @@ -55,6 +55,7 @@ int evdi_driver_unload(struct drm_device *dev)
evdi_fbdev_unplug(dev);
drm_unplug_dev(dev);

evdi_painter_cleanup(evdi);
evdi_stats_cleanup(evdi);
evdi_fbdev_cleanup(dev);
evdi_modeset_cleanup(dev);
Expand Down
46 changes: 37 additions & 9 deletions module/evdi_painter.c
Expand Up @@ -34,7 +34,8 @@ struct evdi_event_crtc_state_pending {

struct evdi_painter {
bool is_connected;
u8 edid[EDID_LENGTH];
struct edid *edid;
unsigned int edid_length;

struct mutex lock;
struct drm_clip_rect dirty_rects[MAX_DIRTS];
Expand Down Expand Up @@ -169,19 +170,22 @@ bool evdi_painter_is_connected(struct evdi_device *evdi)
return false;
}

u8 *evdi_painter_get_edid(struct evdi_device *evdi)
u8 *evdi_painter_get_edid_copy(struct evdi_device *evdi)
{
u8 *block = NULL;
EVDI_CHECKPT();

painter_lock(evdi->painter);
if (evdi_painter_is_connected(evdi)) {
block = kmalloc(EDID_LENGTH, GFP_KERNEL);
if (evdi_painter_is_connected(evdi) &&
evdi->painter->edid &&
evdi->painter->edid_length) {
block = kmalloc(evdi->painter->edid_length, GFP_KERNEL);
if (block) {
memcpy(block, &evdi->painter->edid[0], EDID_LENGTH);
memcpy(block, evdi->painter->edid, evdi->painter->edid_length);
EVDI_DEBUG("(dev=%d) %02x %02x %02x\n", evdi->dev_index, block[0], block[1], block[2]);
}
}

painter_unlock(evdi->painter);
return block;
}
Expand Down Expand Up @@ -367,7 +371,11 @@ void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
}
}

void evdi_painter_connect(struct evdi_device* evdi, void const* edid, struct drm_file* file, int dev_index)
void evdi_painter_connect(struct evdi_device* evdi,
void const* edid,
unsigned int edid_length,
struct drm_file* file,
int dev_index)
{
struct evdi_painter* painter = evdi->painter;
EVDI_CHECKPT();
Expand All @@ -382,8 +390,15 @@ void evdi_painter_connect(struct evdi_device* evdi, void const* edid, struct drm
evdi->dev_index = dev_index;
EVDI_DEBUG("(dev=%d) Connected with %p\n", evdi->dev_index, painter->drm_filp);

memcpy(painter->edid, edid, EDID_LENGTH);
EVDI_DEBUG("(dev=%d) Edid (3 bytes): %02x %02x %02x\n", evdi->dev_index, painter->edid[0], painter->edid[1], painter->edid[2]);
painter->edid_length = edid_length;
painter->edid = krealloc(painter->edid, painter->edid_length, GFP_KERNEL);

copy_from_user(painter->edid, edid, painter->edid_length);
EVDI_DEBUG("(dev=%d) Edid (3 bytes): %02x %02x %02x\n",
evdi->dev_index,
painter->edid->header[0],
painter->edid->header[1],
painter->edid->header[2]);

painter->is_connected = true;

Expand Down Expand Up @@ -445,7 +460,7 @@ int evdi_painter_connect_ioctl(struct drm_device *drm_dev, void *data, struct dr

if (painter) {
if (cmd->connected) {
evdi_painter_connect(evdi, cmd->edid, file, cmd->dev_index);
evdi_painter_connect(evdi, cmd->edid, cmd->edid_length, file, cmd->dev_index);
} else {
evdi_painter_disconnect(evdi, file);
}
Expand Down Expand Up @@ -554,3 +569,16 @@ int evdi_painter_init(struct evdi_device *dev)
return -ENOMEM;
}

void evdi_painter_cleanup(struct evdi_device *evdi)
{
struct evdi_painter *painter = evdi->painter;

EVDI_CHECKPT();
if (painter) {
painter_lock(painter);
kfree(painter->edid);
painter->edid_length = 0;
painter->edid = NULL;
painter_unlock(painter);
}
}

0 comments on commit 09b525b

Please sign in to comment.