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