162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT
262306a36Sopenharmony_ci/* Copyright (C) 2006-2017 Oracle Corporation */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/vbox_err.h>
562306a36Sopenharmony_ci#include "vbox_drv.h"
662306a36Sopenharmony_ci#include "vboxvideo_guest.h"
762306a36Sopenharmony_ci#include "vboxvideo_vbe.h"
862306a36Sopenharmony_ci#include "hgsmi_channels.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/**
1162306a36Sopenharmony_ci * hgsmi_process_display_info - Set a video mode via an HGSMI request.
1262306a36Sopenharmony_ci *                              The views must have been initialised first
1362306a36Sopenharmony_ci *                              using @a VBoxHGSMISendViewInfo and if the mode
1462306a36Sopenharmony_ci *                              is being set on the first display then it must
1562306a36Sopenharmony_ci *                              be set first using registers.
1662306a36Sopenharmony_ci * @ctx:           The context containing the heap to use.
1762306a36Sopenharmony_ci * @display:       The screen number.
1862306a36Sopenharmony_ci * @origin_x:      The horizontal displacement relative to the first scrn.
1962306a36Sopenharmony_ci * @origin_y:      The vertical displacement relative to the first screen.
2062306a36Sopenharmony_ci * @start_offset:  The offset of the visible area of the framebuffer
2162306a36Sopenharmony_ci *                 relative to the framebuffer start.
2262306a36Sopenharmony_ci * @pitch:         The offset in bytes between the starts of two adjecent
2362306a36Sopenharmony_ci *                 scan lines in video RAM.
2462306a36Sopenharmony_ci * @width:         The mode width.
2562306a36Sopenharmony_ci * @height:        The mode height.
2662306a36Sopenharmony_ci * @bpp:           The colour depth of the mode.
2762306a36Sopenharmony_ci * @flags:         Flags.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_civoid hgsmi_process_display_info(struct gen_pool *ctx, u32 display,
3062306a36Sopenharmony_ci				s32 origin_x, s32 origin_y, u32 start_offset,
3162306a36Sopenharmony_ci				u32 pitch, u32 width, u32 height,
3262306a36Sopenharmony_ci				u16 bpp, u16 flags)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct vbva_infoscreen *p;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
3762306a36Sopenharmony_ci			       VBVA_INFO_SCREEN);
3862306a36Sopenharmony_ci	if (!p)
3962306a36Sopenharmony_ci		return;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	p->view_index = display;
4262306a36Sopenharmony_ci	p->origin_x = origin_x;
4362306a36Sopenharmony_ci	p->origin_y = origin_y;
4462306a36Sopenharmony_ci	p->start_offset = start_offset;
4562306a36Sopenharmony_ci	p->line_size = pitch;
4662306a36Sopenharmony_ci	p->width = width;
4762306a36Sopenharmony_ci	p->height = height;
4862306a36Sopenharmony_ci	p->bits_per_pixel = bpp;
4962306a36Sopenharmony_ci	p->flags = flags;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
5262306a36Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci/**
5662306a36Sopenharmony_ci * hgsmi_update_input_mapping - Report the rectangle relative to which absolute
5762306a36Sopenharmony_ci *                              pointer events should be expressed.  This
5862306a36Sopenharmony_ci *                              information remains valid until the next VBVA
5962306a36Sopenharmony_ci *                              resize event for any screen, at which time it is
6062306a36Sopenharmony_ci *                              reset to the bounding rectangle of all virtual
6162306a36Sopenharmony_ci *                              screens.
6262306a36Sopenharmony_ci * Return: 0 or negative errno value.
6362306a36Sopenharmony_ci * @ctx:       The context containing the heap to use.
6462306a36Sopenharmony_ci * @origin_x:  Upper left X co-ordinate relative to the first screen.
6562306a36Sopenharmony_ci * @origin_y:  Upper left Y co-ordinate relative to the first screen.
6662306a36Sopenharmony_ci * @width:     Rectangle width.
6762306a36Sopenharmony_ci * @height:    Rectangle height.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_ciint hgsmi_update_input_mapping(struct gen_pool *ctx, s32 origin_x, s32 origin_y,
7062306a36Sopenharmony_ci			       u32 width, u32 height)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	struct vbva_report_input_mapping *p;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p), HGSMI_CH_VBVA,
7562306a36Sopenharmony_ci			       VBVA_REPORT_INPUT_MAPPING);
7662306a36Sopenharmony_ci	if (!p)
7762306a36Sopenharmony_ci		return -ENOMEM;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	p->x = origin_x;
8062306a36Sopenharmony_ci	p->y = origin_y;
8162306a36Sopenharmony_ci	p->cx = width;
8262306a36Sopenharmony_ci	p->cy = height;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
8562306a36Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return 0;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci/**
9162306a36Sopenharmony_ci * hgsmi_get_mode_hints - Get most recent video mode hints.
9262306a36Sopenharmony_ci * Return: 0 or negative errno value.
9362306a36Sopenharmony_ci * @ctx:      The context containing the heap to use.
9462306a36Sopenharmony_ci * @screens:  The number of screens to query hints for, starting at 0.
9562306a36Sopenharmony_ci * @hints:    Array of vbva_modehint structures for receiving the hints.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_ciint hgsmi_get_mode_hints(struct gen_pool *ctx, unsigned int screens,
9862306a36Sopenharmony_ci			 struct vbva_modehint *hints)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	struct vbva_query_mode_hints *p;
10162306a36Sopenharmony_ci	size_t size;
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (WARN_ON(!hints))
10462306a36Sopenharmony_ci		return -EINVAL;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	size = screens * sizeof(struct vbva_modehint);
10762306a36Sopenharmony_ci	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + size, HGSMI_CH_VBVA,
10862306a36Sopenharmony_ci			       VBVA_QUERY_MODE_HINTS);
10962306a36Sopenharmony_ci	if (!p)
11062306a36Sopenharmony_ci		return -ENOMEM;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	p->hints_queried_count = screens;
11362306a36Sopenharmony_ci	p->hint_structure_guest_size = sizeof(struct vbva_modehint);
11462306a36Sopenharmony_ci	p->rc = VERR_NOT_SUPPORTED;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	hgsmi_buffer_submit(ctx, p);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (p->rc < 0) {
11962306a36Sopenharmony_ci		hgsmi_buffer_free(ctx, p);
12062306a36Sopenharmony_ci		return -EIO;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	memcpy(hints, ((u8 *)p) + sizeof(struct vbva_query_mode_hints), size);
12462306a36Sopenharmony_ci	hgsmi_buffer_free(ctx, p);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	return 0;
12762306a36Sopenharmony_ci}
128