• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
set_crtc_mode(struct sp_dev * dev,struct sp_crtc * crtc,struct sp_connector * conn,drmModeModeInfoPtr mode)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 
initialize_screens(struct sp_dev * dev)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 
get_sp_plane(struct sp_dev * dev,struct sp_crtc * crtc)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 
put_sp_plane(struct sp_plane * plane)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 
set_sp_plane(struct sp_dev * dev,struct sp_plane * plane,struct sp_crtc * crtc,int x,int y)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 }
set_sp_plane_pset(struct sp_dev * dev,struct sp_plane * plane,drmModePropertySetPtr pset,struct sp_crtc * crtc,int x,int y)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