// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012, Microsoft Corporation.
*
* Author:
* Haiyang Zhang <haiyangz@microsoft.com>
*/
/*
* Hyper-V Synthetic Video Frame Buffer Driver
*
* This is the driver for the Hyper-V Synthetic Video, which supports
* screen resolution up to Full HD 1920x1080 with 32 bit color on Windows
* Server 2012, and 1600x1200 with 16 bit color on Windows Server 2008 R2
* or earlier.
*
* It also solves the double mouse cursor issue of the emulated video mode.
*
* The default screen resolution is 1152x864, which may be changed by a
* kernel parameter:
* video=hyperv_fb:<width>x<height>
* For example: video=hyperv_fb:1280x1024
*
* Portrait orientation is also supported:
* For example: video=hyperv_fb:864x1152
*
* When a Windows 10 RS5+ host is used, the virtual machine screen
* resolution is obtained from the host. The "video=hyperv_fb" option is
* not needed, but still can be used to overwrite what the host specifies.
* The VM resolution on the host could be set by executing the powershell
* "set-vmvideo" command. For example
* set-vmvideo -vmname name -horizontalresolution:1920 \
* -verticalresolution:1200 -resolutiontype single
*
* Gen 1 VMs also support direct using VM's physical memory for framebuffer.
* It could improve the efficiency and performance for framebuffer and VM.
* This requires to allocate contiguous physical memory from Linux kernel's
* CMA memory allocator. To enable this, supply a kernel parameter to give
* enough memory space to CMA allocator for framebuffer. For example:
* cma=130m
* This gives 130MB memory to CMA allocator that can be allocated to
* framebuffer. For reference, 8K resolution (7680x4320) takes about
* 127MB memory.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/efi.h>
#include <linux/console.h>
#include <linux/hyperv.h>
/* Hyper-V Synthetic Video Protocol definitions and structures */
#define MAX_VMBUS_PKT_SIZE 0x4000
#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5)
#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff)
#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16)
#define SYNTHVID_DEPTH_WIN7 16
#define SYNTHVID_DEPTH_WIN8 32
#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
#define SYNTHVID_WIDTH_MAX_WIN7 1600
#define SYNTHVID_HEIGHT_MAX_WIN7 1200
#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
#define PCI_VENDOR_ID_MICROSOFT 0x1414
#define PCI_DEVICE_ID_HYPERV_VIDEO 0x5353
enum pipe_msg_type {
PIPE_MSG_INVALID,
PIPE_MSG_DATA,
PIPE_MSG_MAX
};
struct pipe_msg_hdr {
u32 type;
u32 size; /* size of message after this field */
} __packed;
enum synthvid_msg_type {
SYNTHVID_ERROR = 0,
SYNTHVID_VERSION_REQUEST = 1,
SYNTHVID_VERSION_RESPONSE = 2,
SYNTHVID_VRAM_LOCATION = 3,
SYNTHVID_VRAM_LOCATION_ACK = 4,
SYNTHVID_SITUATION_UPDATE<