You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
5.4 KiB
232 lines
5.4 KiB
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include <xf86drm.h> |
|
#include <xf86drmMode.h> |
|
#include <drm_fourcc.h> |
|
|
|
#include "modeset.h" |
|
#include "bo.h" |
|
#include "dev.h" |
|
|
|
static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc, |
|
struct sp_connector *conn, drmModeModeInfoPtr mode) |
|
{ |
|
int ret; |
|
struct drm_mode_create_blob create_blob; |
|
drmModePropertySetPtr pset; |
|
|
|
memset(&create_blob, 0, sizeof(create_blob)); |
|
create_blob.length = sizeof(struct drm_mode_modeinfo); |
|
create_blob.data = (__u64)(uintptr_t)mode; |
|
|
|
ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob); |
|
if (ret) { |
|
printf("Failed to create mode property blob %d", ret); |
|
return ret; |
|
} |
|
|
|
pset = drmModePropertySetAlloc(); |
|
if (!pset) { |
|
printf("Failed to allocate property set"); |
|
return -1; |
|
} |
|
|
|
ret = drmModePropertySetAdd(pset, crtc->crtc->crtc_id, |
|
crtc->mode_pid, create_blob.blob_id) || |
|
drmModePropertySetAdd(pset, crtc->crtc->crtc_id, |
|
crtc->active_pid, 1) || |
|
drmModePropertySetAdd(pset, conn->conn->connector_id, |
|
conn->crtc_id_pid, crtc->crtc->crtc_id); |
|
if (ret) { |
|
printf("Failed to add blob %d to pset", create_blob.blob_id); |
|
drmModePropertySetFree(pset); |
|
return ret; |
|
} |
|
|
|
ret = drmModePropertySetCommit(dev->fd, DRM_MODE_ATOMIC_ALLOW_MODESET, |
|
NULL, pset); |
|
|
|
drmModePropertySetFree(pset); |
|
|
|
if (ret) { |
|
printf("Failed to commit pset ret=%d\n", ret); |
|
return ret; |
|
} |
|
|
|
memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo)); |
|
crtc->crtc->mode_valid = 1; |
|
return 0; |
|
} |
|
|
|
int initialize_screens(struct sp_dev *dev) |
|
{ |
|
int ret, i, j; |
|
unsigned crtc_mask = 0; |
|
|
|
for (i = 0; i < dev->num_connectors; i++) { |
|
struct sp_connector *c = &dev->connectors[i]; |
|
drmModeModeInfoPtr m = NULL; |
|
drmModeEncoderPtr e = NULL; |
|
struct sp_crtc *cr = NULL; |
|
|
|
if (c->conn->connection != DRM_MODE_CONNECTED) |
|
continue; |
|
|
|
if (!c->conn->count_modes) { |
|
printf("connector has no modes, skipping\n"); |
|
continue; |
|
} |
|
|
|
/* Take the first unless there's a preferred mode */ |
|
m = &c->conn->modes[0]; |
|
for (j = 0; j < c->conn->count_modes; j++) { |
|
drmModeModeInfoPtr tmp_m = &c->conn->modes[j]; |
|
|
|
if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED)) |
|
continue; |
|
|
|
m = tmp_m; |
|
break; |
|
} |
|
|
|
if (!c->conn->count_encoders) { |
|
printf("no possible encoders for connector\n"); |
|
continue; |
|
} |
|
|
|
for (j = 0; j < dev->num_encoders; j++) { |
|
e = dev->encoders[j]; |
|
if (e->encoder_id == c->conn->encoders[0]) |
|
break; |
|
} |
|
if (j == dev->num_encoders) { |
|
printf("could not find encoder for the connector\n"); |
|
continue; |
|
} |
|
|
|
for (j = 0; j < dev->num_crtcs; j++) { |
|
if ((1 << j) & crtc_mask) |
|
continue; |
|
|
|
cr = &dev->crtcs[j]; |
|
|
|
if ((1 << j) & e->possible_crtcs) |
|
break; |
|
} |
|
if (j == dev->num_crtcs) { |
|
printf("could not find crtc for the encoder\n"); |
|
continue; |
|
} |
|
|
|
ret = set_crtc_mode(dev, cr, c, m); |
|
if (ret) { |
|
printf("failed to set mode!\n"); |
|
continue; |
|
} |
|
crtc_mask |= 1 << j; |
|
} |
|
return 0; |
|
} |
|
|
|
struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc) |
|
{ |
|
int i; |
|
|
|
for(i = 0; i < dev->num_planes; i++) { |
|
struct sp_plane *p = &dev->planes[i]; |
|
|
|
if (p->in_use) |
|
continue; |
|
|
|
if (!(p->plane->possible_crtcs & (1 << crtc->pipe))) |
|
continue; |
|
|
|
p->in_use = 1; |
|
return p; |
|
} |
|
return NULL; |
|
} |
|
|
|
void put_sp_plane(struct sp_plane *plane) |
|
{ |
|
drmModePlanePtr p; |
|
|
|
/* Get the latest plane information (most notably the crtc_id) */ |
|
p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id); |
|
if (p) |
|
plane->plane = p; |
|
|
|
if (plane->bo) { |
|
free_sp_bo(plane->bo); |
|
plane->bo = NULL; |
|
} |
|
plane->in_use = 0; |
|
} |
|
|
|
int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane, |
|
struct sp_crtc *crtc, int x, int y) |
|
{ |
|
int ret; |
|
uint32_t w, h; |
|
|
|
w = plane->bo->width; |
|
h = plane->bo->height; |
|
|
|
if ((w + x) > crtc->crtc->mode.hdisplay) |
|
w = crtc->crtc->mode.hdisplay - x; |
|
if ((h + y) > crtc->crtc->mode.vdisplay) |
|
h = crtc->crtc->mode.vdisplay - y; |
|
|
|
ret = drmModeSetPlane(dev->fd, plane->plane->plane_id, |
|
crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h, |
|
0, 0, w << 16, h << 16); |
|
if (ret) { |
|
printf("failed to set plane to crtc ret=%d\n", ret); |
|
return ret; |
|
} |
|
|
|
return ret; |
|
} |
|
int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, |
|
drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y) |
|
{ |
|
int ret; |
|
uint32_t w, h; |
|
|
|
w = plane->bo->width; |
|
h = plane->bo->height; |
|
|
|
if ((w + x) > crtc->crtc->mode.hdisplay) |
|
w = crtc->crtc->mode.hdisplay - x; |
|
if ((h + y) > crtc->crtc->mode.vdisplay) |
|
h = crtc->crtc->mode.vdisplay - y; |
|
|
|
ret = drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->crtc_pid, crtc->crtc->crtc_id) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->fb_pid, plane->bo->fb_id) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->crtc_x_pid, x) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->crtc_y_pid, y) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->crtc_w_pid, w) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->crtc_h_pid, h) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->src_x_pid, 0) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->src_y_pid, 0) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->src_w_pid, w << 16) |
|
|| drmModePropertySetAdd(pset, plane->plane->plane_id, |
|
plane->src_h_pid, h << 16); |
|
if (ret) { |
|
printf("failed to add properties to the set\n"); |
|
return -1; |
|
} |
|
|
|
return ret; |
|
}
|
|
|