aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark2012-09-30 11:21:59 -0500
committerRob Clark2012-09-30 11:21:59 -0500
commit64a970788e0b95e1a0ce005ad050f00891c8bab8 (patch)
tree5f1099a16204ec57bce7640d3f10c2d9b8ad4772
parent6ea931ea247e1f6ab159e180e7bbf11bf2d3f58f (diff)
downloadxf86-video-omap-64a970788e0b95e1a0ce005ad050f00891c8bab8.tar.gz
xf86-video-omap-64a970788e0b95e1a0ce005ad050f00891c8bab8.tar.xz
xf86-video-omap-64a970788e0b95e1a0ce005ad050f00891c8bab8.zip
fix multi-display + rotation
If the fb is reallocated due to rotated CRTC in drmmode_set_mode_major() then we need to reconfigure the CRTCs that are torn down by the kernel when the previous fb was destroyed. Signed-off-by: Rob Clark <rob@ti.com>
-rw-r--r--src/drmmode_display.c213
-rw-r--r--src/omap_driver.c2
-rw-r--r--src/omap_driver.h5
3 files changed, 122 insertions, 98 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 8a5506f..3deb952 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -250,59 +250,18 @@ drmmode_set_rotation(xf86CrtcPtr crtc, Rotation rotation)
250} 250}
251 251
252static Bool 252static Bool
253drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, 253drmmode_restore_crtc(xf86CrtcPtr crtc)
254 Rotation rotation, int x, int y)
255{ 254{
256 ScrnInfoPtr pScrn = crtc->scrn; 255 ScrnInfoPtr pScrn = crtc->scrn;
257 OMAPPtr pOMAP = OMAPPTR(pScrn); 256 OMAPPtr pOMAP = OMAPPTR(pScrn);
258 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); 257 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
259 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; 258 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
260 drmmode_ptr drmmode = drmmode_crtc->drmmode; 259 drmmode_ptr drmmode = drmmode_crtc->drmmode;
261 int saved_x, saved_y;
262 Rotation saved_rotation;
263 DisplayModeRec saved_mode;
264 uint32_t *output_ids = NULL; 260 uint32_t *output_ids = NULL;
265 int output_count = 0; 261 int output_count = 0;
266 int ret = TRUE; 262 int ret = TRUE;
267 int i; 263 int i;
268 int fb_id;
269 drmModeModeInfo kmode; 264 drmModeModeInfo kmode;
270 Bool was_rotated = drmmode->rotated_crtcs > 0;
271
272 TRACE_ENTER();
273
274 /* update the count of number of rotated CRTCs.. if we have one or more
275 * rotated outputs then we want to use a tiled buffer, but otherwise
276 * stick with non-tiled
277 */
278 if ((drmmode_crtc->rotation != RR_Rotate_0) &&
279 (rotation == RR_Rotate_0)) {
280 DEBUG_MSG("disabling rotation for crtc: %u",
281 drmmode_crtc->mode_crtc->crtc_id);
282 drmmode->rotated_crtcs--;
283 } else if ((drmmode_crtc->rotation == RR_Rotate_0) &&
284 (rotation != RR_Rotate_0)) {
285 DEBUG_MSG("enabling rotation for crtc: %u",
286 drmmode_crtc->mode_crtc->crtc_id);
287 drmmode->rotated_crtcs++;
288 }
289
290 drmmode_crtc->rotation = rotation;
291
292 /* at this point, if we are switching from unrotated to rotated
293 * or visa versa, then we need to reallocate the scanout buffer..
294 */
295 if (was_rotated != (drmmode->rotated_crtcs > 0)) {
296 /* reallocate scanout buffer.. */
297 drmmode_reallocate_scanout(pScrn, TRUE);
298 }
299
300 /* note: this needs to be done before setting the mode, otherwise
301 * drm core will reject connecting the fb to crtc due to mismatched
302 * dimensions:
303 */
304 if (!drmmode_set_rotation(crtc, rotation))
305 goto done;
306 265
307 if (drmmode->fb_id == 0) { 266 if (drmmode->fb_id == 0) {
308 unsigned int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8); 267 unsigned int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
@@ -316,29 +275,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
316 pitch, omap_bo_handle(pOMAP->scanout), 275 pitch, omap_bo_handle(pOMAP->scanout),
317 &drmmode->fb_id); 276 &drmmode->fb_id);
318 if (ret < 0) { 277 if (ret < 0) {
319 // Fixme - improve this error message: 278 ERROR_MSG("failed to add fb: %s", strerror(errno));
320 ErrorF("failed to add fb\n");
321 return FALSE; 279 return FALSE;
322 } 280 }
323 } 281 }
324 282
325 /* Save the current mode in case there's a problem: */
326 saved_mode = crtc->mode;
327 saved_x = crtc->x;
328 saved_y = crtc->y;
329 saved_rotation = crtc->rotation;
330
331 /* Set the new mode: */
332 crtc->mode = *mode;
333 crtc->x = x;
334 crtc->y = y;
335 crtc->rotation = rotation;
336
337 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output); 283 output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
338 if (!output_ids) { 284 if (!output_ids) {
339 // Fixme - have an error message? 285 ERROR_MSG("allocation failed");
340 ret = FALSE; 286 return FALSE;
341 goto done;
342 } 287 }
343 288
344 for (i = 0; i < xf86_config->num_output; i++) { 289 for (i = 0; i < xf86_config->num_output; i++) {
@@ -354,26 +299,18 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
354 output_count++; 299 output_count++;
355 } 300 }
356 301
357 // Fixme - Intel puts this function here, and Nouveau puts it at the end 302 drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
358 // of this function -> determine what's best for TI'S OMAP4:
359 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
360 crtc->gamma_blue, crtc->gamma_size);
361
362 drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
363
364 fb_id = drmmode->fb_id;
365 303
366 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 304 ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
367 fb_id, x, y, output_ids, output_count, &kmode); 305 drmmode->fb_id, crtc->x, crtc->y,
306 output_ids, output_count, &kmode);
368 if (ret) { 307 if (ret) {
369 xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, 308 ERROR_MSG("failed to set mode: %s", strerror(-ret));
370 "failed to set mode: %s\n", strerror(-ret)); 309 ret = FALSE;
371 } else { 310 } else {
372 ret = TRUE; 311 ret = TRUE;
373 } 312 }
374 313
375 // FIXME - DO WE NEED TO CALL TO THE PVR EXA/DRI2 CODE TO UPDATE THEM???
376
377 /* Turn on any outputs on this crtc that may have been disabled: */ 314 /* Turn on any outputs on this crtc that may have been disabled: */
378 for (i = 0; i < xf86_config->num_output; i++) { 315 for (i = 0; i < xf86_config->num_output; i++) {
379 xf86OutputPtr output = xf86_config->output[i]; 316 xf86OutputPtr output = xf86_config->output[i];
@@ -384,15 +321,77 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
384 drmmode_output_dpms(output, DPMSModeOn); 321 drmmode_output_dpms(output, DPMSModeOn);
385 } 322 }
386 323
387 // TODO: only call this if we are not using sw cursor.. ie. bad to call this
388 // if we haven't called xf86InitCursor()!!
389 // if (pScrn->pScreen)
390 // xf86_reload_cursors(pScrn->pScreen);
391
392done:
393 if (output_ids) { 324 if (output_ids) {
394 free(output_ids); 325 free(output_ids);
395 } 326 }
327
328 return ret;
329}
330
331static Bool
332drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
333 Rotation rotation, int x, int y)
334{
335 ScrnInfoPtr pScrn = crtc->scrn;
336 drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
337 drmmode_ptr drmmode = drmmode_crtc->drmmode;
338 int saved_x, saved_y;
339 Rotation saved_rotation;
340 DisplayModeRec saved_mode;
341 int ret = TRUE;
342 Bool was_rotated = drmmode->rotated_crtcs > 0;
343
344 TRACE_ENTER();
345
346 /* update the count of number of rotated CRTCs.. if we have one or more
347 * rotated outputs then we want to use a tiled buffer, but otherwise
348 * stick with non-tiled
349 */
350 if ((drmmode_crtc->rotation != RR_Rotate_0) &&
351 (rotation == RR_Rotate_0)) {
352 DEBUG_MSG("disabling rotation for crtc: %u",
353 drmmode_crtc->mode_crtc->crtc_id);
354 drmmode->rotated_crtcs--;
355 } else if ((drmmode_crtc->rotation == RR_Rotate_0) &&
356 (rotation != RR_Rotate_0)) {
357 DEBUG_MSG("enabling rotation for crtc: %u",
358 drmmode_crtc->mode_crtc->crtc_id);
359 drmmode->rotated_crtcs++;
360 }
361
362 drmmode_crtc->rotation = rotation;
363
364 /* at this point, if we are switching from unrotated to rotated
365 * or visa versa, then we need to reallocate the scanout buffer..
366 */
367 if (was_rotated != (drmmode->rotated_crtcs > 0)) {
368 /* reallocate scanout buffer.. */
369 drmmode_reallocate_scanout(pScrn, TRUE, crtc);
370 }
371
372 /* note: this needs to be done before setting the mode, otherwise
373 * drm core will reject connecting the fb to crtc due to mismatched
374 * dimensions:
375 */
376 if (!drmmode_set_rotation(crtc, rotation)) {
377 ERROR_MSG("could not set rotation");
378 return FALSE;
379 }
380
381 /* Save the current mode in case there's a problem: */
382 saved_mode = crtc->mode;
383 saved_x = crtc->x;
384 saved_y = crtc->y;
385 saved_rotation = crtc->rotation;
386
387 /* Set the new mode: */
388 crtc->mode = *mode;
389 crtc->x = x;
390 crtc->y = y;
391 crtc->rotation = rotation;
392
393 ret = drmmode_restore_crtc(crtc);
394
396 if (!ret) { 395 if (!ret) {
397 /* If there was a problem, restore the old mode: */ 396 /* If there was a problem, restore the old mode: */
398 crtc->x = saved_x; 397 crtc->x = saved_x;
@@ -1111,37 +1110,26 @@ drmmode_is_rotated(ScrnInfoPtr pScrn)
1111} 1110}
1112 1111
1113Bool 1112Bool
1114drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw) 1113drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw, xf86CrtcPtr crtc)
1115{ 1114{
1116 OMAPPtr pOMAP = OMAPPTR(pScrn); 1115 OMAPPtr pOMAP = OMAPPTR(pScrn);
1117 ScreenPtr pScreen = pScrn->pScreen; 1116 ScreenPtr pScreen = pScrn->pScreen;
1118 Bool changed = FALSE;
1119 uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
1120 int width = pScrn->virtualX; 1117 int width = pScrn->virtualX;
1121 int height = pScrn->virtualY; 1118 int height = pScrn->virtualY;
1122 unsigned int pitch;
1123 Bool rotate = drmmode_is_rotated(pScrn); 1119 Bool rotate = drmmode_is_rotated(pScrn);
1120 unsigned int pitch;
1124 1121
1125 if (rotate) { 1122 if (rotate) {
1126 /* if we are using tiled buffers, we really should check if
1127 * width/height has changed, rather than size.. for now, just
1128 * always re-alloc:
1129 */
1130 changed = TRUE;
1131 pitch = OMAPCalculateTiledStride(width, pScrn->bitsPerPixel); 1123 pitch = OMAPCalculateTiledStride(width, pScrn->bitsPerPixel);
1132 } else { 1124 } else {
1133 pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel); 1125 pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel);
1134 } 1126 }
1135 1127
1136 if (pOMAP->scanout) { 1128 if ((width != pOMAP->scanout_w) ||
1137 if ((pitch * height) != omap_bo_size(pOMAP->scanout)) { 1129 (height != pOMAP->scanout_h) ||
1138 changed = TRUE; 1130 (rotate != pOMAP->scanout_rotate)) {
1139 } 1131 uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
1140 } else {
1141 changed = TRUE;
1142 }
1143 1132
1144 if (changed) {
1145 /* remove old fb if it exists */ 1133 /* remove old fb if it exists */
1146 drmmode_remove_fb(pScrn); 1134 drmmode_remove_fb(pScrn);
1147 1135
@@ -1169,6 +1157,10 @@ drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
1169 return FALSE; 1157 return FALSE;
1170 } 1158 }
1171 1159
1160 pOMAP->scanout_w = width;
1161 pOMAP->scanout_h = height;
1162 pOMAP->scanout_rotate = rotate;
1163
1172 pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8); 1164 pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
1173 1165
1174 if (pScreen && pScreen->ModifyPixmapHeader) { 1166 if (pScreen && pScreen->ModifyPixmapHeader) {
@@ -1181,6 +1173,35 @@ drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
1181 1173
1182 if (pScreen && pScrn->EnableDisableFBAccess && redraw) 1174 if (pScreen && pScrn->EnableDisableFBAccess && redraw)
1183 pScrn->EnableDisableFBAccess(ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, TRUE)); 1175 pScrn->EnableDisableFBAccess(ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, TRUE));
1176
1177 /* if reallocation triggered by a mode-set, we need to reconfigure any
1178 * other crtc's which have just been torn down by destroying the old fb:
1179 */
1180 if (crtc) {
1181 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1182 int i;
1183 DEBUG_MSG("restoring CRTCs");
1184 for (i = 0; i < config->num_crtc; i++) {
1185 if (config->crtc[i] != crtc) {
1186 int ret;
1187 DEBUG_MSG("restore CRTC %d", i);
1188 ret = drmmode_restore_crtc(config->crtc[i]);
1189 if (!ret) {
1190 ERROR_MSG("failed to reconfig crtc %d", i);
1191 /* hmm, I guess just keep trying the rest? */
1192 }
1193 }
1194 }
1195 }
1196 } else {
1197
1198 if (pScreen && pScreen->ModifyPixmapHeader) {
1199 PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
1200 pScreen->ModifyPixmapHeader(rootPixmap,
1201 pScrn->virtualX, pScrn->virtualY,
1202 pScrn->depth, pScrn->bitsPerPixel, pitch,
1203 omap_bo_map(pOMAP->scanout));
1204 }
1184 } 1205 }
1185 1206
1186 return TRUE; 1207 return TRUE;
@@ -1194,7 +1215,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
1194 pScrn->virtualX = width; 1215 pScrn->virtualX = width;
1195 pScrn->virtualY = height; 1216 pScrn->virtualY = height;
1196 1217
1197 if (!drmmode_reallocate_scanout(pScrn, FALSE)) 1218 if (!drmmode_reallocate_scanout(pScrn, FALSE, NULL))
1198 return FALSE; 1219 return FALSE;
1199 1220
1200 return TRUE; 1221 return TRUE;
diff --git a/src/omap_driver.c b/src/omap_driver.c
index 983d24c..96ab937 100644
--- a/src/omap_driver.c
+++ b/src/omap_driver.c
@@ -217,7 +217,7 @@ OMAPTiledFlags(unsigned int bitsPerPixel)
217static Bool 217static Bool
218OMAPMapMem(ScrnInfoPtr pScrn) 218OMAPMapMem(ScrnInfoPtr pScrn)
219{ 219{
220 return drmmode_reallocate_scanout(pScrn, FALSE); 220 return drmmode_reallocate_scanout(pScrn, FALSE, NULL);
221} 221}
222 222
223 223
diff --git a/src/omap_driver.h b/src/omap_driver.h
index 7bfedc0..f3f0450 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -150,6 +150,8 @@ typedef struct _OMAPRec
150 150
151 /** Scan-out buffer. */ 151 /** Scan-out buffer. */
152 struct omap_bo *scanout; 152 struct omap_bo *scanout;
153 int scanout_w, scanout_h;
154 Bool scanout_rotate;
153 155
154 /** Pointer to the options for this screen. */ 156 /** Pointer to the options for this screen. */
155 OptionInfoPtr pOptionInfo; 157 OptionInfoPtr pOptionInfo;
@@ -240,7 +242,8 @@ Bool drmmode_page_flip(DrawablePtr pDraw, PixmapPtr back, void *priv);
240void drmmode_wait_for_event(ScrnInfoPtr pScrn); 242void drmmode_wait_for_event(ScrnInfoPtr pScrn);
241Bool drmmode_cursor_init(ScreenPtr pScreen); 243Bool drmmode_cursor_init(ScreenPtr pScreen);
242Bool drmmode_is_rotated(ScrnInfoPtr pScrn); 244Bool drmmode_is_rotated(ScrnInfoPtr pScrn);
243Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw); 245Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw,
246 xf86CrtcPtr crtc);
244 247
245 248
246/** 249/**