Home | History | Annotate | Download | only in planetest
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include <xf86drm.h>
      6 #include <xf86drmMode.h>
      7 #include <drm_fourcc.h>
      8 
      9 #include "modeset.h"
     10 #include "bo.h"
     11 #include "dev.h"
     12 
     13 static int set_crtc_mode(struct sp_dev *dev, struct sp_crtc *crtc,
     14 			struct sp_connector *conn, drmModeModeInfoPtr mode)
     15 {
     16 	int ret;
     17 	struct drm_mode_create_blob create_blob;
     18 	drmModePropertySetPtr pset;
     19 
     20 	memset(&create_blob, 0, sizeof(create_blob));
     21 	create_blob.length = sizeof(struct drm_mode_modeinfo);
     22 	create_blob.data = (__u64)(uintptr_t)mode;
     23 
     24 	ret = drmIoctl(dev->fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
     25 	if (ret) {
     26 		printf("Failed to create mode property blob %d", ret);
     27 		return ret;
     28 	}
     29 
     30 	pset = drmModePropertySetAlloc();
     31 	if (!pset) {
     32 		printf("Failed to allocate property set");
     33 		return -1;
     34 	}
     35 
     36 	ret = drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
     37 				    crtc->mode_pid, create_blob.blob_id) ||
     38 	      drmModePropertySetAdd(pset, crtc->crtc->crtc_id,
     39 				    crtc->active_pid, 1) ||
     40 		drmModePropertySetAdd(pset, conn->conn->connector_id,
     41 				conn->crtc_id_pid, crtc->crtc->crtc_id);
     42 	if (ret) {
     43 		printf("Failed to add blob %d to pset", create_blob.blob_id);
     44 		drmModePropertySetFree(pset);
     45 		return ret;
     46 	}
     47 
     48 	ret = drmModePropertySetCommit(dev->fd, DRM_MODE_ATOMIC_ALLOW_MODESET,
     49 					NULL, pset);
     50 
     51 	drmModePropertySetFree(pset);
     52 
     53 	if (ret) {
     54 		printf("Failed to commit pset ret=%d\n", ret);
     55 		return ret;
     56 	}
     57 
     58 	memcpy(&crtc->crtc->mode, mode, sizeof(struct drm_mode_modeinfo));
     59 	crtc->crtc->mode_valid = 1;
     60 	return 0;
     61 }
     62 
     63 int initialize_screens(struct sp_dev *dev)
     64 {
     65 	int ret, i, j;
     66 	unsigned crtc_mask = 0;
     67 
     68 	for (i = 0; i < dev->num_connectors; i++) {
     69 		struct sp_connector *c = &dev->connectors[i];
     70 		drmModeModeInfoPtr m = NULL;
     71 		drmModeEncoderPtr e = NULL;
     72 		struct sp_crtc *cr = NULL;
     73 
     74 		if (c->conn->connection != DRM_MODE_CONNECTED)
     75 			continue;
     76 
     77 		if (!c->conn->count_modes) {
     78 			printf("connector has no modes, skipping\n");
     79 			continue;
     80 		}
     81 
     82 		/* Take the first unless there's a preferred mode */
     83 		m = &c->conn->modes[0];
     84 		for (j = 0; j < c->conn->count_modes; j++) {
     85 			drmModeModeInfoPtr tmp_m = &c->conn->modes[j];
     86 
     87 			if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED))
     88 				continue;
     89 
     90 			m = tmp_m;
     91 			break;
     92 		}
     93 
     94 		if (!c->conn->count_encoders) {
     95 			printf("no possible encoders for connector\n");
     96 			continue;
     97 		}
     98 
     99 		for (j = 0; j < dev->num_encoders; j++) {
    100 			e = dev->encoders[j];
    101 			if (e->encoder_id == c->conn->encoders[0])
    102 				break;
    103 		}
    104 		if (j == dev->num_encoders) {
    105 			printf("could not find encoder for the connector\n");
    106 			continue;
    107 		}
    108 
    109 		for (j = 0; j < dev->num_crtcs; j++) {
    110 			if ((1 << j) & crtc_mask)
    111 				continue;
    112 
    113 			cr = &dev->crtcs[j];
    114 
    115 			if ((1 << j) & e->possible_crtcs)
    116 				break;
    117 		}
    118 		if (j == dev->num_crtcs) {
    119 			printf("could not find crtc for the encoder\n");
    120 			continue;
    121 		}
    122 
    123 		ret = set_crtc_mode(dev, cr, c, m);
    124 		if (ret) {
    125 			printf("failed to set mode!\n");
    126 			continue;
    127 		}
    128 		crtc_mask |= 1 << j;
    129 	}
    130 	return 0;
    131 }
    132 
    133 struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc)
    134 {
    135 	int i;
    136 
    137 	for(i = 0; i < dev->num_planes; i++) {
    138 		struct sp_plane *p = &dev->planes[i];
    139 
    140 		if (p->in_use)
    141 			continue;
    142 
    143 		if (!(p->plane->possible_crtcs & (1 << crtc->pipe)))
    144 			continue;
    145 
    146 		p->in_use = 1;
    147 		return p;
    148 	}
    149 	return NULL;
    150 }
    151 
    152 void put_sp_plane(struct sp_plane *plane)
    153 {
    154 	drmModePlanePtr p;
    155 
    156 	/* Get the latest plane information (most notably the crtc_id) */
    157 	p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id);
    158 	if (p)
    159 		plane->plane = p;
    160 
    161 	if (plane->bo) {
    162 		free_sp_bo(plane->bo);
    163 		plane->bo = NULL;
    164 	}
    165 	plane->in_use = 0;
    166 }
    167 
    168 int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane,
    169 		struct sp_crtc *crtc, int x, int y)
    170 {
    171 	int ret;
    172 	uint32_t w, h;
    173 
    174 	w = plane->bo->width;
    175 	h = plane->bo->height;
    176 
    177 	if ((w + x) > crtc->crtc->mode.hdisplay)
    178 		w = crtc->crtc->mode.hdisplay - x;
    179 	if ((h + y) > crtc->crtc->mode.vdisplay)
    180 		h = crtc->crtc->mode.vdisplay - y;
    181 
    182 	ret = drmModeSetPlane(dev->fd, plane->plane->plane_id,
    183 			crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h,
    184 			0, 0, w << 16, h << 16);
    185 	if (ret) {
    186 		printf("failed to set plane to crtc ret=%d\n", ret);
    187 		return ret;
    188 	}
    189 
    190 	return ret;
    191 }
    192 int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane,
    193 		drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y)
    194 {
    195 	int ret;
    196 	uint32_t w, h;
    197 
    198 	w = plane->bo->width;
    199 	h = plane->bo->height;
    200 
    201 	if ((w + x) > crtc->crtc->mode.hdisplay)
    202 		w = crtc->crtc->mode.hdisplay - x;
    203 	if ((h + y) > crtc->crtc->mode.vdisplay)
    204 		h = crtc->crtc->mode.vdisplay - y;
    205 
    206 	ret = drmModePropertySetAdd(pset, plane->plane->plane_id,
    207 			plane->crtc_pid, crtc->crtc->crtc_id)
    208 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    209 			plane->fb_pid, plane->bo->fb_id)
    210 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    211 			plane->crtc_x_pid, x)
    212 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    213 			plane->crtc_y_pid, y)
    214 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    215 			plane->crtc_w_pid, w)
    216 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    217 			plane->crtc_h_pid, h)
    218 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    219 			plane->src_x_pid, 0)
    220 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    221 			plane->src_y_pid, 0)
    222 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    223 			plane->src_w_pid, w << 16)
    224 		|| drmModePropertySetAdd(pset, plane->plane->plane_id,
    225 			plane->src_h_pid, h << 16);
    226 	if (ret) {
    227 		printf("failed to add properties to the set\n");
    228 		return -1;
    229 	}
    230 
    231 	return ret;
    232 }
    233