forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-31 f70575805708cabdedea7498aaa3f710fde4d920
kernel/drivers/gpu/drm/qxl/qxl_display.c
....@@ -24,10 +24,15 @@
2424 */
2525
2626 #include <linux/crc32.h>
27
-#include <drm/drm_crtc_helper.h>
28
-#include <drm/drm_plane_helper.h>
29
-#include <drm/drm_atomic_helper.h>
27
+#include <linux/delay.h>
28
+
29
+#include <drm/drm_drv.h>
3030 #include <drm/drm_atomic.h>
31
+#include <drm/drm_atomic_helper.h>
32
+#include <drm/drm_gem_framebuffer_helper.h>
33
+#include <drm/drm_plane_helper.h>
34
+#include <drm/drm_probe_helper.h>
35
+#include <drm/drm_simple_kms_helper.h>
3136
3237 #include "qxl_drv.h"
3338 #include "qxl_object.h"
....@@ -37,7 +42,8 @@
3742 return head->width && head->height;
3843 }
3944
40
-static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
45
+static int qxl_alloc_client_monitors_config(struct qxl_device *qdev,
46
+ unsigned int count)
4147 {
4248 if (qdev->client_monitors_config &&
4349 count > qdev->client_monitors_config->count) {
....@@ -46,18 +52,20 @@
4652 }
4753 if (!qdev->client_monitors_config) {
4854 qdev->client_monitors_config = kzalloc(
49
- sizeof(struct qxl_monitors_config) +
50
- sizeof(struct qxl_head) * count, GFP_KERNEL);
55
+ struct_size(qdev->client_monitors_config,
56
+ heads, count), GFP_KERNEL);
5157 if (!qdev->client_monitors_config)
52
- return;
58
+ return -ENOMEM;
5359 }
5460 qdev->client_monitors_config->count = count;
61
+ return 0;
5562 }
5663
5764 enum {
5865 MONITORS_CONFIG_MODIFIED,
5966 MONITORS_CONFIG_UNCHANGED,
6067 MONITORS_CONFIG_BAD_CRC,
68
+ MONITORS_CONFIG_ERROR,
6169 };
6270
6371 static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
....@@ -76,10 +84,10 @@
7684 DRM_DEBUG_KMS("no client monitors configured\n");
7785 return status;
7886 }
79
- if (num_monitors > qdev->monitors_config->max_allowed) {
87
+ if (num_monitors > qxl_num_crtc) {
8088 DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
81
- qdev->monitors_config->max_allowed, num_monitors);
82
- num_monitors = qdev->monitors_config->max_allowed;
89
+ qxl_num_crtc, num_monitors);
90
+ num_monitors = qxl_num_crtc;
8391 } else {
8492 num_monitors = qdev->rom->client_monitors_config.count;
8593 }
....@@ -87,10 +95,12 @@
8795 && (num_monitors != qdev->client_monitors_config->count)) {
8896 status = MONITORS_CONFIG_MODIFIED;
8997 }
90
- qxl_alloc_client_monitors_config(qdev, num_monitors);
98
+ if (qxl_alloc_client_monitors_config(qdev, num_monitors)) {
99
+ status = MONITORS_CONFIG_ERROR;
100
+ return status;
101
+ }
91102 /* we copy max from the client but it isn't used */
92
- qdev->client_monitors_config->max_allowed =
93
- qdev->monitors_config->max_allowed;
103
+ qdev->client_monitors_config->max_allowed = qxl_num_crtc;
94104 for (i = 0 ; i < qdev->client_monitors_config->count ; ++i) {
95105 struct qxl_urect *c_rect =
96106 &qdev->rom->client_monitors_config.heads[i];
....@@ -153,13 +163,18 @@
153163 void qxl_display_read_client_monitors_config(struct qxl_device *qdev)
154164 {
155165 struct drm_device *dev = &qdev->ddev;
156
- int status, retries;
166
+ struct drm_modeset_acquire_ctx ctx;
167
+ int status, retries, ret;
157168
158169 for (retries = 0; retries < 10; retries++) {
159170 status = qxl_display_copy_rom_client_monitors_config(qdev);
160171 if (status != MONITORS_CONFIG_BAD_CRC)
161172 break;
162173 udelay(5);
174
+ }
175
+ if (status == MONITORS_CONFIG_ERROR) {
176
+ DRM_DEBUG_KMS("ignoring client monitors config: error");
177
+ return;
163178 }
164179 if (status == MONITORS_CONFIG_BAD_CRC) {
165180 DRM_DEBUG_KMS("ignoring client monitors config: bad crc");
....@@ -170,9 +185,9 @@
170185 return;
171186 }
172187
173
- drm_modeset_lock_all(dev);
188
+ DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
174189 qxl_update_offset_props(qdev);
175
- drm_modeset_unlock_all(dev);
190
+ DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
176191 if (!drm_helper_hpd_irq_event(dev)) {
177192 /* notify that the monitor configuration changed, to
178193 adjust at the arbitrary resolution */
....@@ -180,20 +195,63 @@
180195 }
181196 }
182197
183
-static int qxl_add_monitors_config_modes(struct drm_connector *connector,
184
- unsigned *pwidth,
185
- unsigned *pheight)
198
+static int qxl_check_mode(struct qxl_device *qdev,
199
+ unsigned int width,
200
+ unsigned int height)
201
+{
202
+ unsigned int stride;
203
+ unsigned int size;
204
+
205
+ if (check_mul_overflow(width, 4u, &stride))
206
+ return -EINVAL;
207
+ if (check_mul_overflow(stride, height, &size))
208
+ return -EINVAL;
209
+ if (size > qdev->vram_size)
210
+ return -ENOMEM;
211
+ return 0;
212
+}
213
+
214
+static int qxl_check_framebuffer(struct qxl_device *qdev,
215
+ struct qxl_bo *bo)
216
+{
217
+ return qxl_check_mode(qdev, bo->surf.width, bo->surf.height);
218
+}
219
+
220
+static int qxl_add_mode(struct drm_connector *connector,
221
+ unsigned int width,
222
+ unsigned int height,
223
+ bool preferred)
186224 {
187225 struct drm_device *dev = connector->dev;
188
- struct qxl_device *qdev = dev->dev_private;
226
+ struct qxl_device *qdev = to_qxl(dev);
227
+ struct drm_display_mode *mode = NULL;
228
+ int rc;
229
+
230
+ rc = qxl_check_mode(qdev, width, height);
231
+ if (rc != 0)
232
+ return 0;
233
+
234
+ mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
235
+ if (preferred)
236
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
237
+ mode->hdisplay = width;
238
+ mode->vdisplay = height;
239
+ drm_mode_set_name(mode);
240
+ drm_mode_probed_add(connector, mode);
241
+ return 1;
242
+}
243
+
244
+static int qxl_add_monitors_config_modes(struct drm_connector *connector)
245
+{
246
+ struct drm_device *dev = connector->dev;
247
+ struct qxl_device *qdev = to_qxl(dev);
189248 struct qxl_output *output = drm_connector_to_qxl_output(connector);
190249 int h = output->index;
191
- struct drm_display_mode *mode = NULL;
192250 struct qxl_head *head;
193251
194252 if (!qdev->monitors_config)
195253 return 0;
196
- if (h >= qdev->monitors_config->max_allowed)
254
+ if (h >= qxl_num_crtc)
197255 return 0;
198256 if (!qdev->client_monitors_config)
199257 return 0;
....@@ -203,59 +261,28 @@
203261 head = &qdev->client_monitors_config->heads[h];
204262 DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height);
205263
206
- mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
207
- false);
208
- mode->type |= DRM_MODE_TYPE_PREFERRED;
209
- mode->hdisplay = head->width;
210
- mode->vdisplay = head->height;
211
- drm_mode_set_name(mode);
212
- *pwidth = head->width;
213
- *pheight = head->height;
214
- drm_mode_probed_add(connector, mode);
215
- /* remember the last custom size for mode validation */
216
- qdev->monitors_config_width = mode->hdisplay;
217
- qdev->monitors_config_height = mode->vdisplay;
218
- return 1;
264
+ return qxl_add_mode(connector, head->width, head->height, true);
219265 }
220266
221267 static struct mode_size {
222268 int w;
223269 int h;
224
-} common_modes[] = {
225
- { 640, 480},
270
+} extra_modes[] = {
226271 { 720, 480},
227
- { 800, 600},
228
- { 848, 480},
229
- {1024, 768},
230272 {1152, 768},
231
- {1280, 720},
232
- {1280, 800},
233273 {1280, 854},
234
- {1280, 960},
235
- {1280, 1024},
236
- {1440, 900},
237
- {1400, 1050},
238
- {1680, 1050},
239
- {1600, 1200},
240
- {1920, 1080},
241
- {1920, 1200}
242274 };
243275
244
-static int qxl_add_common_modes(struct drm_connector *connector,
245
- unsigned pwidth,
246
- unsigned pheight)
276
+static int qxl_add_extra_modes(struct drm_connector *connector)
247277 {
248
- struct drm_device *dev = connector->dev;
249
- struct drm_display_mode *mode = NULL;
250
- int i;
251
- for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
252
- mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
253
- 60, false, false, false);
254
- if (common_modes[i].w == pwidth && common_modes[i].h == pheight)
255
- mode->type |= DRM_MODE_TYPE_PREFERRED;
256
- drm_mode_probed_add(connector, mode);
257
- }
258
- return i - 1;
278
+ int i, ret = 0;
279
+
280
+ for (i = 0; i < ARRAY_SIZE(extra_modes); i++)
281
+ ret += qxl_add_mode(connector,
282
+ extra_modes[i].w,
283
+ extra_modes[i].h,
284
+ false);
285
+ return ret;
259286 }
260287
261288 static void qxl_send_monitors_config(struct qxl_device *qdev)
....@@ -285,31 +312,34 @@
285312 const char *reason)
286313 {
287314 struct drm_device *dev = crtc->dev;
288
- struct qxl_device *qdev = dev->dev_private;
315
+ struct qxl_device *qdev = to_qxl(dev);
289316 struct qxl_crtc *qcrtc = to_qxl_crtc(crtc);
290317 struct qxl_head head;
291318 int oldcount, i = qcrtc->index;
292319
293
- if (!qdev->primary_created) {
320
+ if (!qdev->primary_bo) {
294321 DRM_DEBUG_KMS("no primary surface, skip (%s)\n", reason);
295322 return;
296323 }
297324
298
- if (!qdev->monitors_config ||
299
- qdev->monitors_config->max_allowed <= i)
325
+ if (!qdev->monitors_config || qxl_num_crtc <= i)
300326 return;
301327
302328 head.id = i;
303329 head.flags = 0;
330
+ head.surface_id = 0;
304331 oldcount = qdev->monitors_config->count;
305332 if (crtc->state->active) {
306333 struct drm_display_mode *mode = &crtc->mode;
334
+
307335 head.width = mode->hdisplay;
308336 head.height = mode->vdisplay;
309337 head.x = crtc->x;
310338 head.y = crtc->y;
311339 if (qdev->monitors_config->count < i + 1)
312340 qdev->monitors_config->count = i + 1;
341
+ if (qdev->primary_bo == qdev->dumb_shadow_bo)
342
+ head.x += qdev->dumb_heads[i].x;
313343 } else if (i > 0) {
314344 head.width = 0;
315345 head.height = 0;
....@@ -335,28 +365,16 @@
335365 if (oldcount != qdev->monitors_config->count)
336366 DRM_DEBUG_KMS("active heads %d -> %d (%d total)\n",
337367 oldcount, qdev->monitors_config->count,
338
- qdev->monitors_config->max_allowed);
368
+ qxl_num_crtc);
339369
340370 qdev->monitors_config->heads[i] = head;
371
+ qdev->monitors_config->max_allowed = qxl_num_crtc;
341372 qxl_send_monitors_config(qdev);
342373 }
343374
344375 static void qxl_crtc_atomic_flush(struct drm_crtc *crtc,
345376 struct drm_crtc_state *old_crtc_state)
346377 {
347
- struct drm_device *dev = crtc->dev;
348
- struct drm_pending_vblank_event *event;
349
- unsigned long flags;
350
-
351
- if (crtc->state && crtc->state->event) {
352
- event = crtc->state->event;
353
- crtc->state->event = NULL;
354
-
355
- spin_lock_irqsave(&dev->event_lock, flags);
356
- drm_crtc_send_vblank_event(crtc, event);
357
- spin_unlock_irqrestore(&dev->event_lock, flags);
358
- }
359
-
360378 qxl_crtc_update_monitors_config(crtc, "flush");
361379 }
362380
....@@ -378,38 +396,27 @@
378396 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
379397 };
380398
381
-void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
382
-{
383
- struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
384
- struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);
385
-
386
- WARN_ON(bo->shadow);
387
- drm_gem_object_put_unlocked(qxl_fb->obj);
388
- drm_framebuffer_cleanup(fb);
389
- kfree(qxl_fb);
390
-}
391
-
392399 static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
393400 struct drm_file *file_priv,
394
- unsigned flags, unsigned color,
401
+ unsigned int flags, unsigned int color,
395402 struct drm_clip_rect *clips,
396
- unsigned num_clips)
403
+ unsigned int num_clips)
397404 {
398405 /* TODO: vmwgfx where this was cribbed from had locking. Why? */
399
- struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
400
- struct qxl_device *qdev = qxl_fb->base.dev->dev_private;
406
+ struct qxl_device *qdev = to_qxl(fb->dev);
401407 struct drm_clip_rect norect;
402408 struct qxl_bo *qobj;
403
- int inc = 1;
409
+ struct drm_modeset_acquire_ctx ctx;
410
+ bool is_primary;
411
+ int inc = 1, ret;
404412
405
- drm_modeset_lock_all(fb->dev);
413
+ DRM_MODESET_LOCK_ALL_BEGIN(fb->dev, ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret);
406414
407
- qobj = gem_to_qxl_bo(qxl_fb->obj);
415
+ qobj = gem_to_qxl_bo(fb->obj[0]);
408416 /* if we aren't primary surface ignore this */
409
- if (!qobj->is_primary) {
410
- drm_modeset_unlock_all(fb->dev);
411
- return 0;
412
- }
417
+ is_primary = qobj->shadow ? qobj->shadow->is_primary : qobj->is_primary;
418
+ if (!is_primary)
419
+ goto out_lock_end;
413420
414421 if (!num_clips) {
415422 num_clips = 1;
....@@ -422,39 +429,20 @@
422429 inc = 2; /* skip source rects */
423430 }
424431
425
- qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color,
426
- clips, num_clips, inc);
432
+ qxl_draw_dirty_fb(qdev, fb, qobj, flags, color,
433
+ clips, num_clips, inc, 0);
427434
428
- drm_modeset_unlock_all(fb->dev);
435
+out_lock_end:
436
+ DRM_MODESET_LOCK_ALL_END(fb->dev, ctx, ret);
429437
430438 return 0;
431439 }
432440
433441 static const struct drm_framebuffer_funcs qxl_fb_funcs = {
434
- .destroy = qxl_user_framebuffer_destroy,
442
+ .destroy = drm_gem_fb_destroy,
435443 .dirty = qxl_framebuffer_surface_dirty,
436
-/* TODO?
437
- * .create_handle = qxl_user_framebuffer_create_handle, */
444
+ .create_handle = drm_gem_fb_create_handle,
438445 };
439
-
440
-int
441
-qxl_framebuffer_init(struct drm_device *dev,
442
- struct qxl_framebuffer *qfb,
443
- const struct drm_mode_fb_cmd2 *mode_cmd,
444
- struct drm_gem_object *obj,
445
- const struct drm_framebuffer_funcs *funcs)
446
-{
447
- int ret;
448
-
449
- qfb->obj = obj;
450
- drm_helper_mode_fill_fb_struct(dev, &qfb->base, mode_cmd);
451
- ret = drm_framebuffer_init(dev, &qfb->base, funcs);
452
- if (ret) {
453
- qfb->obj = NULL;
454
- return ret;
455
- }
456
- return 0;
457
-}
458446
459447 static void qxl_crtc_atomic_enable(struct drm_crtc *crtc,
460448 struct drm_crtc_state *old_state)
....@@ -477,28 +465,21 @@
477465 static int qxl_primary_atomic_check(struct drm_plane *plane,
478466 struct drm_plane_state *state)
479467 {
480
- struct qxl_device *qdev = plane->dev->dev_private;
481
- struct qxl_framebuffer *qfb;
468
+ struct qxl_device *qdev = to_qxl(plane->dev);
482469 struct qxl_bo *bo;
483470
484471 if (!state->crtc || !state->fb)
485472 return 0;
486473
487
- qfb = to_qxl_framebuffer(state->fb);
488
- bo = gem_to_qxl_bo(qfb->obj);
474
+ bo = gem_to_qxl_bo(state->fb->obj[0]);
489475
490
- if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
491
- DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
492
- return -EINVAL;
493
- }
494
-
495
- return 0;
476
+ return qxl_check_framebuffer(qdev, bo);
496477 }
497478
498479 static int qxl_primary_apply_cursor(struct drm_plane *plane)
499480 {
500481 struct drm_device *dev = plane->dev;
501
- struct qxl_device *qdev = dev->dev_private;
482
+ struct qxl_device *qdev = to_qxl(dev);
502483 struct drm_framebuffer *fb = plane->state->fb;
503484 struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
504485 struct qxl_cursor_cmd *cmd;
....@@ -545,65 +526,41 @@
545526 static void qxl_primary_atomic_update(struct drm_plane *plane,
546527 struct drm_plane_state *old_state)
547528 {
548
- struct qxl_device *qdev = plane->dev->dev_private;
549
- struct qxl_framebuffer *qfb =
550
- to_qxl_framebuffer(plane->state->fb);
551
- struct qxl_framebuffer *qfb_old;
552
- struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
553
- struct qxl_bo *bo_old;
529
+ struct qxl_device *qdev = to_qxl(plane->dev);
530
+ struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]);
531
+ struct qxl_bo *primary;
554532 struct drm_clip_rect norect = {
555533 .x1 = 0,
556534 .y1 = 0,
557
- .x2 = qfb->base.width,
558
- .y2 = qfb->base.height
535
+ .x2 = plane->state->fb->width,
536
+ .y2 = plane->state->fb->height
559537 };
560
- int ret;
561
- bool same_shadow = false;
538
+ uint32_t dumb_shadow_offset = 0;
562539
563
- if (old_state->fb) {
564
- qfb_old = to_qxl_framebuffer(old_state->fb);
565
- bo_old = gem_to_qxl_bo(qfb_old->obj);
566
- } else {
567
- bo_old = NULL;
568
- }
540
+ primary = bo->shadow ? bo->shadow : bo;
569541
570
- if (bo == bo_old)
571
- return;
572
-
573
- if (bo_old && bo_old->shadow && bo->shadow &&
574
- bo_old->shadow == bo->shadow) {
575
- same_shadow = true;
576
- }
577
-
578
- if (bo_old && bo_old->is_primary) {
579
- if (!same_shadow)
542
+ if (!primary->is_primary) {
543
+ if (qdev->primary_bo)
580544 qxl_io_destroy_primary(qdev);
581
- bo_old->is_primary = false;
582
-
583
- ret = qxl_primary_apply_cursor(plane);
584
- if (ret)
585
- DRM_ERROR(
586
- "could not set cursor after creating primary");
545
+ qxl_io_create_primary(qdev, primary);
546
+ qxl_primary_apply_cursor(plane);
587547 }
588548
589
- if (!bo->is_primary) {
590
- if (!same_shadow)
591
- qxl_io_create_primary(qdev, 0, bo);
592
- bo->is_primary = true;
593
- }
549
+ if (bo->is_dumb)
550
+ dumb_shadow_offset =
551
+ qdev->dumb_heads[plane->state->crtc->index].x;
594552
595
- qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
553
+ qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1,
554
+ dumb_shadow_offset);
596555 }
597556
598557 static void qxl_primary_atomic_disable(struct drm_plane *plane,
599558 struct drm_plane_state *old_state)
600559 {
601
- struct qxl_device *qdev = plane->dev->dev_private;
560
+ struct qxl_device *qdev = to_qxl(plane->dev);
602561
603562 if (old_state->fb) {
604
- struct qxl_framebuffer *qfb =
605
- to_qxl_framebuffer(old_state->fb);
606
- struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
563
+ struct qxl_bo *bo = gem_to_qxl_bo(old_state->fb->obj[0]);
607564
608565 if (bo->is_primary) {
609566 qxl_io_destroy_primary(qdev);
....@@ -616,7 +573,7 @@
616573 struct drm_plane_state *old_state)
617574 {
618575 struct drm_device *dev = plane->dev;
619
- struct qxl_device *qdev = dev->dev_private;
576
+ struct qxl_device *qdev = to_qxl(dev);
620577 struct drm_framebuffer *fb = plane->state->fb;
621578 struct qxl_crtc *qcrtc = to_qxl_crtc(plane->state->crtc);
622579 struct qxl_release *release;
....@@ -635,7 +592,7 @@
635592 return;
636593
637594 if (fb != old_state->fb) {
638
- obj = to_qxl_framebuffer(fb)->obj;
595
+ obj = fb->obj[0];
639596 user_bo = gem_to_qxl_bo(obj);
640597
641598 /* pinning is done in the prepare/cleanup framevbuffer */
....@@ -649,9 +606,13 @@
649606 if (ret)
650607 goto out_kunmap;
651608
652
- ret = qxl_release_reserve_list(release, true);
609
+ ret = qxl_bo_pin(cursor_bo);
653610 if (ret)
654611 goto out_free_bo;
612
+
613
+ ret = qxl_release_reserve_list(release, true);
614
+ if (ret)
615
+ goto out_unpin;
655616
656617 ret = qxl_bo_kmap(cursor_bo, (void **)&cursor);
657618 if (ret)
....@@ -697,15 +658,17 @@
697658 qxl_release_fence_buffer_objects(release);
698659 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
699660
700
- if (old_cursor_bo)
701
- qxl_bo_unref(&old_cursor_bo);
702
-
661
+ if (old_cursor_bo != NULL)
662
+ qxl_bo_unpin(old_cursor_bo);
663
+ qxl_bo_unref(&old_cursor_bo);
703664 qxl_bo_unref(&cursor_bo);
704665
705666 return;
706667
707668 out_backoff:
708669 qxl_release_backoff_reserve_list(release);
670
+out_unpin:
671
+ qxl_bo_unpin(cursor_bo);
709672 out_free_bo:
710673 qxl_bo_unref(&cursor_bo);
711674 out_kunmap:
....@@ -719,7 +682,7 @@
719682 static void qxl_cursor_atomic_disable(struct drm_plane *plane,
720683 struct drm_plane_state *old_state)
721684 {
722
- struct qxl_device *qdev = plane->dev->dev_private;
685
+ struct qxl_device *qdev = to_qxl(plane->dev);
723686 struct qxl_release *release;
724687 struct qxl_cursor_cmd *cmd;
725688 int ret;
....@@ -744,47 +707,105 @@
744707 qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
745708 }
746709
710
+static void qxl_update_dumb_head(struct qxl_device *qdev,
711
+ int index, struct qxl_bo *bo)
712
+{
713
+ uint32_t width, height;
714
+
715
+ if (index >= qdev->monitors_config->max_allowed)
716
+ return;
717
+
718
+ if (bo && bo->is_dumb) {
719
+ width = bo->surf.width;
720
+ height = bo->surf.height;
721
+ } else {
722
+ width = 0;
723
+ height = 0;
724
+ }
725
+
726
+ if (qdev->dumb_heads[index].width == width &&
727
+ qdev->dumb_heads[index].height == height)
728
+ return;
729
+
730
+ DRM_DEBUG("#%d: %dx%d -> %dx%d\n", index,
731
+ qdev->dumb_heads[index].width,
732
+ qdev->dumb_heads[index].height,
733
+ width, height);
734
+ qdev->dumb_heads[index].width = width;
735
+ qdev->dumb_heads[index].height = height;
736
+}
737
+
738
+static void qxl_calc_dumb_shadow(struct qxl_device *qdev,
739
+ struct qxl_surface *surf)
740
+{
741
+ struct qxl_head *head;
742
+ int i;
743
+
744
+ memset(surf, 0, sizeof(*surf));
745
+ for (i = 0; i < qdev->monitors_config->max_allowed; i++) {
746
+ head = qdev->dumb_heads + i;
747
+ head->x = surf->width;
748
+ surf->width += head->width;
749
+ if (surf->height < head->height)
750
+ surf->height = head->height;
751
+ }
752
+ if (surf->width < 64)
753
+ surf->width = 64;
754
+ if (surf->height < 64)
755
+ surf->height = 64;
756
+ surf->format = SPICE_SURFACE_FMT_32_xRGB;
757
+ surf->stride = surf->width * 4;
758
+
759
+ if (!qdev->dumb_shadow_bo ||
760
+ qdev->dumb_shadow_bo->surf.width != surf->width ||
761
+ qdev->dumb_shadow_bo->surf.height != surf->height)
762
+ DRM_DEBUG("%dx%d\n", surf->width, surf->height);
763
+}
764
+
747765 static int qxl_plane_prepare_fb(struct drm_plane *plane,
748766 struct drm_plane_state *new_state)
749767 {
750
- struct qxl_device *qdev = plane->dev->dev_private;
768
+ struct qxl_device *qdev = to_qxl(plane->dev);
751769 struct drm_gem_object *obj;
752
- struct qxl_bo *user_bo, *old_bo = NULL;
770
+ struct qxl_bo *user_bo;
771
+ struct qxl_surface surf;
753772 int ret;
754773
755774 if (!new_state->fb)
756775 return 0;
757776
758
- obj = to_qxl_framebuffer(new_state->fb)->obj;
777
+ obj = new_state->fb->obj[0];
759778 user_bo = gem_to_qxl_bo(obj);
760779
761780 if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
762
- user_bo->is_dumb && !user_bo->shadow) {
763
- if (plane->state->fb) {
764
- obj = to_qxl_framebuffer(plane->state->fb)->obj;
765
- old_bo = gem_to_qxl_bo(obj);
781
+ user_bo->is_dumb) {
782
+ qxl_update_dumb_head(qdev, new_state->crtc->index,
783
+ user_bo);
784
+ qxl_calc_dumb_shadow(qdev, &surf);
785
+ if (!qdev->dumb_shadow_bo ||
786
+ qdev->dumb_shadow_bo->surf.width != surf.width ||
787
+ qdev->dumb_shadow_bo->surf.height != surf.height) {
788
+ if (qdev->dumb_shadow_bo) {
789
+ drm_gem_object_put
790
+ (&qdev->dumb_shadow_bo->tbo.base);
791
+ qdev->dumb_shadow_bo = NULL;
792
+ }
793
+ qxl_bo_create(qdev, surf.height * surf.stride,
794
+ true, true, QXL_GEM_DOMAIN_SURFACE, 0,
795
+ &surf, &qdev->dumb_shadow_bo);
766796 }
767
- if (old_bo && old_bo->shadow &&
768
- user_bo->gem_base.size == old_bo->gem_base.size &&
769
- plane->state->crtc == new_state->crtc &&
770
- plane->state->crtc_w == new_state->crtc_w &&
771
- plane->state->crtc_h == new_state->crtc_h &&
772
- plane->state->src_x == new_state->src_x &&
773
- plane->state->src_y == new_state->src_y &&
774
- plane->state->src_w == new_state->src_w &&
775
- plane->state->src_h == new_state->src_h &&
776
- plane->state->rotation == new_state->rotation &&
777
- plane->state->zpos == new_state->zpos) {
778
- drm_gem_object_get(&old_bo->shadow->gem_base);
779
- user_bo->shadow = old_bo->shadow;
780
- } else {
781
- qxl_bo_create(qdev, user_bo->gem_base.size,
782
- true, true, QXL_GEM_DOMAIN_VRAM, NULL,
783
- &user_bo->shadow);
797
+ if (user_bo->shadow != qdev->dumb_shadow_bo) {
798
+ if (user_bo->shadow) {
799
+ drm_gem_object_put
800
+ (&user_bo->shadow->tbo.base);
801
+ user_bo->shadow = NULL;
802
+ }
803
+ drm_gem_object_get(&qdev->dumb_shadow_bo->tbo.base);
804
+ user_bo->shadow = qdev->dumb_shadow_bo;
784805 }
785806 }
786807
787
- ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL);
808
+ ret = qxl_bo_pin(user_bo);
788809 if (ret)
789810 return ret;
790811
....@@ -805,12 +826,12 @@
805826 return;
806827 }
807828
808
- obj = to_qxl_framebuffer(old_state->fb)->obj;
829
+ obj = old_state->fb->obj[0];
809830 user_bo = gem_to_qxl_bo(obj);
810831 qxl_bo_unpin(user_bo);
811832
812
- if (user_bo->shadow && !user_bo->is_primary) {
813
- drm_gem_object_put_unlocked(&user_bo->shadow->gem_base);
833
+ if (old_state->fb != plane->state->fb && user_bo->shadow) {
834
+ drm_gem_object_put(&user_bo->shadow->tbo.base);
814835 user_bo->shadow = NULL;
815836 }
816837 }
....@@ -905,7 +926,7 @@
905926 {
906927 struct qxl_crtc *qxl_crtc;
907928 struct drm_plane *primary, *cursor;
908
- struct qxl_device *qdev = dev->dev_private;
929
+ struct qxl_device *qdev = to_qxl(dev);
909930 int r;
910931
911932 qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL);
....@@ -946,14 +967,26 @@
946967
947968 static int qxl_conn_get_modes(struct drm_connector *connector)
948969 {
949
- unsigned pwidth = 1024;
950
- unsigned pheight = 768;
970
+ struct drm_device *dev = connector->dev;
971
+ struct qxl_device *qdev = to_qxl(dev);
972
+ struct qxl_output *output = drm_connector_to_qxl_output(connector);
973
+ unsigned int pwidth = 1024;
974
+ unsigned int pheight = 768;
951975 int ret = 0;
952976
953
- ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight);
954
- if (ret < 0)
955
- return ret;
956
- ret += qxl_add_common_modes(connector, pwidth, pheight);
977
+ if (qdev->client_monitors_config) {
978
+ struct qxl_head *head;
979
+ head = &qdev->client_monitors_config->heads[output->index];
980
+ if (head->width)
981
+ pwidth = head->width;
982
+ if (head->height)
983
+ pheight = head->height;
984
+ }
985
+
986
+ ret += drm_add_modes_noedid(connector, 8192, 8192);
987
+ ret += qxl_add_extra_modes(connector);
988
+ ret += qxl_add_monitors_config_modes(connector);
989
+ drm_set_preferred_mode(connector, pwidth, pheight);
957990 return ret;
958991 }
959992
....@@ -961,21 +994,12 @@
961994 struct drm_display_mode *mode)
962995 {
963996 struct drm_device *ddev = connector->dev;
964
- struct qxl_device *qdev = ddev->dev_private;
965
- int i;
997
+ struct qxl_device *qdev = to_qxl(ddev);
966998
967
- /* TODO: is this called for user defined modes? (xrandr --add-mode)
968
- * TODO: check that the mode fits in the framebuffer */
999
+ if (qxl_check_mode(qdev, mode->hdisplay, mode->vdisplay) != 0)
1000
+ return MODE_BAD;
9691001
970
- if(qdev->monitors_config_width == mode->hdisplay &&
971
- qdev->monitors_config_height == mode->vdisplay)
972
- return MODE_OK;
973
-
974
- for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
975
- if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
976
- return MODE_OK;
977
- }
978
- return MODE_BAD;
1002
+ return MODE_OK;
9791003 }
9801004
9811005 static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
....@@ -986,10 +1010,6 @@
9861010 DRM_DEBUG("\n");
9871011 return &qxl_output->enc;
9881012 }
989
-
990
-
991
-static const struct drm_encoder_helper_funcs qxl_enc_helper_funcs = {
992
-};
9931013
9941014 static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
9951015 .get_modes = qxl_conn_get_modes,
....@@ -1004,7 +1024,7 @@
10041024 struct qxl_output *output =
10051025 drm_connector_to_qxl_output(connector);
10061026 struct drm_device *ddev = connector->dev;
1007
- struct qxl_device *qdev = ddev->dev_private;
1027
+ struct qxl_device *qdev = to_qxl(ddev);
10081028 bool connected = false;
10091029
10101030 /* The first monitor is always connected */
....@@ -1032,22 +1052,12 @@
10321052 }
10331053
10341054 static const struct drm_connector_funcs qxl_connector_funcs = {
1035
- .dpms = drm_helper_connector_dpms,
10361055 .detect = qxl_conn_detect,
10371056 .fill_modes = drm_helper_probe_single_connector_modes,
10381057 .destroy = qxl_conn_destroy,
10391058 .reset = drm_atomic_helper_connector_reset,
10401059 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
10411060 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1042
-};
1043
-
1044
-static void qxl_enc_destroy(struct drm_encoder *encoder)
1045
-{
1046
- drm_encoder_cleanup(encoder);
1047
-}
1048
-
1049
-static const struct drm_encoder_funcs qxl_enc_funcs = {
1050
- .destroy = qxl_enc_destroy,
10511061 };
10521062
10531063 static int qxl_mode_create_hotplug_mode_update_property(struct qxl_device *qdev)
....@@ -1064,10 +1074,11 @@
10641074
10651075 static int qdev_output_init(struct drm_device *dev, int num_output)
10661076 {
1067
- struct qxl_device *qdev = dev->dev_private;
1077
+ struct qxl_device *qdev = to_qxl(dev);
10681078 struct qxl_output *qxl_output;
10691079 struct drm_connector *connector;
10701080 struct drm_encoder *encoder;
1081
+ int ret;
10711082
10721083 qxl_output = kzalloc(sizeof(struct qxl_output), GFP_KERNEL);
10731084 if (!qxl_output)
....@@ -1080,15 +1091,19 @@
10801091 drm_connector_init(dev, &qxl_output->base,
10811092 &qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
10821093
1083
- drm_encoder_init(dev, &qxl_output->enc, &qxl_enc_funcs,
1084
- DRM_MODE_ENCODER_VIRTUAL, NULL);
1094
+ ret = drm_simple_encoder_init(dev, &qxl_output->enc,
1095
+ DRM_MODE_ENCODER_VIRTUAL);
1096
+ if (ret) {
1097
+ drm_err(dev, "drm_simple_encoder_init() failed, error %d\n",
1098
+ ret);
1099
+ goto err_drm_connector_cleanup;
1100
+ }
10851101
10861102 /* we get HPD via client monitors config */
10871103 connector->polled = DRM_CONNECTOR_POLL_HPD;
10881104 encoder->possible_crtcs = 1 << num_output;
10891105 drm_connector_attach_encoder(&qxl_output->base,
10901106 &qxl_output->enc);
1091
- drm_encoder_helper_add(encoder, &qxl_enc_helper_funcs);
10921107 drm_connector_helper_add(connector, &qxl_connector_helper_funcs);
10931108
10941109 drm_object_attach_property(&connector->base,
....@@ -1098,6 +1113,11 @@
10981113 drm_object_attach_property(&connector->base,
10991114 dev->mode_config.suggested_y_property, 0);
11001115 return 0;
1116
+
1117
+err_drm_connector_cleanup:
1118
+ drm_connector_cleanup(&qxl_output->base);
1119
+ kfree(qxl_output);
1120
+ return ret;
11011121 }
11021122
11031123 static struct drm_framebuffer *
....@@ -1105,26 +1125,8 @@
11051125 struct drm_file *file_priv,
11061126 const struct drm_mode_fb_cmd2 *mode_cmd)
11071127 {
1108
- struct drm_gem_object *obj;
1109
- struct qxl_framebuffer *qxl_fb;
1110
- int ret;
1111
-
1112
- obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
1113
- if (!obj)
1114
- return NULL;
1115
-
1116
- qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL);
1117
- if (qxl_fb == NULL)
1118
- return NULL;
1119
-
1120
- ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
1121
- if (ret) {
1122
- kfree(qxl_fb);
1123
- drm_gem_object_put_unlocked(obj);
1124
- return NULL;
1125
- }
1126
-
1127
- return &qxl_fb->base;
1128
+ return drm_gem_fb_create_with_funcs(dev, file_priv, mode_cmd,
1129
+ &qxl_fb_funcs);
11281130 }
11291131
11301132 static const struct drm_mode_config_funcs qxl_mode_funcs = {
....@@ -1137,9 +1139,8 @@
11371139 {
11381140 int ret;
11391141 struct drm_gem_object *gobj;
1140
- int max_allowed = qxl_num_crtc;
11411142 int monitors_config_size = sizeof(struct qxl_monitors_config) +
1142
- max_allowed * sizeof(struct qxl_head);
1143
+ qxl_num_crtc * sizeof(struct qxl_head);
11431144
11441145 ret = qxl_gem_object_create(qdev, monitors_config_size, 0,
11451146 QXL_GEM_DOMAIN_VRAM,
....@@ -1150,7 +1151,7 @@
11501151 }
11511152 qdev->monitors_config_bo = gem_to_qxl_bo(gobj);
11521153
1153
- ret = qxl_bo_pin(qdev->monitors_config_bo, QXL_GEM_DOMAIN_VRAM, NULL);
1154
+ ret = qxl_bo_pin(qdev->monitors_config_bo);
11541155 if (ret)
11551156 return ret;
11561157
....@@ -1161,7 +1162,12 @@
11611162 qxl_bo_physical_address(qdev, qdev->monitors_config_bo, 0);
11621163
11631164 memset(qdev->monitors_config, 0, monitors_config_size);
1164
- qdev->monitors_config->max_allowed = max_allowed;
1165
+ qdev->dumb_heads = kcalloc(qxl_num_crtc, sizeof(qdev->dumb_heads[0]),
1166
+ GFP_KERNEL);
1167
+ if (!qdev->dumb_heads) {
1168
+ qxl_destroy_monitors_object(qdev);
1169
+ return -ENOMEM;
1170
+ }
11651171 return 0;
11661172 }
11671173
....@@ -1211,24 +1217,17 @@
12111217 }
12121218
12131219 qxl_display_read_client_monitors_config(qdev);
1214
- qdev->mode_info.mode_config_initialized = true;
12151220
12161221 drm_mode_config_reset(&qdev->ddev);
1217
-
1218
- /* primary surface must be created by this point, to allow
1219
- * issuing command queue commands and having them read by
1220
- * spice server. */
1221
- qxl_fbdev_init(qdev);
12221222 return 0;
12231223 }
12241224
12251225 void qxl_modeset_fini(struct qxl_device *qdev)
12261226 {
1227
- qxl_fbdev_fini(qdev);
1228
-
1229
- qxl_destroy_monitors_object(qdev);
1230
- if (qdev->mode_info.mode_config_initialized) {
1231
- drm_mode_config_cleanup(&qdev->ddev);
1232
- qdev->mode_info.mode_config_initialized = false;
1227
+ if (qdev->dumb_shadow_bo) {
1228
+ drm_gem_object_put(&qdev->dumb_shadow_bo->tbo.base);
1229
+ qdev->dumb_shadow_bo = NULL;
12331230 }
1231
+ qxl_destroy_monitors_object(qdev);
1232
+ drm_mode_config_cleanup(&qdev->ddev);
12341233 }