1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/dma-buf-map.h>
14#include <linux/export.h>
15
16#include <drm/drm_atomic.h>
17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_fb_helper.h>
19#include <drm/drm_fourcc.h>
20#include <drm/drm_gem_framebuffer_helper.h>
21#include <drm/drm_plane_helper.h>
22#include <drm/drm_probe_helper.h>
23
24#include "hgsmi_channels.h"
25#include "vbox_drv.h"
26#include "vboxvideo.h"
27
28
29
30
31
32static void vbox_do_modeset(struct drm_crtc *crtc)
33{
34 struct drm_framebuffer *fb = crtc->primary->state->fb;
35 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
36 struct vbox_private *vbox;
37 int width, height, bpp, pitch;
38 u16 flags;
39 s32 x_offset, y_offset;
40
41 vbox = to_vbox_dev(crtc->dev);
42 width = vbox_crtc->width ? vbox_crtc->width : 640;
43 height = vbox_crtc->height ? vbox_crtc->height : 480;
44 bpp = fb ? fb->format->cpp[0] * 8 : 32;
45 pitch = fb ? fb->pitches[0] : width * bpp / 8;
46 x_offset = vbox->single_framebuffer ? vbox_crtc->x : vbox_crtc->x_hint;
47 y_offset = vbox->single_framebuffer ? vbox_crtc->y : vbox_crtc->y_hint;
48
49
50
51
52
53
54
55 if (vbox_crtc->crtc_id == 0 && fb &&
56 vbox_crtc->fb_offset / pitch < 0xffff - crtc->y &&
57 vbox_crtc->fb_offset % (bpp / 8) == 0) {
58 vbox_write_ioport(VBE_DISPI_INDEX_XRES, width);
59 vbox_write_ioport(VBE_DISPI_INDEX_YRES, height);
60 vbox_write_ioport(VBE_DISPI_INDEX_VIRT_WIDTH, pitch * 8 / bpp);
61 vbox_write_ioport(VBE_DISPI_INDEX_BPP, bpp);
62 vbox_write_ioport(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
63 vbox_write_ioport(VBE_DISPI_INDEX_X_OFFSET,
64 vbox_crtc->fb_offset % pitch / bpp * 8 + vbox_crtc->x);
65 vbox_write_ioport(VBE_DISPI_INDEX_Y_OFFSET,
66 vbox_crtc->fb_offset / pitch + vbox_crtc->y);
67 }
68
69 flags = VBVA_SCREEN_F_ACTIVE;
70 flags |= (fb && crtc->state->enable) ? 0 : VBVA_SCREEN_F_BLANK;
71 flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0;
72 hgsmi_process_display_info(vbox->guest_pool, vbox_crtc->crtc_id,
73 x_offset, y_offset,
74 vbox_crtc->x * bpp / 8 +
75 vbox_crtc->y * pitch,
76 pitch, width, height, bpp, flags);
77}
78
79static int vbox_set_view(struct drm_crtc *crtc)
80{
81 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
82 struct vbox_private *vbox = to_vbox_dev(crtc->dev);
83 struct vbva_infoview *p;
84
85
86
87
88
89
90
91
92
93
94
95
96 p = hgsmi_buffer_alloc(vbox->guest_pool, sizeof(*p),
97 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
98 if (!p)
99 return -ENOMEM;
100
101 p->view_index = vbox_crtc->crtc_id;
102 p->view_offset = vbox_crtc->fb_offset;
103 p->view_size = vbox->available_vram_size - vbox_crtc->fb_offset +
104 vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
105 p->max_screen_size = vbox->available_vram_size - vbox_crtc->fb_offset;
106
107 hgsmi_buffer_submit(vbox->guest_pool, p);
108 hgsmi_buffer_free(vbox->guest_pool, p);
109
110 return 0;
111}
112
113
114
115
116
117
118static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
119{
120 struct drm_crtc *crtci;
121 struct drm_connector *connectori;
122 struct drm_framebuffer *fb, *fb1 = NULL;
123 bool single_framebuffer = true;
124 bool old_single_framebuffer = vbox->single_framebuffer;
125 u16 width = 0, height = 0;
126
127
128
129
130
131
132 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list, head) {
133 fb = crtci->primary->state->fb;
134 if (!fb)
135 continue;
136
137 if (!fb1) {
138 fb1 = fb;
139 if (fb1 == vbox->ddev.fb_helper->fb)
140 break;
141 } else if (fb != fb1) {
142 single_framebuffer = false;
143 }
144 }
145 if (!fb1)
146 return false;
147
148 if (single_framebuffer) {
149 vbox->single_framebuffer = true;
150 vbox->input_mapping_width = fb1->width;
151 vbox->input_mapping_height = fb1->height;
152 return old_single_framebuffer != vbox->single_framebuffer;
153 }
154
155 list_for_each_entry(connectori, &vbox->ddev.mode_config.connector_list,
156 head) {
157 struct vbox_connector *vbox_connector =
158 to_vbox_connector(connectori);
159 struct vbox_crtc *vbox_crtc = vbox_connector->vbox_crtc;
160
161 width = max_t(u16, width, vbox_crtc->x_hint +
162 vbox_connector->mode_hint.width);
163 height = max_t(u16, height, vbox_crtc->y_hint +
164 vbox_connector->mode_hint.height);
165 }
166
167 vbox->single_framebuffer = false;
168 vbox->input_mapping_width = width;
169 vbox->input_mapping_height = height;
170
171 return old_single_framebuffer != vbox->single_framebuffer;
172}
173
174static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc,
175 struct drm_framebuffer *fb,
176 int x, int y)
177{
178 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(fb->obj[0]);
179 struct vbox_private *vbox = to_vbox_dev(crtc->dev);
180 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
181 bool needs_modeset = drm_atomic_crtc_needs_modeset(crtc->state);
182
183 mutex_lock(&vbox->hw_mutex);
184
185 if (crtc->state->enable) {
186 vbox_crtc->width = crtc->state->mode.hdisplay;
187 vbox_crtc->height = crtc->state->mode.vdisplay;
188 }
189
190 vbox_crtc->x = x;
191 vbox_crtc->y = y;
192 vbox_crtc->fb_offset = drm_gem_vram_offset(gbo);
193
194
195 if (needs_modeset && vbox_set_up_input_mapping(vbox)) {
196 struct drm_crtc *crtci;
197
198 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list,
199 head) {
200 if (crtci == crtc)
201 continue;
202 vbox_do_modeset(crtci);
203 }
204 }
205
206 vbox_set_view(crtc);
207 vbox_do_modeset(crtc);
208
209 if (needs_modeset)
210 hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
211 vbox->input_mapping_width,
212 vbox->input_mapping_height);
213
214 mutex_unlock(&vbox->hw_mutex);
215}
216
217static void vbox_crtc_atomic_enable(struct drm_crtc *crtc,
218 struct drm_atomic_state *state)
219{
220}
221
222static void vbox_crtc_atomic_disable(struct drm_crtc *crtc,
223 struct drm_atomic_state *state)
224{
225}
226
227static void vbox_crtc_atomic_flush(struct drm_crtc *crtc,
228 struct drm_atomic_state *state)
229{
230}
231
232static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = {
233 .atomic_enable = vbox_crtc_atomic_enable,
234 .atomic_disable = vbox_crtc_atomic_disable,
235 .atomic_flush = vbox_crtc_atomic_flush,
236};
237
238static void vbox_crtc_destroy(struct drm_crtc *crtc)
239{
240 drm_crtc_cleanup(crtc);
241 kfree(crtc);
242}
243
244static const struct drm_crtc_funcs vbox_crtc_funcs = {
245 .set_config = drm_atomic_helper_set_config,
246 .page_flip = drm_atomic_helper_page_flip,
247
248 .destroy = vbox_crtc_destroy,
249 .reset = drm_atomic_helper_crtc_reset,
250 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
251 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
252};
253
254static int vbox_primary_atomic_check(struct drm_plane *plane,
255 struct drm_plane_state *new_state)
256{
257 struct drm_crtc_state *crtc_state = NULL;
258
259 if (new_state->crtc) {
260 crtc_state = drm_atomic_get_existing_crtc_state(
261 new_state->state, new_state->crtc);
262 if (WARN_ON(!crtc_state))
263 return -EINVAL;
264 }
265
266 return drm_atomic_helper_check_plane_state(new_state, crtc_state,
267 DRM_PLANE_HELPER_NO_SCALING,
268 DRM_PLANE_HELPER_NO_SCALING,
269 false, true);
270}
271
272static void vbox_primary_atomic_update(struct drm_plane *plane,
273 struct drm_plane_state *old_state)
274{
275 struct drm_crtc *crtc = plane->state->crtc;
276 struct drm_framebuffer *fb = plane->state->fb;
277 struct vbox_private *vbox = to_vbox_dev(fb->dev);
278 struct drm_mode_rect *clips;
279 uint32_t num_clips, i;
280
281 vbox_crtc_set_base_and_mode(crtc, fb,
282 plane->state->src_x >> 16,
283 plane->state->src_y >> 16);
284
285
286
287 clips = drm_plane_get_damage_clips(plane->state);
288 num_clips = drm_plane_get_damage_clips_count(plane->state);
289
290 if (!num_clips)
291 return;
292
293 mutex_lock(&vbox->hw_mutex);
294
295 for (i = 0; i < num_clips; ++i, ++clips) {
296 struct vbva_cmd_hdr cmd_hdr;
297 unsigned int crtc_id = to_vbox_crtc(crtc)->crtc_id;
298
299 cmd_hdr.x = (s16)clips->x1;
300 cmd_hdr.y = (s16)clips->y1;
301 cmd_hdr.w = (u16)clips->x2 - clips->x1;
302 cmd_hdr.h = (u16)clips->y2 - clips->y1;
303
304 if (!vbva_buffer_begin_update(&vbox->vbva_info[crtc_id],
305 vbox->guest_pool))
306 continue;
307
308 vbva_write(&vbox->vbva_info[crtc_id], vbox->guest_pool,
309 &cmd_hdr, sizeof(cmd_hdr));
310 vbva_buffer_end_update(&vbox->vbva_info[crtc_id]);
311 }
312
313 mutex_unlock(&vbox->hw_mutex);
314}
315
316static void vbox_primary_atomic_disable(struct drm_plane *plane,
317 struct drm_plane_state *old_state)
318{
319 struct drm_crtc *crtc = old_state->crtc;
320
321
322 vbox_crtc_set_base_and_mode(crtc, old_state->fb,
323 old_state->src_x >> 16,
324 old_state->src_y >> 16);
325}
326
327static int vbox_cursor_atomic_check(struct drm_plane *plane,
328 struct drm_plane_state *new_state)
329{
330 struct drm_crtc_state *crtc_state = NULL;
331 u32 width = new_state->crtc_w;
332 u32 height = new_state->crtc_h;
333 int ret;
334
335 if (new_state->crtc) {
336 crtc_state = drm_atomic_get_existing_crtc_state(
337 new_state->state, new_state->crtc);
338 if (WARN_ON(!crtc_state))
339 return -EINVAL;
340 }
341
342 ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
343 DRM_PLANE_HELPER_NO_SCALING,
344 DRM_PLANE_HELPER_NO_SCALING,
345 true, true);
346 if (ret)
347 return ret;
348
349 if (!new_state->fb)
350 return 0;
351
352 if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT ||
353 width == 0 || height == 0)
354 return -EINVAL;
355
356 return 0;
357}
358
359
360
361
362
363
364static void copy_cursor_image(u8 *src, u8 *dst, u32 width, u32 height,
365 size_t mask_size)
366{
367 size_t line_size = (width + 7) / 8;
368 u32 i, j;
369
370 memcpy(dst + mask_size, src, width * height * 4);
371 for (i = 0; i < height; ++i)
372 for (j = 0; j < width; ++j)
373 if (((u32 *)src)[i * width + j] > 0xf0000000)
374 dst[i * line_size + j / 8] |= (0x80 >> (j % 8));
375}
376
377static void vbox_cursor_atomic_update(struct drm_plane *plane,
378 struct drm_plane_state *old_state)
379{
380 struct vbox_private *vbox =
381 container_of(plane->dev, struct vbox_private, ddev);
382 struct vbox_crtc *vbox_crtc = to_vbox_crtc(plane->state->crtc);
383 struct drm_framebuffer *fb = plane->state->fb;
384 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(fb->obj[0]);
385 u32 width = plane->state->crtc_w;
386 u32 height = plane->state->crtc_h;
387 size_t data_size, mask_size;
388 u32 flags;
389 struct dma_buf_map map;
390 int ret;
391 u8 *src;
392
393
394
395
396
397 if (fb == old_state->fb)
398 return;
399
400 mutex_lock(&vbox->hw_mutex);
401
402 vbox_crtc->cursor_enabled = true;
403
404 ret = drm_gem_vram_vmap(gbo, &map);
405 if (ret) {
406
407
408
409 mutex_unlock(&vbox->hw_mutex);
410 DRM_WARN("Could not map cursor bo, skipping update\n");
411 return;
412 }
413 src = map.vaddr;
414
415
416
417
418
419
420 mask_size = ((width + 7) / 8 * height + 3) & ~3;
421 data_size = width * height * 4 + mask_size;
422
423 copy_cursor_image(src, vbox->cursor_data, width, height, mask_size);
424 drm_gem_vram_vunmap(gbo, &map);
425
426 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
427 VBOX_MOUSE_POINTER_ALPHA;
428 hgsmi_update_pointer_shape(vbox->guest_pool, flags,
429 min_t(u32, max(fb->hot_x, 0), width),
430 min_t(u32, max(fb->hot_y, 0), height),
431 width, height, vbox->cursor_data, data_size);
432
433 mutex_unlock(&vbox->hw_mutex);
434}
435
436static void vbox_cursor_atomic_disable(struct drm_plane *plane,
437 struct drm_plane_state *old_state)
438{
439 struct vbox_private *vbox =
440 container_of(plane->dev, struct vbox_private, ddev);
441 struct vbox_crtc *vbox_crtc = to_vbox_crtc(old_state->crtc);
442 bool cursor_enabled = false;
443 struct drm_crtc *crtci;
444
445 mutex_lock(&vbox->hw_mutex);
446
447 vbox_crtc->cursor_enabled = false;
448
449 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list, head) {
450 if (to_vbox_crtc(crtci)->cursor_enabled)
451 cursor_enabled = true;
452 }
453
454 if (!cursor_enabled)
455 hgsmi_update_pointer_shape(vbox->guest_pool, 0, 0, 0,
456 0, 0, NULL, 0);
457
458 mutex_unlock(&vbox->hw_mutex);
459}
460
461static const u32 vbox_cursor_plane_formats[] = {
462 DRM_FORMAT_ARGB8888,
463};
464
465static const struct drm_plane_helper_funcs vbox_cursor_helper_funcs = {
466 .atomic_check = vbox_cursor_atomic_check,
467 .atomic_update = vbox_cursor_atomic_update,
468 .atomic_disable = vbox_cursor_atomic_disable,
469 .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
470 .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
471};
472
473static const struct drm_plane_funcs vbox_cursor_plane_funcs = {
474 .update_plane = drm_atomic_helper_update_plane,
475 .disable_plane = drm_atomic_helper_disable_plane,
476 .destroy = drm_primary_helper_destroy,
477 .reset = drm_atomic_helper_plane_reset,
478 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
479 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
480};
481
482static const u32 vbox_primary_plane_formats[] = {
483 DRM_FORMAT_XRGB8888,
484 DRM_FORMAT_ARGB8888,
485};
486
487static const struct drm_plane_helper_funcs vbox_primary_helper_funcs = {
488 .atomic_check = vbox_primary_atomic_check,
489 .atomic_update = vbox_primary_atomic_update,
490 .atomic_disable = vbox_primary_atomic_disable,
491 .prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
492 .cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
493};
494
495static const struct drm_plane_funcs vbox_primary_plane_funcs = {
496 .update_plane = drm_atomic_helper_update_plane,
497 .disable_plane = drm_atomic_helper_disable_plane,
498 .destroy = drm_primary_helper_destroy,
499 .reset = drm_atomic_helper_plane_reset,
500 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
501 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
502};
503
504static struct drm_plane *vbox_create_plane(struct vbox_private *vbox,
505 unsigned int possible_crtcs,
506 enum drm_plane_type type)
507{
508 const struct drm_plane_helper_funcs *helper_funcs = NULL;
509 const struct drm_plane_funcs *funcs;
510 struct drm_plane *plane;
511 const u32 *formats;
512 int num_formats;
513 int err;
514
515 if (type == DRM_PLANE_TYPE_PRIMARY) {
516 funcs = &vbox_primary_plane_funcs;
517 formats = vbox_primary_plane_formats;
518 helper_funcs = &vbox_primary_helper_funcs;
519 num_formats = ARRAY_SIZE(vbox_primary_plane_formats);
520 } else if (type == DRM_PLANE_TYPE_CURSOR) {
521 funcs = &vbox_cursor_plane_funcs;
522 formats = vbox_cursor_plane_formats;
523 helper_funcs = &vbox_cursor_helper_funcs;
524 num_formats = ARRAY_SIZE(vbox_cursor_plane_formats);
525 } else {
526 return ERR_PTR(-EINVAL);
527 }
528
529 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
530 if (!plane)
531 return ERR_PTR(-ENOMEM);
532
533 err = drm_universal_plane_init(&vbox->ddev, plane, possible_crtcs,
534 funcs, formats, num_formats,
535 NULL, type, NULL);
536 if (err)
537 goto free_plane;
538
539 drm_plane_helper_add(plane, helper_funcs);
540
541 return plane;
542
543free_plane:
544 kfree(plane);
545 return ERR_PTR(-EINVAL);
546}
547
548static struct vbox_crtc *vbox_crtc_init(struct drm_device *dev, unsigned int i)
549{
550 struct vbox_private *vbox =
551 container_of(dev, struct vbox_private, ddev);
552 struct drm_plane *cursor = NULL;
553 struct vbox_crtc *vbox_crtc;
554 struct drm_plane *primary;
555 u32 caps = 0;
556 int ret;
557
558 ret = hgsmi_query_conf(vbox->guest_pool,
559 VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps);
560 if (ret)
561 return ERR_PTR(ret);
562
563 vbox_crtc = kzalloc(sizeof(*vbox_crtc), GFP_KERNEL);
564 if (!vbox_crtc)
565 return ERR_PTR(-ENOMEM);
566
567 primary = vbox_create_plane(vbox, 1 << i, DRM_PLANE_TYPE_PRIMARY);
568 if (IS_ERR(primary)) {
569 ret = PTR_ERR(primary);
570 goto free_mem;
571 }
572
573 if ((caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)) {
574 cursor = vbox_create_plane(vbox, 1 << i, DRM_PLANE_TYPE_CURSOR);
575 if (IS_ERR(cursor)) {
576 ret = PTR_ERR(cursor);
577 goto clean_primary;
578 }
579 } else {
580 DRM_WARN("VirtualBox host is too old, no cursor support\n");
581 }
582
583 vbox_crtc->crtc_id = i;
584
585 ret = drm_crtc_init_with_planes(dev, &vbox_crtc->base, primary, cursor,
586 &vbox_crtc_funcs, NULL);
587 if (ret)
588 goto clean_cursor;
589
590 drm_mode_crtc_set_gamma_size(&vbox_crtc->base, 256);
591 drm_crtc_helper_add(&vbox_crtc->base, &vbox_crtc_helper_funcs);
592
593 return vbox_crtc;
594
595clean_cursor:
596 if (cursor) {
597 drm_plane_cleanup(cursor);
598 kfree(cursor);
599 }
600clean_primary:
601 drm_plane_cleanup(primary);
602 kfree(primary);
603free_mem:
604 kfree(vbox_crtc);
605 return ERR_PTR(ret);
606}
607
608static void vbox_encoder_destroy(struct drm_encoder *encoder)
609{
610 drm_encoder_cleanup(encoder);
611 kfree(encoder);
612}
613
614static const struct drm_encoder_funcs vbox_enc_funcs = {
615 .destroy = vbox_encoder_destroy,
616};
617
618static struct drm_encoder *vbox_encoder_init(struct drm_device *dev,
619 unsigned int i)
620{
621 struct vbox_encoder *vbox_encoder;
622
623 vbox_encoder = kzalloc(sizeof(*vbox_encoder), GFP_KERNEL);
624 if (!vbox_encoder)
625 return NULL;
626
627 drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
628 DRM_MODE_ENCODER_DAC, NULL);
629
630 vbox_encoder->base.possible_crtcs = 1 << i;
631 return &vbox_encoder->base;
632}
633
634
635
636
637
638
639
640static void vbox_set_edid(struct drm_connector *connector, int width,
641 int height)
642{
643 enum { EDID_SIZE = 128 };
644 unsigned char edid[EDID_SIZE] = {
645 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
646 0x58, 0x58,
647 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00,
649 0x01,
650 0x00,
651 0x01, 0x03,
652 0x80,
653 0x00,
654 0x00,
655 0x78,
656 0xEE,
657
658 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
659
660 0x00, 0x00, 0x00,
661 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
662 0x01, 0x01,
663 0x01, 0x01, 0x01, 0x01,
664 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x02, 0x02,
665 0x02, 0x02,
666
667 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668
669 0x00, 0x00, 0x00, 0xFD, 0x00,
670 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20,
671 0x20, 0x20,
672
673 0x20,
674
675 0x00, 0x00, 0x00, 0xFC, 0x00,
676 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r',
677 '\n',
678
679 0x00, 0x00, 0x00, 0x10, 0x00,
680 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
681 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
682 0x20,
683 0x00,
684 0x00
685 };
686 int clock = (width + 6) * (height + 6) * 60 / 10000;
687 unsigned int i, sum = 0;
688
689 edid[12] = width & 0xff;
690 edid[13] = width >> 8;
691 edid[14] = height & 0xff;
692 edid[15] = height >> 8;
693 edid[54] = clock & 0xff;
694 edid[55] = clock >> 8;
695 edid[56] = width & 0xff;
696 edid[58] = (width >> 4) & 0xf0;
697 edid[59] = height & 0xff;
698 edid[61] = (height >> 4) & 0xf0;
699 for (i = 0; i < EDID_SIZE - 1; ++i)
700 sum += edid[i];
701 edid[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
702 drm_connector_update_edid_property(connector, (struct edid *)edid);
703}
704
705static int vbox_get_modes(struct drm_connector *connector)
706{
707 struct vbox_connector *vbox_connector = NULL;
708 struct drm_display_mode *mode = NULL;
709 struct vbox_private *vbox = NULL;
710 unsigned int num_modes = 0;
711 int preferred_width, preferred_height;
712
713 vbox_connector = to_vbox_connector(connector);
714 vbox = to_vbox_dev(connector->dev);
715
716 hgsmi_report_flags_location(vbox->guest_pool, GUEST_HEAP_OFFSET(vbox) +
717 HOST_FLAGS_OFFSET);
718 if (vbox_connector->vbox_crtc->crtc_id == 0)
719 vbox_report_caps(vbox);
720
721 num_modes = drm_add_modes_noedid(connector, 2560, 1600);
722 preferred_width = vbox_connector->mode_hint.width ?
723 vbox_connector->mode_hint.width : 1024;
724 preferred_height = vbox_connector->mode_hint.height ?
725 vbox_connector->mode_hint.height : 768;
726 mode = drm_cvt_mode(connector->dev, preferred_width, preferred_height,
727 60, false, false, false);
728 if (mode) {
729 mode->type |= DRM_MODE_TYPE_PREFERRED;
730 drm_mode_probed_add(connector, mode);
731 ++num_modes;
732 }
733 vbox_set_edid(connector, preferred_width, preferred_height);
734
735 if (vbox_connector->vbox_crtc->x_hint != -1)
736 drm_object_property_set_value(&connector->base,
737 vbox->ddev.mode_config.suggested_x_property,
738 vbox_connector->vbox_crtc->x_hint);
739 else
740 drm_object_property_set_value(&connector->base,
741 vbox->ddev.mode_config.suggested_x_property, 0);
742
743 if (vbox_connector->vbox_crtc->y_hint != -1)
744 drm_object_property_set_value(&connector->base,
745 vbox->ddev.mode_config.suggested_y_property,
746 vbox_connector->vbox_crtc->y_hint);
747 else
748 drm_object_property_set_value(&connector->base,
749 vbox->ddev.mode_config.suggested_y_property, 0);
750
751 return num_modes;
752}
753
754static void vbox_connector_destroy(struct drm_connector *connector)
755{
756 drm_connector_unregister(connector);
757 drm_connector_cleanup(connector);
758 kfree(connector);
759}
760
761static enum drm_connector_status
762vbox_connector_detect(struct drm_connector *connector, bool force)
763{
764 struct vbox_connector *vbox_connector;
765
766 vbox_connector = to_vbox_connector(connector);
767
768 return vbox_connector->mode_hint.disconnected ?
769 connector_status_disconnected : connector_status_connected;
770}
771
772static int vbox_fill_modes(struct drm_connector *connector, u32 max_x,
773 u32 max_y)
774{
775 struct vbox_connector *vbox_connector;
776 struct drm_device *dev;
777 struct drm_display_mode *mode, *iterator;
778
779 vbox_connector = to_vbox_connector(connector);
780 dev = vbox_connector->base.dev;
781 list_for_each_entry_safe(mode, iterator, &connector->modes, head) {
782 list_del(&mode->head);
783 drm_mode_destroy(dev, mode);
784 }
785
786 return drm_helper_probe_single_connector_modes(connector, max_x, max_y);
787}
788
789static const struct drm_connector_helper_funcs vbox_connector_helper_funcs = {
790 .get_modes = vbox_get_modes,
791};
792
793static const struct drm_connector_funcs vbox_connector_funcs = {
794 .detect = vbox_connector_detect,
795 .fill_modes = vbox_fill_modes,
796 .destroy = vbox_connector_destroy,
797 .reset = drm_atomic_helper_connector_reset,
798 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
799 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
800};
801
802static int vbox_connector_init(struct drm_device *dev,
803 struct vbox_crtc *vbox_crtc,
804 struct drm_encoder *encoder)
805{
806 struct vbox_connector *vbox_connector;
807 struct drm_connector *connector;
808
809 vbox_connector = kzalloc(sizeof(*vbox_connector), GFP_KERNEL);
810 if (!vbox_connector)
811 return -ENOMEM;
812
813 connector = &vbox_connector->base;
814 vbox_connector->vbox_crtc = vbox_crtc;
815
816 drm_connector_init(dev, connector, &vbox_connector_funcs,
817 DRM_MODE_CONNECTOR_VGA);
818 drm_connector_helper_add(connector, &vbox_connector_helper_funcs);
819
820 connector->interlace_allowed = 0;
821 connector->doublescan_allowed = 0;
822
823 drm_mode_create_suggested_offset_properties(dev);
824 drm_object_attach_property(&connector->base,
825 dev->mode_config.suggested_x_property, 0);
826 drm_object_attach_property(&connector->base,
827 dev->mode_config.suggested_y_property, 0);
828
829 drm_connector_attach_encoder(connector, encoder);
830
831 return 0;
832}
833
834static const struct drm_mode_config_funcs vbox_mode_funcs = {
835 .fb_create = drm_gem_fb_create_with_dirty,
836 .mode_valid = drm_vram_helper_mode_valid,
837 .atomic_check = drm_atomic_helper_check,
838 .atomic_commit = drm_atomic_helper_commit,
839};
840
841int vbox_mode_init(struct vbox_private *vbox)
842{
843 struct drm_device *dev = &vbox->ddev;
844 struct drm_encoder *encoder;
845 struct vbox_crtc *vbox_crtc;
846 unsigned int i;
847 int ret;
848
849 drm_mode_config_init(dev);
850
851 dev->mode_config.funcs = (void *)&vbox_mode_funcs;
852 dev->mode_config.min_width = 0;
853 dev->mode_config.min_height = 0;
854 dev->mode_config.preferred_depth = 24;
855 dev->mode_config.max_width = VBE_DISPI_MAX_XRES;
856 dev->mode_config.max_height = VBE_DISPI_MAX_YRES;
857
858 for (i = 0; i < vbox->num_crtcs; ++i) {
859 vbox_crtc = vbox_crtc_init(dev, i);
860 if (IS_ERR(vbox_crtc)) {
861 ret = PTR_ERR(vbox_crtc);
862 goto err_drm_mode_cleanup;
863 }
864 encoder = vbox_encoder_init(dev, i);
865 if (!encoder) {
866 ret = -ENOMEM;
867 goto err_drm_mode_cleanup;
868 }
869 ret = vbox_connector_init(dev, vbox_crtc, encoder);
870 if (ret)
871 goto err_drm_mode_cleanup;
872 }
873
874 drm_mode_config_reset(dev);
875 return 0;
876
877err_drm_mode_cleanup:
878 drm_mode_config_cleanup(dev);
879 return ret;
880}
881
882void vbox_mode_fini(struct vbox_private *vbox)
883{
884 drm_mode_config_cleanup(&vbox->ddev);
885}
886