1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include <linux/export.h>
35#include <drm/drm_crtc_helper.h>
36#include <drm/drm_plane_helper.h>
37
38#include "vbox_drv.h"
39#include "vboxvideo.h"
40#include "hgsmi_channels.h"
41
42static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
43 u32 handle, u32 width, u32 height,
44 s32 hot_x, s32 hot_y);
45static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y);
46
47
48
49
50
51static void vbox_do_modeset(struct drm_crtc *crtc,
52 const struct drm_display_mode *mode)
53{
54 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
55 struct vbox_private *vbox;
56 int width, height, bpp, pitch;
57 u16 flags;
58 s32 x_offset, y_offset;
59
60 vbox = crtc->dev->dev_private;
61 width = mode->hdisplay ? mode->hdisplay : 640;
62 height = mode->vdisplay ? mode->vdisplay : 480;
63 bpp = crtc->enabled ? CRTC_FB(crtc)->format->cpp[0] * 8 : 32;
64 pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8;
65 x_offset = vbox->single_framebuffer ? crtc->x : vbox_crtc->x_hint;
66 y_offset = vbox->single_framebuffer ? crtc->y : vbox_crtc->y_hint;
67
68
69
70
71
72
73
74 if (vbox_crtc->crtc_id == 0 && crtc->enabled &&
75 vbox_crtc->fb_offset / pitch < 0xffff - crtc->y &&
76 vbox_crtc->fb_offset % (bpp / 8) == 0) {
77 vbox_write_ioport(VBE_DISPI_INDEX_XRES, width);
78 vbox_write_ioport(VBE_DISPI_INDEX_YRES, height);
79 vbox_write_ioport(VBE_DISPI_INDEX_VIRT_WIDTH, pitch * 8 / bpp);
80 vbox_write_ioport(VBE_DISPI_INDEX_BPP,
81 CRTC_FB(crtc)->format->cpp[0] * 8);
82 vbox_write_ioport(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
83 vbox_write_ioport(
84 VBE_DISPI_INDEX_X_OFFSET,
85 vbox_crtc->fb_offset % pitch / bpp * 8 + crtc->x);
86 vbox_write_ioport(VBE_DISPI_INDEX_Y_OFFSET,
87 vbox_crtc->fb_offset / pitch + crtc->y);
88 }
89
90 flags = VBVA_SCREEN_F_ACTIVE;
91 flags |= (crtc->enabled && !vbox_crtc->blanked) ?
92 0 : VBVA_SCREEN_F_BLANK;
93 flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0;
94 hgsmi_process_display_info(vbox->guest_pool, vbox_crtc->crtc_id,
95 x_offset, y_offset,
96 crtc->x * bpp / 8 + crtc->y * pitch,
97 pitch, width, height,
98 vbox_crtc->blanked ? 0 : bpp, flags);
99}
100
101static int vbox_set_view(struct drm_crtc *crtc)
102{
103 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
104 struct vbox_private *vbox = crtc->dev->dev_private;
105 struct vbva_infoview *p;
106
107
108
109
110
111
112
113
114
115
116
117
118 p = hgsmi_buffer_alloc(vbox->guest_pool, sizeof(*p),
119 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
120 if (!p)
121 return -ENOMEM;
122
123 p->view_index = vbox_crtc->crtc_id;
124 p->view_offset = vbox_crtc->fb_offset;
125 p->view_size = vbox->available_vram_size - vbox_crtc->fb_offset +
126 vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
127 p->max_screen_size = vbox->available_vram_size - vbox_crtc->fb_offset;
128
129 hgsmi_buffer_submit(vbox->guest_pool, p);
130 hgsmi_buffer_free(vbox->guest_pool, p);
131
132 return 0;
133}
134
135static void vbox_crtc_dpms(struct drm_crtc *crtc, int mode)
136{
137 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
138 struct vbox_private *vbox = crtc->dev->dev_private;
139
140 switch (mode) {
141 case DRM_MODE_DPMS_ON:
142 vbox_crtc->blanked = false;
143 break;
144 case DRM_MODE_DPMS_STANDBY:
145 case DRM_MODE_DPMS_SUSPEND:
146 case DRM_MODE_DPMS_OFF:
147 vbox_crtc->blanked = true;
148 break;
149 }
150
151 mutex_lock(&vbox->hw_mutex);
152 vbox_do_modeset(crtc, &crtc->hwmode);
153 mutex_unlock(&vbox->hw_mutex);
154}
155
156static bool vbox_crtc_mode_fixup(struct drm_crtc *crtc,
157 const struct drm_display_mode *mode,
158 struct drm_display_mode *adjusted_mode)
159{
160 return true;
161}
162
163
164
165
166
167
168static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
169{
170 struct drm_crtc *crtci;
171 struct drm_connector *connectori;
172 struct drm_framebuffer *fb1 = NULL;
173 bool single_framebuffer = true;
174 bool old_single_framebuffer = vbox->single_framebuffer;
175 u16 width = 0, height = 0;
176
177
178
179
180
181
182 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) {
183 if (!fb1) {
184 fb1 = CRTC_FB(crtci);
185 if (to_vbox_framebuffer(fb1) == &vbox->fbdev->afb)
186 break;
187 } else if (CRTC_FB(crtci) && fb1 != CRTC_FB(crtci)) {
188 single_framebuffer = false;
189 }
190 }
191 if (single_framebuffer) {
192 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
193 head) {
194 if (to_vbox_crtc(crtci)->crtc_id != 0)
195 continue;
196
197 vbox->single_framebuffer = true;
198 vbox->input_mapping_width = CRTC_FB(crtci)->width;
199 vbox->input_mapping_height = CRTC_FB(crtci)->height;
200 return old_single_framebuffer !=
201 vbox->single_framebuffer;
202 }
203 }
204
205 list_for_each_entry(connectori, &vbox->dev->mode_config.connector_list,
206 head) {
207 struct vbox_connector *vbox_connector =
208 to_vbox_connector(connectori);
209 struct vbox_crtc *vbox_crtc = vbox_connector->vbox_crtc;
210
211 width = max_t(u16, width, vbox_crtc->x_hint +
212 vbox_connector->mode_hint.width);
213 height = max_t(u16, height, vbox_crtc->y_hint +
214 vbox_connector->mode_hint.height);
215 }
216
217 vbox->single_framebuffer = false;
218 vbox->input_mapping_width = width;
219 vbox->input_mapping_height = height;
220
221 return old_single_framebuffer != vbox->single_framebuffer;
222}
223
224static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
225 struct drm_framebuffer *old_fb,
226 struct drm_framebuffer *new_fb,
227 int x, int y)
228{
229 struct vbox_private *vbox = crtc->dev->dev_private;
230 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
231 struct drm_gem_object *obj;
232 struct vbox_framebuffer *vbox_fb;
233 struct vbox_bo *bo;
234 int ret;
235 u64 gpu_addr;
236
237
238 if (old_fb) {
239 vbox_fb = to_vbox_framebuffer(old_fb);
240 obj = vbox_fb->obj;
241 bo = gem_to_vbox_bo(obj);
242 ret = vbox_bo_reserve(bo, false);
243 if (ret)
244 return ret;
245
246 vbox_bo_unpin(bo);
247 vbox_bo_unreserve(bo);
248 }
249
250 vbox_fb = to_vbox_framebuffer(new_fb);
251 obj = vbox_fb->obj;
252 bo = gem_to_vbox_bo(obj);
253
254 ret = vbox_bo_reserve(bo, false);
255 if (ret)
256 return ret;
257
258 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
259 if (ret) {
260 vbox_bo_unreserve(bo);
261 return ret;
262 }
263
264 if (&vbox->fbdev->afb == vbox_fb)
265 vbox_fbdev_set_base(vbox, gpu_addr);
266 vbox_bo_unreserve(bo);
267
268
269 vbox_crtc->fb_offset = gpu_addr;
270 if (vbox_set_up_input_mapping(vbox)) {
271 struct drm_crtc *crtci;
272
273 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
274 head) {
275 vbox_set_view(crtc);
276 vbox_do_modeset(crtci, &crtci->mode);
277 }
278 }
279
280 return 0;
281}
282
283static int vbox_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
284 struct drm_framebuffer *old_fb)
285{
286 return vbox_crtc_do_set_base(crtc, old_fb, CRTC_FB(crtc), x, y);
287}
288
289static int vbox_crtc_mode_set(struct drm_crtc *crtc,
290 struct drm_display_mode *mode,
291 struct drm_display_mode *adjusted_mode,
292 int x, int y, struct drm_framebuffer *old_fb)
293{
294 struct vbox_private *vbox = crtc->dev->dev_private;
295 int ret;
296
297 vbox_crtc_mode_set_base(crtc, x, y, old_fb);
298
299 mutex_lock(&vbox->hw_mutex);
300 ret = vbox_set_view(crtc);
301 if (!ret)
302 vbox_do_modeset(crtc, mode);
303 hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
304 vbox->input_mapping_width,
305 vbox->input_mapping_height);
306 mutex_unlock(&vbox->hw_mutex);
307
308 return ret;
309}
310
311static int vbox_crtc_page_flip(struct drm_crtc *crtc,
312 struct drm_framebuffer *fb,
313 struct drm_pending_vblank_event *event,
314 uint32_t page_flip_flags,
315 struct drm_modeset_acquire_ctx *ctx)
316{
317 struct vbox_private *vbox = crtc->dev->dev_private;
318 struct drm_device *drm = vbox->dev;
319 unsigned long flags;
320 int rc;
321
322 rc = vbox_crtc_do_set_base(crtc, CRTC_FB(crtc), fb, 0, 0);
323 if (rc)
324 return rc;
325
326 mutex_lock(&vbox->hw_mutex);
327 vbox_set_view(crtc);
328 vbox_do_modeset(crtc, &crtc->mode);
329 mutex_unlock(&vbox->hw_mutex);
330
331 spin_lock_irqsave(&drm->event_lock, flags);
332
333 if (event)
334 drm_crtc_send_vblank_event(crtc, event);
335
336 spin_unlock_irqrestore(&drm->event_lock, flags);
337
338 return 0;
339}
340
341static void vbox_crtc_disable(struct drm_crtc *crtc)
342{
343}
344
345static void vbox_crtc_prepare(struct drm_crtc *crtc)
346{
347}
348
349static void vbox_crtc_commit(struct drm_crtc *crtc)
350{
351}
352
353static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = {
354 .dpms = vbox_crtc_dpms,
355 .mode_fixup = vbox_crtc_mode_fixup,
356 .mode_set = vbox_crtc_mode_set,
357
358 .disable = vbox_crtc_disable,
359 .prepare = vbox_crtc_prepare,
360 .commit = vbox_crtc_commit,
361};
362
363static void vbox_crtc_reset(struct drm_crtc *crtc)
364{
365}
366
367static void vbox_crtc_destroy(struct drm_crtc *crtc)
368{
369 drm_crtc_cleanup(crtc);
370 kfree(crtc);
371}
372
373static const struct drm_crtc_funcs vbox_crtc_funcs = {
374 .cursor_move = vbox_cursor_move,
375 .cursor_set2 = vbox_cursor_set2,
376 .reset = vbox_crtc_reset,
377 .set_config = drm_crtc_helper_set_config,
378
379 .page_flip = vbox_crtc_page_flip,
380 .destroy = vbox_crtc_destroy,
381};
382
383static struct vbox_crtc *vbox_crtc_init(struct drm_device *dev, unsigned int i)
384{
385 struct vbox_crtc *vbox_crtc;
386
387 vbox_crtc = kzalloc(sizeof(*vbox_crtc), GFP_KERNEL);
388 if (!vbox_crtc)
389 return NULL;
390
391 vbox_crtc->crtc_id = i;
392
393 drm_crtc_init(dev, &vbox_crtc->base, &vbox_crtc_funcs);
394 drm_mode_crtc_set_gamma_size(&vbox_crtc->base, 256);
395 drm_crtc_helper_add(&vbox_crtc->base, &vbox_crtc_helper_funcs);
396
397 return vbox_crtc;
398}
399
400static void vbox_encoder_destroy(struct drm_encoder *encoder)
401{
402 drm_encoder_cleanup(encoder);
403 kfree(encoder);
404}
405
406static struct drm_encoder *vbox_best_single_encoder(struct drm_connector
407 *connector)
408{
409 int enc_id = connector->encoder_ids[0];
410
411
412 if (enc_id)
413 return drm_encoder_find(connector->dev, NULL, enc_id);
414
415 return NULL;
416}
417
418static const struct drm_encoder_funcs vbox_enc_funcs = {
419 .destroy = vbox_encoder_destroy,
420};
421
422static void vbox_encoder_dpms(struct drm_encoder *encoder, int mode)
423{
424}
425
426static bool vbox_mode_fixup(struct drm_encoder *encoder,
427 const struct drm_display_mode *mode,
428 struct drm_display_mode *adjusted_mode)
429{
430 return true;
431}
432
433static void vbox_encoder_mode_set(struct drm_encoder *encoder,
434 struct drm_display_mode *mode,
435 struct drm_display_mode *adjusted_mode)
436{
437}
438
439static void vbox_encoder_prepare(struct drm_encoder *encoder)
440{
441}
442
443static void vbox_encoder_commit(struct drm_encoder *encoder)
444{
445}
446
447static const struct drm_encoder_helper_funcs vbox_enc_helper_funcs = {
448 .dpms = vbox_encoder_dpms,
449 .mode_fixup = vbox_mode_fixup,
450 .prepare = vbox_encoder_prepare,
451 .commit = vbox_encoder_commit,
452 .mode_set = vbox_encoder_mode_set,
453};
454
455static struct drm_encoder *vbox_encoder_init(struct drm_device *dev,
456 unsigned int i)
457{
458 struct vbox_encoder *vbox_encoder;
459
460 vbox_encoder = kzalloc(sizeof(*vbox_encoder), GFP_KERNEL);
461 if (!vbox_encoder)
462 return NULL;
463
464 drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
465 DRM_MODE_ENCODER_DAC, NULL);
466 drm_encoder_helper_add(&vbox_encoder->base, &vbox_enc_helper_funcs);
467
468 vbox_encoder->base.possible_crtcs = 1 << i;
469 return &vbox_encoder->base;
470}
471
472
473
474
475
476
477
478static void vbox_set_edid(struct drm_connector *connector, int width,
479 int height)
480{
481 enum { EDID_SIZE = 128 };
482 unsigned char edid[EDID_SIZE] = {
483 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
484 0x58, 0x58,
485 0x00, 0x00,
486 0x00, 0x00, 0x00, 0x00,
487 0x01,
488 0x00,
489 0x01, 0x03,
490 0x80,
491 0x00,
492 0x00,
493 0x78,
494 0xEE,
495
496 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
497
498 0x00, 0x00, 0x00,
499 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
500 0x01, 0x01,
501 0x01, 0x01, 0x01, 0x01,
502 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x02, 0x02,
503 0x02, 0x02,
504
505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
506
507 0x00, 0x00, 0x00, 0xFD, 0x00,
508 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20,
509 0x20, 0x20,
510
511 0x20,
512
513 0x00, 0x00, 0x00, 0xFC, 0x00,
514 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r',
515 '\n',
516
517 0x00, 0x00, 0x00, 0x10, 0x00,
518 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
519 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
520 0x20,
521 0x00,
522 0x00
523 };
524 int clock = (width + 6) * (height + 6) * 60 / 10000;
525 unsigned int i, sum = 0;
526
527 edid[12] = width & 0xff;
528 edid[13] = width >> 8;
529 edid[14] = height & 0xff;
530 edid[15] = height >> 8;
531 edid[54] = clock & 0xff;
532 edid[55] = clock >> 8;
533 edid[56] = width & 0xff;
534 edid[58] = (width >> 4) & 0xf0;
535 edid[59] = height & 0xff;
536 edid[61] = (height >> 4) & 0xf0;
537 for (i = 0; i < EDID_SIZE - 1; ++i)
538 sum += edid[i];
539 edid[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
540 drm_connector_update_edid_property(connector, (struct edid *)edid);
541}
542
543static int vbox_get_modes(struct drm_connector *connector)
544{
545 struct vbox_connector *vbox_connector = NULL;
546 struct drm_display_mode *mode = NULL;
547 struct vbox_private *vbox = NULL;
548 unsigned int num_modes = 0;
549 int preferred_width, preferred_height;
550
551 vbox_connector = to_vbox_connector(connector);
552 vbox = connector->dev->dev_private;
553
554
555
556
557
558
559
560
561
562
563
564
565 hgsmi_report_flags_location(vbox->guest_pool, GUEST_HEAP_OFFSET(vbox) +
566 HOST_FLAGS_OFFSET);
567 if (vbox_connector->vbox_crtc->crtc_id == 0)
568 vbox_report_caps(vbox);
569 if (!vbox->initial_mode_queried) {
570 if (vbox_connector->vbox_crtc->crtc_id == 0) {
571 vbox->initial_mode_queried = true;
572 vbox_report_hotplug(vbox);
573 }
574 return drm_add_modes_noedid(connector, 800, 600);
575 }
576 num_modes = drm_add_modes_noedid(connector, 2560, 1600);
577 preferred_width = vbox_connector->mode_hint.width ?
578 vbox_connector->mode_hint.width : 1024;
579 preferred_height = vbox_connector->mode_hint.height ?
580 vbox_connector->mode_hint.height : 768;
581 mode = drm_cvt_mode(connector->dev, preferred_width, preferred_height,
582 60, false, false, false);
583 if (mode) {
584 mode->type |= DRM_MODE_TYPE_PREFERRED;
585 drm_mode_probed_add(connector, mode);
586 ++num_modes;
587 }
588 vbox_set_edid(connector, preferred_width, preferred_height);
589
590 if (vbox_connector->vbox_crtc->x_hint != -1)
591 drm_object_property_set_value(&connector->base,
592 vbox->dev->mode_config.suggested_x_property,
593 vbox_connector->vbox_crtc->x_hint);
594 else
595 drm_object_property_set_value(&connector->base,
596 vbox->dev->mode_config.suggested_x_property, 0);
597
598 if (vbox_connector->vbox_crtc->y_hint != -1)
599 drm_object_property_set_value(&connector->base,
600 vbox->dev->mode_config.suggested_y_property,
601 vbox_connector->vbox_crtc->y_hint);
602 else
603 drm_object_property_set_value(&connector->base,
604 vbox->dev->mode_config.suggested_y_property, 0);
605
606 return num_modes;
607}
608
609static enum drm_mode_status vbox_mode_valid(struct drm_connector *connector,
610 struct drm_display_mode *mode)
611{
612 return MODE_OK;
613}
614
615static void vbox_connector_destroy(struct drm_connector *connector)
616{
617 drm_connector_unregister(connector);
618 drm_connector_cleanup(connector);
619 kfree(connector);
620}
621
622static enum drm_connector_status
623vbox_connector_detect(struct drm_connector *connector, bool force)
624{
625 struct vbox_connector *vbox_connector;
626
627 vbox_connector = to_vbox_connector(connector);
628
629 return vbox_connector->mode_hint.disconnected ?
630 connector_status_disconnected : connector_status_connected;
631}
632
633static int vbox_fill_modes(struct drm_connector *connector, u32 max_x,
634 u32 max_y)
635{
636 struct vbox_connector *vbox_connector;
637 struct drm_device *dev;
638 struct drm_display_mode *mode, *iterator;
639
640 vbox_connector = to_vbox_connector(connector);
641 dev = vbox_connector->base.dev;
642 list_for_each_entry_safe(mode, iterator, &connector->modes, head) {
643 list_del(&mode->head);
644 drm_mode_destroy(dev, mode);
645 }
646
647 return drm_helper_probe_single_connector_modes(connector, max_x, max_y);
648}
649
650static const struct drm_connector_helper_funcs vbox_connector_helper_funcs = {
651 .mode_valid = vbox_mode_valid,
652 .get_modes = vbox_get_modes,
653 .best_encoder = vbox_best_single_encoder,
654};
655
656static const struct drm_connector_funcs vbox_connector_funcs = {
657 .dpms = drm_helper_connector_dpms,
658 .detect = vbox_connector_detect,
659 .fill_modes = vbox_fill_modes,
660 .destroy = vbox_connector_destroy,
661};
662
663static int vbox_connector_init(struct drm_device *dev,
664 struct vbox_crtc *vbox_crtc,
665 struct drm_encoder *encoder)
666{
667 struct vbox_connector *vbox_connector;
668 struct drm_connector *connector;
669
670 vbox_connector = kzalloc(sizeof(*vbox_connector), GFP_KERNEL);
671 if (!vbox_connector)
672 return -ENOMEM;
673
674 connector = &vbox_connector->base;
675 vbox_connector->vbox_crtc = vbox_crtc;
676
677 drm_connector_init(dev, connector, &vbox_connector_funcs,
678 DRM_MODE_CONNECTOR_VGA);
679 drm_connector_helper_add(connector, &vbox_connector_helper_funcs);
680
681 connector->interlace_allowed = 0;
682 connector->doublescan_allowed = 0;
683
684 drm_mode_create_suggested_offset_properties(dev);
685 drm_object_attach_property(&connector->base,
686 dev->mode_config.suggested_x_property, 0);
687 drm_object_attach_property(&connector->base,
688 dev->mode_config.suggested_y_property, 0);
689 drm_connector_register(connector);
690
691 drm_connector_attach_encoder(connector, encoder);
692
693 return 0;
694}
695
696int vbox_mode_init(struct drm_device *dev)
697{
698 struct vbox_private *vbox = dev->dev_private;
699 struct drm_encoder *encoder;
700 struct vbox_crtc *vbox_crtc;
701 unsigned int i;
702 int ret;
703
704
705 for (i = 0; i < vbox->num_crtcs; ++i) {
706 vbox_crtc = vbox_crtc_init(dev, i);
707 if (!vbox_crtc)
708 return -ENOMEM;
709 encoder = vbox_encoder_init(dev, i);
710 if (!encoder)
711 return -ENOMEM;
712 ret = vbox_connector_init(dev, vbox_crtc, encoder);
713 if (ret)
714 return ret;
715 }
716
717 return 0;
718}
719
720void vbox_mode_fini(struct drm_device *dev)
721{
722
723}
724
725
726
727
728
729
730static void copy_cursor_image(u8 *src, u8 *dst, u32 width, u32 height,
731 size_t mask_size)
732{
733 size_t line_size = (width + 7) / 8;
734 u32 i, j;
735
736 memcpy(dst + mask_size, src, width * height * 4);
737 for (i = 0; i < height; ++i)
738 for (j = 0; j < width; ++j)
739 if (((u32 *)src)[i * width + j] > 0xf0000000)
740 dst[i * line_size + j / 8] |= (0x80 >> (j % 8));
741}
742
743static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
744 u32 handle, u32 width, u32 height,
745 s32 hot_x, s32 hot_y)
746{
747 struct vbox_private *vbox = crtc->dev->dev_private;
748 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
749 struct ttm_bo_kmap_obj uobj_map;
750 size_t data_size, mask_size;
751 struct drm_gem_object *obj;
752 u32 flags, caps = 0;
753 struct vbox_bo *bo;
754 bool src_isiomem;
755 u8 *dst = NULL;
756 u8 *src;
757 int ret;
758
759
760
761
762
763 hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
764 vbox->input_mapping_width,
765 vbox->input_mapping_height);
766 if (!handle) {
767 bool cursor_enabled = false;
768 struct drm_crtc *crtci;
769
770
771 vbox_crtc->cursor_enabled = false;
772 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
773 head) {
774 if (to_vbox_crtc(crtci)->cursor_enabled)
775 cursor_enabled = true;
776 }
777
778 if (!cursor_enabled)
779 hgsmi_update_pointer_shape(vbox->guest_pool, 0, 0, 0,
780 0, 0, NULL, 0);
781 return 0;
782 }
783
784 vbox_crtc->cursor_enabled = true;
785
786 if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT ||
787 width == 0 || height == 0)
788 return -EINVAL;
789
790 ret = hgsmi_query_conf(vbox->guest_pool,
791 VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps);
792 if (ret)
793 return ret;
794
795 if (!(caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)) {
796
797
798
799
800 return -EBUSY;
801 }
802
803 obj = drm_gem_object_lookup(file_priv, handle);
804 if (!obj) {
805 DRM_ERROR("Cannot find cursor object %x for crtc\n", handle);
806 return -ENOENT;
807 }
808
809 bo = gem_to_vbox_bo(obj);
810 ret = vbox_bo_reserve(bo, false);
811 if (ret)
812 goto out_unref_obj;
813
814
815
816
817
818
819 mask_size = ((width + 7) / 8 * height + 3) & ~3;
820 data_size = width * height * 4 + mask_size;
821 vbox->cursor_hot_x = min_t(u32, max(hot_x, 0), width);
822 vbox->cursor_hot_y = min_t(u32, max(hot_y, 0), height);
823 vbox->cursor_width = width;
824 vbox->cursor_height = height;
825 vbox->cursor_data_size = data_size;
826 dst = vbox->cursor_data;
827
828 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map);
829 if (ret) {
830 vbox->cursor_data_size = 0;
831 goto out_unreserve_bo;
832 }
833
834 src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem);
835 if (src_isiomem) {
836 DRM_ERROR("src cursor bo not in main memory\n");
837 ret = -EIO;
838 goto out_unmap_bo;
839 }
840
841 copy_cursor_image(src, dst, width, height, mask_size);
842
843 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
844 VBOX_MOUSE_POINTER_ALPHA;
845 ret = hgsmi_update_pointer_shape(vbox->guest_pool, flags,
846 vbox->cursor_hot_x, vbox->cursor_hot_y,
847 width, height, dst, data_size);
848out_unmap_bo:
849 ttm_bo_kunmap(&uobj_map);
850out_unreserve_bo:
851 vbox_bo_unreserve(bo);
852out_unref_obj:
853 drm_gem_object_put_unlocked(obj);
854
855 return ret;
856}
857
858static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y)
859{
860 struct vbox_private *vbox = crtc->dev->dev_private;
861 u32 flags = VBOX_MOUSE_POINTER_VISIBLE |
862 VBOX_MOUSE_POINTER_SHAPE | VBOX_MOUSE_POINTER_ALPHA;
863 s32 crtc_x =
864 vbox->single_framebuffer ? crtc->x : to_vbox_crtc(crtc)->x_hint;
865 s32 crtc_y =
866 vbox->single_framebuffer ? crtc->y : to_vbox_crtc(crtc)->y_hint;
867 u32 host_x, host_y;
868 u32 hot_x = 0;
869 u32 hot_y = 0;
870 int ret;
871
872
873
874
875
876 if (x + crtc_x < 0 || y + crtc_y < 0 || vbox->cursor_data_size == 0)
877 return 0;
878
879 ret = hgsmi_cursor_position(vbox->guest_pool, true, x + crtc_x,
880 y + crtc_y, &host_x, &host_y);
881
882
883
884
885
886
887
888
889
890
891
892
893 if (ret || (host_x == 0 && host_y == 0))
894 return ret;
895
896 if (x + crtc_x < host_x)
897 hot_x = min(host_x - x - crtc_x, vbox->cursor_width);
898 if (y + crtc_y < host_y)
899 hot_y = min(host_y - y - crtc_y, vbox->cursor_height);
900
901 if (hot_x == vbox->cursor_hot_x && hot_y == vbox->cursor_hot_y)
902 return 0;
903
904 vbox->cursor_hot_x = hot_x;
905 vbox->cursor_hot_y = hot_y;
906
907 return hgsmi_update_pointer_shape(vbox->guest_pool, flags,
908 hot_x, hot_y, vbox->cursor_width, vbox->cursor_height,
909 vbox->cursor_data, vbox->cursor_data_size);
910}
911