xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/vboxvideo/modesetting.c (revision 41ec02673d281bbb3d38e6c78504ce6e30c228c1)
1 /*	$NetBSD: modesetting.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $	*/
2 
3 // SPDX-License-Identifier: MIT
4 /* Copyright (C) 2006-2017 Oracle Corporation */
5 
6 #include <sys/cdefs.h>
7 __KERNEL_RCSID(0, "$NetBSD: modesetting.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $");
8 
9 #include <linux/vbox_err.h>
10 #include "vbox_drv.h"
11 #include "vboxvideo_guest.h"
12 #include "vboxvideo_vbe.h"
13 #include "hgsmi_channels.h"
14 
15 /**
16  * Set a video mode via an HGSMI request.  The views must have been
17  * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
18  * set on the first display then it must be set first using registers.
19  * @ctx:           The context containing the heap to use.
20  * @display:       The screen number.
21  * @origin_x:      The horizontal displacement relative to the first scrn.
22  * @origin_y:      The vertical displacement relative to the first screen.
23  * @start_offset:  The offset of the visible area of the framebuffer
24  *                 relative to the framebuffer start.
25  * @pitch:         The offset in bytes between the starts of two adjecent
26  *                 scan lines in video RAM.
27  * @width:         The mode width.
28  * @height:        The mode height.
29  * @bpp:           The colour depth of the mode.
30  * @flags:         Flags.
31  */
hgsmi_process_display_info(struct gen_pool * ctx,u32 display,s32 origin_x,s32 origin_y,u32 start_offset,u32 pitch,u32 width,u32 height,u16 bpp,u16 flags)32 void hgsmi_process_display_info(struct gen_pool *ctx, u32 display,
33 				s32 origin_x, s32 origin_y, u32 start_offset,
34 				u32 pitch, u32 width, u32 height,
35 				u16 bpp, u16 flags)
36 {
37 	struct vbva_infoscreen *p;
38 
39 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
40 			       VBVA_INFO_SCREEN);
41 	if (!p)
42 		return;
43 
44 	p->view_index = display;
45 	p->origin_x = origin_x;
46 	p->origin_y = origin_y;
47 	p->start_offset = start_offset;
48 	p->line_size = pitch;
49 	p->width = width;
50 	p->height = height;
51 	p->bits_per_pixel = bpp;
52 	p->flags = flags;
53 
54 	hgsmi_buffer_submit(ctx, p);
55 	hgsmi_buffer_free(ctx, p);
56 }
57 
58 /**
59  * Report the rectangle relative to which absolute pointer events should be
60  * expressed.  This information remains valid until the next VBVA resize event
61  * for any screen, at which time it is reset to the bounding rectangle of all
62  * virtual screens.
63  * Return: 0 or negative errno value.
64  * @ctx:       The context containing the heap to use.
65  * @origin_x:  Upper left X co-ordinate relative to the first screen.
66  * @origin_y:  Upper left Y co-ordinate relative to the first screen.
67  * @width:     Rectangle width.
68  * @height:    Rectangle height.
69  */
hgsmi_update_input_mapping(struct gen_pool * ctx,s32 origin_x,s32 origin_y,u32 width,u32 height)70 int hgsmi_update_input_mapping(struct gen_pool *ctx, s32 origin_x, s32 origin_y,
71 			       u32 width, u32 height)
72 {
73 	struct vbva_report_input_mapping *p;
74 
75 	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
76 			       VBVA_REPORT_INPUT_MAPPING);
77 	if (!p)
78 		return -ENOMEM;
79 
80 	p->x = origin_x;
81 	p->y = origin_y;
82 	p->cx = width;
83 	p->cy = height;
84 
85 	hgsmi_buffer_submit(ctx, p);
86 	hgsmi_buffer_free(ctx, p);
87 
88 	return 0;
89 }
90 
91 /**
92  * Get most recent video mode hints.
93  * Return: 0 or negative errno value.
94  * @ctx:      The context containing the heap to use.
95  * @screens:  The number of screens to query hints for, starting at 0.
96  * @hints:    Array of vbva_modehint structures for receiving the hints.
97  */
hgsmi_get_mode_hints(struct gen_pool * ctx,unsigned int screens,struct vbva_modehint * hints)98 int hgsmi_get_mode_hints(struct gen_pool *ctx, unsigned int screens,
99 			 struct vbva_modehint *hints)
100 {
101 	struct vbva_query_mode_hints *p;
102 	size_t size;
103 
104 	if (WARN_ON(!hints))
105 		return -EINVAL;
106 
107 	size = screens * sizeof(struct vbva_modehint);
108 	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + size, HGSMI_CH_VBVA,
109 			       VBVA_QUERY_MODE_HINTS);
110 	if (!p)
111 		return -ENOMEM;
112 
113 	p->hints_queried_count = screens;
114 	p->hint_structure_guest_size = sizeof(struct vbva_modehint);
115 	p->rc = VERR_NOT_SUPPORTED;
116 
117 	hgsmi_buffer_submit(ctx, p);
118 
119 	if (p->rc < 0) {
120 		hgsmi_buffer_free(ctx, p);
121 		return -EIO;
122 	}
123 
124 	memcpy(hints, ((u8 *)p) + sizeof(struct vbva_query_mode_hints), size);
125 	hgsmi_buffer_free(ctx, p);
126 
127 	return 0;
128 }
129