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->data[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 DRM_GEM_VRAM_PLANE_HELPER_FUNCS,
492};
493
494static const struct drm_plane_funcs vbox_primary_plane_funcs = {
495 .update_plane = drm_atomic_helper_update_plane,
496 .disable_plane = drm_atomic_helper_disable_plane,
497 .destroy = drm_primary_helper_destroy,
498 .reset = drm_atomic_helper_plane_reset,
499 .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
500 .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
501};
502
503static struct drm_plane *vbox_create_plane(struct vbox_private *vbox,
504 unsigned int possible_crtcs,
505 enum drm_plane_type type)
506{
507 const struct drm_plane_helper_funcs *helper_funcs = NULL;
508 const struct drm_plane_funcs *funcs;
509 struct drm_plane *plane;
510 const u32 *formats;
511 int num_formats;
512 int err;
513
514 if (type == DRM_PLANE_TYPE_PRIMARY) {
515 funcs = &vbox_primary_plane_funcs;
516 formats = vbox_primary_plane_formats;
517 helper_funcs = &vbox_primary_helper_funcs;
518 num_formats = ARRAY_SIZE(vbox_primary_plane_formats);
519 } else if (type == DRM_PLANE_TYPE_CURSOR) {
520 funcs = &vbox_cursor_plane_funcs;
521 formats = vbox_cursor_plane_formats;
522 helper_funcs = &vbox_cursor_helper_funcs;
523 num_formats = ARRAY_SIZE(vbox_cursor_plane_formats);
524 } else {
525 return ERR_PTR(-EINVAL);
526 }
527
528 plane = kzalloc(sizeof(*plane), GFP_KERNEL);
529 if (!plane)
530 return ERR_PTR(-ENOMEM);
531
532 err = drm_universal_plane_init(&vbox->ddev, plane, possible_crtcs,
533 funcs, formats, num_formats,
534 NULL, type, NULL);
535 if (err)
536 goto free_plane;
537
538 drm_plane_helper_add(plane, helper_funcs);
539
540 return plane;
541
542free_plane:
543 kfree(plane);
544 return ERR_PTR(-EINVAL);
545}
546
547static struct vbox_crtc *vbox_crtc_init(struct drm_device *dev, unsigned int i)
548{
549 struct vbox_private *vbox =
550 container_of(dev, struct vbox_private, ddev);
551 struct drm_plane *cursor = NULL;
552 struct vbox_crtc *vbox_crtc;
553 struct drm_plane *primary;
554 u32 caps = 0;
555 int ret;
556
557 ret = hgsmi_query_conf(vbox->guest_pool,
558 VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps);
559 if (ret)
560 return ERR_PTR(ret);
561
562 vbox_crtc = kzalloc(sizeof(*vbox_crtc), GFP_KERNEL);
563 if (!vbox_crtc)
564 return ERR_PTR(-ENOMEM);
565
566 primary = vbox_create_plane(vbox, 1 << i, DRM_PLANE_TYPE_PRIMARY);
567 if (IS_ERR(primary)) {
568 ret = PTR_ERR(primary);
569 goto free_mem;
570 }
571
572 if ((caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)) {
573 cursor = vbox_create_plane(vbox, 1 << i, DRM_PLANE_TYPE_CURSOR);
574 if (IS_ERR(cursor)) {
575 ret = PTR_ERR(cursor);
576 goto clean_primary;
577 }
578 } else {
579 DRM_WARN("VirtualBox host is too old, no cursor support\n");
580 }
581
582 vbox_crtc->crtc_id = i;
583
584 ret = drm_crtc_init_with_planes(dev, &vbox_crtc->base, primary, cursor,
585 &vbox_crtc_funcs, NULL);
586 if (ret)
587 goto clean_cursor;
588
589 drm_mode_crtc_set_gamma_size(&vbox_crtc->base, 256);
590 drm_crtc_helper_add(&vbox_crtc->base, &vbox_crtc_helper_funcs);
591
592 return vbox_crtc;
593
594clean_cursor:
595 if (cursor) {
596 drm_plane_cleanup(cursor);
597 kfree(cursor);
598 }
599clean_primary:
600 drm_plane_cleanup(primary);
601 kfree(primary);
602free_mem:
603 kfree(vbox_crtc);
604 return ERR_PTR(ret);
605}
606
607static void vbox_encoder_destroy(struct drm_encoder *encoder)
608{
609 drm_encoder_cleanup(encoder);
610 kfree(encoder);
611}
612
613static const struct drm_encoder_funcs vbox_enc_funcs = {
614 .destroy = vbox_encoder_destroy,
615};
616
617static struct drm_encoder *vbox_encoder_init(struct drm_device *dev,
618 unsigned int i)
619{
620 struct vbox_encoder *vbox_encoder;
621
622 vbox_encoder = kzalloc(sizeof(*vbox_encoder), GFP_KERNEL);
623 if (!vbox_encoder)
624 return NULL;
625
626 drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs,
627 DRM_MODE_ENCODER_DAC, NULL);
628
629 vbox_encoder->base.possible_crtcs = 1 << i;
630 return &vbox_encoder->base;
631}
632
633
634
635
636
637
638
639static void vbox_set_edid(struct drm_connector *connector, int width,
640 int height)
641{
642 enum { EDID_SIZE = 128 };
643 unsigned char edid[EDID_SIZE] = {
644 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
645 0x58, 0x58,
646 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00,
648 0x01,
649 0x00,
650 0x01, 0x03,
651 0x80,
652 0x00,
653 0x00,
654 0x78,
655 0xEE,
656
657 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
658
659 0x00, 0x00, 0x00,
660 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
661 0x01, 0x01,
662 0x01, 0x01, 0x01, 0x01,
663 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x02, 0x02,
664 0x02, 0x02,
665
666 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
667
668 0x00, 0x00, 0x00, 0xFD, 0x00,
669 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20,
670 0x20, 0x20,
671
672 0x20,
673
674 0x00, 0x00, 0x00, 0xFC, 0x00,
675 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r',
676 '\n',
677
678 0x00, 0x00, 0x00, 0x10, 0x00,
679 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
680 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
681 0x20,
682 0x00,
683 0x00
684 };
685 int clock = (width + 6) * (height + 6) * 60 / 10000;
686 unsigned int i, sum = 0;
687
688 edid[12] = width & 0xff;
689 edid[13] = width >> 8;
690 edid[14] = height & 0xff;
691 edid[15] = height >> 8;
692 edid[54] = clock & 0xff;
693 edid[55] = clock >> 8;
694 edid[56] = width & 0xff;
695 edid[58] = (width >> 4) & 0xf0;
696 edid[59] = height & 0xff;
697 edid[61] = (height >> 4) & 0xf0;
698 for (i = 0; i < EDID_SIZE - 1; ++i)
699 sum += edid[i];
700 edid[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
701 drm_connector_update_edid_property(connector, (struct edid *)edid);
702}
703
704static int vbox_get_modes(struct drm_connector *connector)
705{
706 struct vbox_connector *vbox_connector = NULL;
707 struct drm_display_mode *mode = NULL;
708 struct vbox_private *vbox = NULL;
709 unsigned int num_modes = 0;
710 int preferred_width, preferred_height;
711
712 vbox_connector = to_vbox_connector(connector);
713 vbox = to_vbox_dev(connector->dev);
714
715 hgsmi_report_flags_location(vbox->guest_pool, GUEST_HEAP_OFFSET(vbox) +
716 HOST_FLAGS_OFFSET);
717 if (vbox_connector->vbox_crtc->crtc_id == 0)
718 vbox_report_caps(vbox);
719
720 num_modes = drm_add_modes_noedid(connector, 2560, 1600);
721 preferred_width = vbox_connector->mode_hint.width ?
722 vbox_connector->mode_hint.width : 1024;
723 preferred_height = vbox_connector->mode_hint.height ?
724 vbox_connector->mode_hint.height : 768;
725 mode = drm_cvt_mode(connector->dev, preferred_width, preferred_height,
726 60, false, false, false);
727 if (mode) {
728 mode->type |= DRM_MODE_TYPE_PREFERRED;
729 drm_mode_probed_add(connector, mode);
730 ++num_modes;
731 }
732 vbox_set_edid(connector, preferred_width, preferred_height);
733
734 if (vbox_connector->vbox_crtc->x_hint != -1)
735 drm_object_property_set_value(&connector->base,
736 vbox->ddev.mode_config.suggested_x_property,
737 vbox_connector->vbox_crtc->x_hint);
738 else
739 drm_object_property_set_value(&connector->base,
740 vbox->ddev.mode_config.suggested_x_property, 0);
741
742 if (vbox_connector->vbox_crtc->y_hint != -1)
743 drm_object_property_set_value(&connector->base,
744 vbox->ddev.mode_config.suggested_y_property,
745 vbox_connector->vbox_crtc->y_hint);
746 else
747 drm_object_property_set_value(&connector->base,
748 vbox->ddev.mode_config.suggested_y_property, 0);
749
750 return num_modes;
751}
752
753static void vbox_connector_destroy(struct drm_connector *connector)
754{
755 drm_connector_unregister(connector);
756 drm_connector_cleanup(connector);
757 kfree(connector);
758}
759
760static enum drm_connector_status
761vbox_connector_detect(struct drm_connector *connector, bool force)
762{
763 struct vbox_connector *vbox_connector;
764
765 vbox_connector = to_vbox_connector(connector);
766
767 return vbox_connector->mode_hint.disconnected ?
768 connector_status_disconnected : connector_status_connected;
769}
770
771static int vbox_fill_modes(struct drm_connector *connector, u32 max_x,
772 u32 max_y)
773{
774 struct vbox_connector *vbox_connector;
775 struct drm_device *dev;
776 struct drm_display_mode *mode, *iterator;
777
778 vbox_connector = to_vbox_connector(connector);
779 dev = vbox_connector->base.dev;
780 list_for_each_entry_safe(mode, iterator, &connector->modes, head) {
781 list_del(&mode->head);
782 drm_mode_destroy(dev, mode);
783 }
784
785 return drm_helper_probe_single_connector_modes(connector, max_x, max_y);
786}
787
788static const struct drm_connector_helper_funcs vbox_connector_helper_funcs = {
789 .get_modes = vbox_get_modes,
790};
791
792static const struct drm_connector_funcs vbox_connector_funcs = {
793 .detect = vbox_connector_detect,
794 .fill_modes = vbox_fill_modes,
795 .destroy = vbox_connector_destroy,
796 .reset = drm_atomic_helper_connector_reset,
797 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
798 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
799};
800
801static int vbox_connector_init(struct drm_device *dev,
802 struct vbox_crtc *vbox_crtc,
803 struct drm_encoder *encoder)
804{
805 struct vbox_connector *vbox_connector;
806 struct drm_connector *connector;
807
808 vbox_connector = kzalloc(sizeof(*vbox_connector), GFP_KERNEL);
809 if (!vbox_connector)
810 return -ENOMEM;
811
812 connector = &vbox_connector->base;
813 vbox_connector->vbox_crtc = vbox_crtc;
814
815 drm_connector_init(dev, connector, &vbox_connector_funcs,
816 DRM_MODE_CONNECTOR_VGA);
817 drm_connector_helper_add(connector, &vbox_connector_helper_funcs);
818
819 connector->interlace_allowed = 0;
820 connector->doublescan_allowed = 0;
821
822 drm_mode_create_suggested_offset_properties(dev);
823 drm_object_attach_property(&connector->base,
824 dev->mode_config.suggested_x_property, 0);
825 drm_object_attach_property(&connector->base,
826 dev->mode_config.suggested_y_property, 0);
827
828 drm_connector_attach_encoder(connector, encoder);
829
830 return 0;
831}
832
833static const struct drm_mode_config_funcs vbox_mode_funcs = {
834 .fb_create = drm_gem_fb_create_with_dirty,
835 .mode_valid = drm_vram_helper_mode_valid,
836 .atomic_check = drm_atomic_helper_check,
837 .atomic_commit = drm_atomic_helper_commit,
838};
839
840int vbox_mode_init(struct vbox_private *vbox)
841{
842 struct drm_device *dev = &vbox->ddev;
843 struct drm_encoder *encoder;
844 struct vbox_crtc *vbox_crtc;
845 unsigned int i;
846 int ret;
847
848 drm_mode_config_init(dev);
849
850 dev->mode_config.funcs = (void *)&vbox_mode_funcs;
851 dev->mode_config.min_width = 0;
852 dev->mode_config.min_height = 0;
853 dev->mode_config.preferred_depth = 24;
854 dev->mode_config.max_width = VBE_DISPI_MAX_XRES;
855 dev->mode_config.max_height = VBE_DISPI_MAX_YRES;
856
857 for (i = 0; i < vbox->num_crtcs; ++i) {
858 vbox_crtc = vbox_crtc_init(dev, i);
859 if (IS_ERR(vbox_crtc)) {
860 ret = PTR_ERR(vbox_crtc);
861 goto err_drm_mode_cleanup;
862 }
863 encoder = vbox_encoder_init(dev, i);
864 if (!encoder) {
865 ret = -ENOMEM;
866 goto err_drm_mode_cleanup;
867 }
868 ret = vbox_connector_init(dev, vbox_crtc, encoder);
869 if (ret)
870 goto err_drm_mode_cleanup;
871 }
872
873 drm_mode_config_reset(dev);
874 return 0;
875
876err_drm_mode_cleanup:
877 drm_mode_config_cleanup(dev);
878 return ret;
879}
880
881void vbox_mode_fini(struct vbox_private *vbox)
882{
883 drm_mode_config_cleanup(&vbox->ddev);
884}
885