18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: MIT
28c2ecf20Sopenharmony_ci/* Copyright (C) 2006-2017 Oracle Corporation */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/vbox_err.h>
58c2ecf20Sopenharmony_ci#include "vbox_drv.h"
68c2ecf20Sopenharmony_ci#include "vboxvideo_guest.h"
78c2ecf20Sopenharmony_ci#include "vboxvideo_vbe.h"
88c2ecf20Sopenharmony_ci#include "hgsmi_channels.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/**
118c2ecf20Sopenharmony_ci * Set a video mode via an HGSMI request.  The views must have been
128c2ecf20Sopenharmony_ci * initialised first using @a VBoxHGSMISendViewInfo and if the mode is being
138c2ecf20Sopenharmony_ci * set on the first display then it must be set first using registers.
148c2ecf20Sopenharmony_ci * @ctx:           The context containing the heap to use.
158c2ecf20Sopenharmony_ci * @display:       The screen number.
168c2ecf20Sopenharmony_ci * @origin_x:      The horizontal displacement relative to the first scrn.
178c2ecf20Sopenharmony_ci * @origin_y:      The vertical displacement relative to the first screen.
188c2ecf20Sopenharmony_ci * @start_offset:  The offset of the visible area of the framebuffer
198c2ecf20Sopenharmony_ci *                 relative to the framebuffer start.
208c2ecf20Sopenharmony_ci * @pitch:         The offset in bytes between the starts of two adjecent
218c2ecf20Sopenharmony_ci *                 scan lines in video RAM.
228c2ecf20Sopenharmony_ci * @width:         The mode width.
238c2ecf20Sopenharmony_ci * @height:        The mode height.
248c2ecf20Sopenharmony_ci * @bpp:           The colour depth of the mode.
258c2ecf20Sopenharmony_ci * @flags:         Flags.
268c2ecf20Sopenharmony_ci */
278c2ecf20Sopenharmony_civoid hgsmi_process_display_info(struct gen_pool *ctx, u32 display,
288c2ecf20Sopenharmony_ci				s32 origin_x, s32 origin_y, u32 start_offset,
298c2ecf20Sopenharmony_ci				u32 pitch, u32 width, u32 height,
308c2ecf20Sopenharmony_ci				u16 bpp, u16 flags)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	struct vbva_infoscreen *p;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
358c2ecf20Sopenharmony_ci			       VBVA_INFO_SCREEN);
368c2ecf20Sopenharmony_ci	if (!p)
378c2ecf20Sopenharmony_ci		return;
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	p->view_index = display;
408c2ecf20Sopenharmony_ci	p->origin_x = origin_x;
418c2ecf20Sopenharmony_ci	p->origin_y = origin_y;
428c2ecf20Sopenharmony_ci	p->start_offset = start_offset;
438c2ecf20Sopenharmony_ci	p->line_size = pitch;
448c2ecf20Sopenharmony_ci	p->width = width;
458c2ecf20Sopenharmony_ci	p->height = height;
468c2ecf20Sopenharmony_ci	p->bits_per_pixel = bpp;
478c2ecf20Sopenharmony_ci	p->flags = flags;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
508c2ecf20Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/**
548c2ecf20Sopenharmony_ci * Report the rectangle relative to which absolute pointer events should be
558c2ecf20Sopenharmony_ci * expressed.  This information remains valid until the next VBVA resize event
568c2ecf20Sopenharmony_ci * for any screen, at which time it is reset to the bounding rectangle of all
578c2ecf20Sopenharmony_ci * virtual screens.
588c2ecf20Sopenharmony_ci * Return: 0 or negative errno value.
598c2ecf20Sopenharmony_ci * @ctx:       The context containing the heap to use.
608c2ecf20Sopenharmony_ci * @origin_x:  Upper left X co-ordinate relative to the first screen.
618c2ecf20Sopenharmony_ci * @origin_y:  Upper left Y co-ordinate relative to the first screen.
628c2ecf20Sopenharmony_ci * @width:     Rectangle width.
638c2ecf20Sopenharmony_ci * @height:    Rectangle height.
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_ciint hgsmi_update_input_mapping(struct gen_pool *ctx, s32 origin_x, s32 origin_y,
668c2ecf20Sopenharmony_ci			       u32 width, u32 height)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	struct vbva_report_input_mapping *p;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
718c2ecf20Sopenharmony_ci			       VBVA_REPORT_INPUT_MAPPING);
728c2ecf20Sopenharmony_ci	if (!p)
738c2ecf20Sopenharmony_ci		return -ENOMEM;
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	p->x = origin_x;
768c2ecf20Sopenharmony_ci	p->y = origin_y;
778c2ecf20Sopenharmony_ci	p->cx = width;
788c2ecf20Sopenharmony_ci	p->cy = height;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
818c2ecf20Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	return 0;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci/**
878c2ecf20Sopenharmony_ci * Get most recent video mode hints.
888c2ecf20Sopenharmony_ci * Return: 0 or negative errno value.
898c2ecf20Sopenharmony_ci * @ctx:      The context containing the heap to use.
908c2ecf20Sopenharmony_ci * @screens:  The number of screens to query hints for, starting at 0.
918c2ecf20Sopenharmony_ci * @hints:    Array of vbva_modehint structures for receiving the hints.
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ciint hgsmi_get_mode_hints(struct gen_pool *ctx, unsigned int screens,
948c2ecf20Sopenharmony_ci			 struct vbva_modehint *hints)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	struct vbva_query_mode_hints *p;
978c2ecf20Sopenharmony_ci	size_t size;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	if (WARN_ON(!hints))
1008c2ecf20Sopenharmony_ci		return -EINVAL;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	size = screens * sizeof(struct vbva_modehint);
1038c2ecf20Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + size, HGSMI_CH_VBVA,
1048c2ecf20Sopenharmony_ci			       VBVA_QUERY_MODE_HINTS);
1058c2ecf20Sopenharmony_ci	if (!p)
1068c2ecf20Sopenharmony_ci		return -ENOMEM;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	p->hints_queried_count = screens;
1098c2ecf20Sopenharmony_ci	p->hint_structure_guest_size = sizeof(struct vbva_modehint);
1108c2ecf20Sopenharmony_ci	p->rc = VERR_NOT_SUPPORTED;
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	if (p->rc < 0) {
1158c2ecf20Sopenharmony_ci		hgsmi_buffer_free(ctx, p);
1168c2ecf20Sopenharmony_ci		return -EIO;
1178c2ecf20Sopenharmony_ci	}
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	memcpy(hints, ((u8 *)p) + sizeof(struct vbva_query_mode_hints), size);
1208c2ecf20Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci	return 0;
1238c2ecf20Sopenharmony_ci}
124