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_atomic_helper.h>
21#include <drm/drm_gem_framebuffer_helper.h>
22#include <drm/drm_plane_helper.h>
23#include <drm/drm_probe_helper.h>
24
25#include "hgsmi_channels.h"
26#include "vbox_drv.h"
27#include "vboxvideo.h"
28
29
30
31
32
33static void vbox_do_modeset(struct drm_crtc *crtc)
34{
35 struct drm_framebuffer *fb = crtc->primary->state->fb;
36 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
37 struct vbox_private *vbox;
38 int width, height, bpp, pitch;
39 u16 flags;
40 s32 x_offset, y_offset;
41
42 vbox = to_vbox_dev(crtc->dev);
43 width = vbox_crtc->width ? vbox_crtc->width : 640;
44 height = vbox_crtc->height ? vbox_crtc->height : 480;
45 bpp = fb ? fb->format->cpp[0] * 8 : 32;
46 pitch = fb ? fb->pitches[0] : width * bpp / 8;
47 x_offset = vbox->single_framebuffer ? vbox_crtc->x : vbox_crtc->x_hint;
48 y_offset = vbox->single_framebuffer ? vbox_crtc->y : vbox_crtc->y_hint;
49
50
51
52
53
54
55
56 if (vbox_crtc->crtc_id == 0 && fb &&
57 vbox_crtc->fb_offset / pitch < 0xffff - crtc->y &&
58 vbox_crtc->fb_offset % (bpp / 8) == 0) {
59 vbox_write_ioport(VBE_DISPI_INDEX_XRES, width);
60 vbox_write_ioport(VBE_DISPI_INDEX_YRES, height);
61 vbox_write_ioport(VBE_DISPI_INDEX_VIRT_WIDTH, pitch * 8 / bpp);
62 vbox_write_ioport(VBE_DISPI_INDEX_BPP, bpp);
63 vbox_write_ioport(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
64 vbox_write_ioport(VBE_DISPI_INDEX_X_OFFSET,
65 vbox_crtc->fb_offset % pitch / bpp * 8 + vbox_crtc->x);
66 vbox_write_ioport(VBE_DISPI_INDEX_Y_OFFSET,
67 vbox_crtc->fb_offset / pitch + vbox_crtc->y);
68 }
69
70 flags = VBVA_SCREEN_F_ACTIVE;
71 flags |= (fb && crtc->state->enable) ? 0 : VBVA_SCREEN_F_BLANK;
72 flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0;
73 hgsmi_process_display_info(vbox->guest_pool, vbox_crtc->crtc_id,
74 x_offset, y_offset,
75 vbox_crtc->x * bpp / 8 +
76 vbox_crtc->y * pitch,
77 pitch, width, height, bpp, flags);
78}
79
80static int vbox_set_view(struct drm_crtc *crtc)
81{
82 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
83 struct vbox_private *vbox = to_vbox_dev(crtc->dev);
84 struct vbva_infoview *p;
85
86
87
88
89
90
91
92
93
94
95
96
97 p = hgsmi_buffer_alloc(vbox->guest_pool, sizeof(*p),
98 HGSMI_CH_VBVA, VBVA_INFO_VIEW);
99 if (!p)
100 return -ENOMEM;
101
102 p->view_index = vbox_crtc->crtc_id;
103 p->view_offset = vbox_crtc->fb_offset;
104 p->view_size = vbox->available_vram_size - vbox_crtc->fb_offset +
105 vbox_crtc->crtc_id * VBVA_MIN_BUFFER_SIZE;
106 p->max_screen_size = vbox->available_vram_size - vbox_crtc->fb_offset;
107
108 hgsmi_buffer_submit(vbox->guest_pool, p);
109 hgsmi_buffer_free(vbox->guest_pool, p);
110
111 return 0;
112}
113
114
115
116
117
118
119static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
120{
121 struct drm_crtc *crtci;
122 struct drm_connector *connectori;
123 struct drm_framebuffer *fb, *fb1 = NULL;
124 bool single_framebuffer = true;
125 bool old_single_framebuffer = vbox->single_framebuffer;
126 u16 width = 0, height = 0;
127
128
129
130
131
132
133 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list, head) {
134 fb = crtci->primary->state->fb;
135 if (!fb)
136 continue;
137
138 if (!fb1) {
139 fb1 = fb;
140 if (fb1 == vbox->ddev.fb_helper->fb)
141 break;
142 } else if (fb != fb1) {
143 single_framebuffer = false;
144 }
145 }
146 if (!fb1)
147 return false;
148
149 if (single_framebuffer) {
150 vbox->single_framebuffer = true;
151 vbox->input_mapping_width = fb1->width;
152 vbox->input_mapping_height = fb1->height;
153 return old_single_framebuffer != vbox->single_framebuffer;
154 }
155
156 list_for_each_entry(connectori, &vbox->ddev.mode_config.connector_list,
157 head) {
158 struct vbox_connector *vbox_connector =
159 to_vbox_connector(connectori);
160 struct vbox_crtc *vbox_crtc = vbox_connector->vbox_crtc;
161
162 width = max_t(u16, width, vbox_crtc->x_hint +
163 vbox_connector->mode_hint.width);
164 height = max_t(u16, height, vbox_crtc->y_hint +
165 vbox_connector->mode_hint.height);
166 }
167
168 vbox->single_framebuffer = false;
169 vbox->input_mapping_width = width;
170 vbox->input_mapping_height = height;
171
172 return old_single_framebuffer != vbox->single_framebuffer;
173}
174
175static void vbox_crtc_set_base_and_mode(struct drm_crtc *crtc,
176 struct drm_framebuffer *fb,
177 int x, int y)
178{
179 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(fb->obj[0]);
180 struct vbox_private *vbox = to_vbox_dev(crtc->dev);
181 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
182 bool needs_modeset = drm_atomic_crtc_needs_modeset(crtc->state);
183
184 mutex_lock(&vbox->hw_mutex);
185
186 if (crtc->state->enable) {
187 vbox_crtc->width = crtc->state->mode.hdisplay;
188 vbox_crtc->height = crtc->state->mode.vdisplay;
189 }
190
191 vbox_crtc->x = x;
192 vbox_crtc->y = y;
193 vbox_crtc->fb_offset = drm_gem_vram_offset(gbo);
194
195
196 if (needs_modeset && vbox_set_up_input_mapping(vbox)) {
197 struct drm_crtc *crtci;
198
199 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list,
200 head) {
201 if (crtci == crtc)
202 continue;
203 vbox_do_modeset(crtci);
204 }
205 }
206
207 vbox_set_view(crtc);
208 vbox_do_modeset(crtc);
209
210 if (needs_modeset)
211 hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
212 vbox->input_mapping_width,
213 vbox->input_mapping_height);
214
215 mutex_unlock(&vbox->hw_mutex);
216}
217
218static void vbox_crtc_atomic_enable(struct drm_crtc *crtc,
219 struct drm_atomic_state *state)
220{
221}
222
223static void vbox_crtc_atomic_disable(struct drm_crtc *crtc,
224 struct drm_atomic_state *state)
225{
226}
227
228static void vbox_crtc_atomic_flush(struct drm_crtc *crtc,
229 struct drm_atomic_state *state)
230{
231}
232
233static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = {
234 .atomic_enable = vbox_crtc_atomic_enable,
235 .atomic_disable = vbox_crtc_atomic_disable,
236 .atomic_flush = vbox_crtc_atomic_flush,
237};
238
239static void vbox_crtc_destroy(struct drm_crtc *crtc)
240{
241 drm_crtc_cleanup(crtc);
242 kfree(crtc);
243}
244
245static const struct drm_crtc_funcs vbox_crtc_funcs = {
246 .set_config = drm_atomic_helper_set_config,
247 .page_flip = drm_atomic_helper_page_flip,
248
249 .destroy = vbox_crtc_destroy,
250 .reset = drm_atomic_helper_crtc_reset,
251 .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
252 .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
253};
254
255static int vbox_primary_atomic_check(struct drm_plane *plane,
256 struct drm_atomic_state *state)
257{
258 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
259 plane);
260 struct drm_crtc_state *crtc_state = NULL;
261
262 if (new_state->crtc) {
263 crtc_state = drm_atomic_get_existing_crtc_state(state,
264 new_state->crtc);
265 if (WARN_ON(!crtc_state))
266 return -EINVAL;
267 }
268
269 return drm_atomic_helper_check_plane_state(new_state, crtc_state,
270 DRM_PLANE_HELPER_NO_SCALING,
271 DRM_PLANE_HELPER_NO_SCALING,
272 false, true);
273}
274
275static void vbox_primary_atomic_update(struct drm_plane *plane,
276 struct drm_atomic_state *state)
277{
278 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
279 plane);
280 struct drm_crtc *crtc = new_state->crtc;
281 struct drm_framebuffer *fb = new_state->fb;
282 struct vbox_private *vbox = to_vbox_dev(fb->dev);
283 struct drm_mode_rect *clips;
284 uint32_t num_clips, i;
285
286 vbox_crtc_set_base_and_mode(crtc, fb,
287 new_state->src_x >> 16,
288 new_state->src_y >> 16);
289
290
291
292 clips = drm_plane_get_damage_clips(new_state);
293 num_clips = drm_plane_get_damage_clips_count(new_state);
294
295 if (!num_clips)
296 return;
297
298 mutex_lock(&vbox->hw_mutex);
299
300 for (i = 0; i < num_clips; ++i, ++clips) {
301 struct vbva_cmd_hdr cmd_hdr;
302 unsigned int crtc_id = to_vbox_crtc(crtc)->crtc_id;
303
304 cmd_hdr.x = (s16)clips->x1;
305 cmd_hdr.y = (s16)clips->y1;
306 cmd_hdr.w = (u16)clips->x2 - clips->x1;
307 cmd_hdr.h = (u16)clips->y2 - clips->y1;
308
309 if (!vbva_buffer_begin_update(&vbox->vbva_info[crtc_id],
310 vbox->guest_pool))
311 continue;
312
313 vbva_write(&vbox->vbva_info[crtc_id], vbox->guest_pool,
314 &cmd_hdr, sizeof(cmd_hdr));
315 vbva_buffer_end_update(&vbox->vbva_info[crtc_id]);
316 }
317
318 mutex_unlock(&vbox->hw_mutex);
319}
320
321static void vbox_primary_atomic_disable(struct drm_plane *plane,
322 struct drm_atomic_state *state)
323{
324 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
325 plane);
326 struct drm_crtc *crtc = old_state->crtc;
327
328
329 vbox_crtc_set_base_and_mode(crtc, old_state->fb,
330 old_state->src_x >> 16,
331 old_state->src_y >> 16);
332}
333
334static int vbox_cursor_atomic_check(struct drm_plane *plane,
335 struct drm_atomic_state *state)
336{
337 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
338 plane);
339 struct drm_crtc_state *crtc_state = NULL;
340 u32 width = new_state->crtc_w;
341 u32 height = new_state->crtc_h;
342 int ret;
343
344 if (new_state->crtc) {
345 crtc_state = drm_atomic_get_existing_crtc_state(state,
346 new_state->crtc);
347 if (WARN_ON(!crtc_state))
348 return -EINVAL;
349 }
350
351 ret = drm_atomic_helper_check_plane_state(new_state, crtc_state,
352 DRM_PLANE_HELPER_NO_SCALING,
353 DRM_PLANE_HELPER_NO_SCALING,
354 true, true);
355 if (ret)
356 return ret;
357
358 if (!new_state->fb)
359 return 0;
360
361 if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT ||
362 width == 0 || height == 0)
363 return -EINVAL;
364
365 return 0;
366}
367
368
369
370
371
372
373static void copy_cursor_image(u8 *src, u8 *dst, u32 width, u32 height,
374 size_t mask_size)
375{
376 size_t line_size = (width + 7) / 8;
377 u32 i, j;
378
379 memcpy(dst + mask_size, src, width * height * 4);
380 for (i = 0; i < height; ++i)
381 for (j = 0; j < width; ++j)
382 if (((u32 *)src)[i * width + j] > 0xf0000000)
383 dst[i * line_size + j / 8] |= (0x80 >> (j % 8));
384}
385
386static void vbox_cursor_atomic_update(struct drm_plane *plane,
387 struct drm_atomic_state *state)
388{
389 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
390 plane);
391 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
392 plane);
393 struct vbox_private *vbox =
394 container_of(plane->dev, struct vbox_private, ddev);
395 struct vbox_crtc *vbox_crtc = to_vbox_crtc(new_state->crtc);
396 struct drm_framebuffer *fb = new_state->fb;
397 u32 width = new_state->crtc_w;
398 u32 height = new_state->crtc_h;
399 struct drm_shadow_plane_state *shadow_plane_state =
400 to_drm_shadow_plane_state(new_state);
401 struct dma_buf_map map = shadow_plane_state->map[0];
402 u8 *src = map.vaddr;
403 size_t data_size, mask_size;
404 u32 flags;
405
406
407
408
409
410 if (fb == old_state->fb)
411 return;
412
413 mutex_lock(&vbox->hw_mutex);
414
415 vbox_crtc->cursor_enabled = true;
416
417
418
419
420
421
422 mask_size = ((width + 7) / 8 * height + 3) & ~3;
423 data_size = width * height * 4 + mask_size;
424
425 copy_cursor_image(src, vbox->cursor_data, width, height, mask_size);
426
427 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE |
428 VBOX_MOUSE_POINTER_ALPHA;
429 hgsmi_update_pointer_shape(vbox->guest_pool, flags,
430 min_t(u32, max(fb->hot_x, 0), width),
431 min_t(u32, max(fb->hot_y, 0), height),
432 width, height, vbox->cursor_data, data_size);
433
434 mutex_unlock(&vbox->hw_mutex);
435}
436
437static void vbox_cursor_atomic_disable(struct drm_plane *plane,
438 struct drm_atomic_state *state)
439{
440 struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
441 plane);
442 struct vbox_private *vbox =
443 container_of(plane->dev, struct vbox_private, ddev);
444 struct vbox_crtc *vbox_crtc = to_vbox_crtc(old_state->crtc);
445 bool cursor_enabled = false;
446 struct drm_crtc *crtci;
447
448 mutex_lock(&vbox->hw_mutex);
449
450 vbox_crtc->cursor_enabled = false;
451
452 list_for_each_entry(crtci, &vbox->ddev.mode_config.crtc_list, head) {
453 if (to_vbox_crtc(crtci)->cursor_enabled)
454 cursor_enabled = true;
455 }
456
457 if (!cursor_enabled)
458 hgsmi_update_pointer_shape(vbox->guest_pool, 0, 0, 0,
459 0, 0, NULL, 0);
460
461 mutex_unlock(&vbox->hw_mutex);
462}
463
464static const u32 vbox_cursor_plane_formats[] = {
465 DRM_FORMAT_ARGB8888,
466};
467
468static const struct drm_plane_helper_funcs vbox_cursor_helper_funcs = {
469 .atomic_check = vbox_cursor_atomic_check,
470 .atomic_update = vbox_cursor_atomic_update,
471 .atomic_disable = vbox_cursor_atomic_disable,
472 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
473};
474
475static const struct drm_plane_funcs vbox_cursor_plane_funcs = {
476 .update_plane = drm_atomic_helper_update_plane,
477 .disable_plane = drm_atomic_helper_disable_plane,
478 .destroy = drm_primary_helper_destroy,
479 DRM_GEM_SHADOW_PLANE_FUNCS,
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