git: 59d36b896992 - stable/14 - LinuxKPI: update linuxkpi_video to Linux 6.6
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 11 Aug 2024 10:15:23 UTC
The branch stable/14 has been updated by wulf: URL: https://cgit.FreeBSD.org/src/commit/?id=59d36b8969925a68f805338c1fd288d1c14bf7d4 commit 59d36b8969925a68f805338c1fd288d1c14bf7d4 Author: Vladimir Kondratyev <wulf@FreeBSD.org> AuthorDate: 2024-08-07 20:38:38 +0000 Commit: Vladimir Kondratyev <wulf@FreeBSD.org> CommitDate: 2024-08-11 10:12:38 +0000 LinuxKPI: update linuxkpi_video to Linux 6.6 disable hdmi_audio_infoframe_pack_for_dp function for now as it depends on not imported yet drm sources and is not used by drm-kmod. Reviewed by: manu Sponsored by: Serenity CyberSecurity, LLC Differential Revision: https://reviews.freebsd.org/D46224 (cherry picked from commit c89d94ad5d95fd15e891b2723caae8a6104ee153) --- .../linuxkpi/common/include/linux/aperture.h | 16 ++-- sys/compat/linuxkpi/common/include/linux/hdmi.h | 9 ++- sys/compat/linuxkpi/common/include/video/cmdline.h | 44 +++++++++++ sys/compat/linuxkpi/common/src/linux_aperture.c | 86 ++++++++++++++-------- sys/compat/linuxkpi/common/src/linux_cmdline.c | 63 ++++++++++++++++ sys/compat/linuxkpi/common/src/linux_hdmi.c | 86 +++++++++++++++++----- sys/modules/linuxkpi_video/Makefile | 1 + 7 files changed, 248 insertions(+), 57 deletions(-) diff --git a/sys/compat/linuxkpi/common/include/linux/aperture.h b/sys/compat/linuxkpi/common/include/linux/aperture.h index e0387ed0225d..7eced3cc3cb1 100644 --- a/sys/compat/linuxkpi/common/include/linux/aperture.h +++ b/sys/compat/linuxkpi/common/include/linux/aperture.h @@ -16,7 +16,9 @@ int devm_aperture_acquire_for_platform_device(struct platform_device *pdev, resource_size_t size); int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, - bool primary, const char *name); + const char *name); + +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev); int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name); #else @@ -28,7 +30,12 @@ static inline int devm_aperture_acquire_for_platform_device(struct platform_devi } static inline int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, - bool primary, const char *name) + const char *name) +{ + return 0; +} + +static inline int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev) { return 0; } @@ -41,7 +48,6 @@ static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, /** * aperture_remove_all_conflicting_devices - remove all existing framebuffers - * @primary: also kick vga16fb if present; only relevant for VGA devices * @name: a descriptive name of the requesting driver * * This function removes all graphics device drivers. Use this function on systems @@ -50,9 +56,9 @@ static inline int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, * Returns: * 0 on success, or a negative errno code otherwise */ -static inline int aperture_remove_all_conflicting_devices(bool primary, const char *name) +static inline int aperture_remove_all_conflicting_devices(const char *name) { - return aperture_remove_conflicting_devices(0, (resource_size_t)-1, primary, name); + return aperture_remove_conflicting_devices(0, (resource_size_t)-1, name); } #endif diff --git a/sys/compat/linuxkpi/common/include/linux/hdmi.h b/sys/compat/linuxkpi/common/include/linux/hdmi.h index c8ec982ff498..2094dbc84e89 100644 --- a/sys/compat/linuxkpi/common/include/linux/hdmi.h +++ b/sys/compat/linuxkpi/common/include/linux/hdmi.h @@ -336,7 +336,14 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, void *buffer, size_t size); ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, void *buffer, size_t size); -int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame); +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame); + +#ifdef __linux__ +struct dp_sdp; +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version); +#endif enum hdmi_3d_structure { HDMI_3D_STRUCTURE_INVALID = -1, diff --git a/sys/compat/linuxkpi/common/include/video/cmdline.h b/sys/compat/linuxkpi/common/include/video/cmdline.h new file mode 100644 index 000000000000..eaa9a998fda2 --- /dev/null +++ b/sys/compat/linuxkpi/common/include/video/cmdline.h @@ -0,0 +1,44 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Serenity Cyber Security, LLC. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _VIDEO_CMDLINE_H_ +#define _VIDEO_CMDLINE_H_ + +#include <linux/types.h> + +#define CONFIG_VIDEO_CMDLINE + +#if defined(CONFIG_VIDEO_CMDLINE) +const char *video_get_options(const char *name); +#else +static inline const char * +video_get_options(const char *name) +{ + return (NULL); +} +#endif +#endif /* _VIDEO_CMDLINE_H_ */ diff --git a/sys/compat/linuxkpi/common/src/linux_aperture.c b/sys/compat/linuxkpi/common/src/linux_aperture.c index 15a56839fa9c..21c7041fc851 100644 --- a/sys/compat/linuxkpi/common/src/linux_aperture.c +++ b/sys/compat/linuxkpi/common/src/linux_aperture.c @@ -20,7 +20,7 @@ * driver can be active at any given time. Many systems load a generic * graphics drivers, such as EFI-GOP or VESA, early during the boot process. * During later boot stages, they replace the generic driver with a dedicated, - * hardware-specific driver. To take over the device the dedicated driver + * hardware-specific driver. To take over the device, the dedicated driver * first has to remove the generic driver. Aperture functions manage * ownership of framebuffer memory and hand-over between drivers. * @@ -43,7 +43,7 @@ * base = mem->start; * size = resource_size(mem); * - * ret = aperture_remove_conflicting_devices(base, size, false, "example"); + * ret = aperture_remove_conflicting_devices(base, size, "example"); * if (ret) * return ret; * @@ -76,7 +76,7 @@ * generic EFI or VESA drivers, have to register themselves as owners of their * framebuffer apertures. Ownership of the framebuffer memory is achieved * by calling devm_aperture_acquire_for_platform_device(). If successful, the - * driveris the owner of the framebuffer range. The function fails if the + * driver is the owner of the framebuffer range. The function fails if the * framebuffer is already owned by another driver. See below for an example. * * .. code-block:: c @@ -126,7 +126,7 @@ * et al for the registered framebuffer range, the aperture helpers call * platform_device_unregister() and the generic driver unloads itself. The * generic driver also has to provide a remove function to make this work. - * Once hot unplugged fro mhardware, it may not access the device's + * Once hot unplugged from hardware, it may not access the device's * registers, framebuffer memory, ROM, etc afterwards. */ @@ -203,7 +203,7 @@ static void aperture_detach_platform_device(struct device *dev) /* * Remove the device from the device hierarchy. This is the right thing - * to do for firmware-based DRM drivers, such as EFI, VESA or VGA. After + * to do for firmware-based fb drivers, such as EFI, VESA or VGA. After * the new driver takes over the hardware, the firmware device's state * will be lost. * @@ -274,7 +274,6 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size) * aperture_remove_conflicting_devices - remove devices in the given range * @base: the aperture's base address in physical memory * @size: aperture size in bytes - * @primary: also kick vga16fb if present; only relevant for VGA devices * @name: a descriptive name of the requesting driver * * This function removes devices that own apertures within @base and @size. @@ -283,7 +282,7 @@ static void aperture_detach_devices(resource_size_t base, resource_size_t size) * 0 on success, or a negative errno code otherwise */ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t size, - bool primary, const char *name) + const char *name) { /* * If a driver asked to unregister a platform device registered by @@ -300,18 +299,45 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si aperture_detach_devices(base, size); - /* - * If this is the primary adapter, there could be a VGA device - * that consumes the VGA framebuffer I/O range. Remove this device - * as well. - */ - if (primary) - aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE); - return 0; } EXPORT_SYMBOL(aperture_remove_conflicting_devices); +/** + * __aperture_remove_legacy_vga_devices - remove legacy VGA devices of a PCI devices + * @pdev: PCI device + * + * This function removes VGA devices provided by @pdev, such as a VGA + * framebuffer or a console. This is useful if you have a VGA-compatible + * PCI graphics device with framebuffers in non-BAR locations. Drivers + * should acquire ownership of those memory areas and afterwards call + * this helper to release remaining VGA devices. + * + * If your hardware has its framebuffers accessible via PCI BARS, use + * aperture_remove_conflicting_pci_devices() instead. The function will + * release any VGA devices automatically. + * + * WARNING: Apparently we must remove graphics drivers before calling + * this helper. Otherwise the vga fbdev driver falls over if + * we have vgacon configured. + * + * Returns: + * 0 on success, or a negative errno code otherwise + */ +int __aperture_remove_legacy_vga_devices(struct pci_dev *pdev) +{ + /* VGA framebuffer */ + aperture_detach_devices(VGA_FB_PHYS_BASE, VGA_FB_PHYS_SIZE); + + /* VGA textmode console */ +#ifdef __linux__ + return vga_remove_vgacon(pdev); +#elif defined(__FreeBSD__) + return 0; +#endif +} +EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices); + /** * aperture_remove_conflicting_pci_devices - remove existing framebuffers for PCI devices * @pdev: PCI device @@ -328,14 +354,14 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na { bool primary = false; resource_size_t base, size; - int bar, ret; + int bar, ret = 0; -#ifdef CONFIG_X86 #ifdef __linux__ - primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; -#elif defined(__FreeBSD__) - primary = NULL; -#endif + if (pdev == vga_default_device()) + primary = true; + + if (primary) + sysfb_disable(); #endif for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { @@ -344,22 +370,18 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na base = pci_resource_start(pdev, bar); size = pci_resource_len(pdev, bar); - ret = aperture_remove_conflicting_devices(base, size, primary, name); - if (ret) - return ret; + aperture_detach_devices(base, size); } /* - * WARNING: Apparently we must kick fbdev drivers before vgacon, - * otherwise the vga fbdev driver falls over. + * If this is the primary adapter, there could be a VGA device + * that consumes the VGA framebuffer I/O range. Remove this + * device as well. */ -#ifdef __linux__ - ret = vga_remove_vgacon(pdev); - if (ret) - return ret; -#endif + if (primary) + ret = __aperture_remove_legacy_vga_devices(pdev); - return 0; + return ret; } EXPORT_SYMBOL(aperture_remove_conflicting_pci_devices); diff --git a/sys/compat/linuxkpi/common/src/linux_cmdline.c b/sys/compat/linuxkpi/common/src/linux_cmdline.c new file mode 100644 index 000000000000..0cfa1d56ee6a --- /dev/null +++ b/sys/compat/linuxkpi/common/src/linux_cmdline.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> + +#include <video/cmdline.h> + +const char * +video_get_options(const char *connector_name) +{ + char tunable[64]; + const char *options; + + /* + * A user may use loader tunables to set a specific mode for the + * console. Tunables are read in the following order: + * 1. kern.vt.fb.modes.$connector_name + * 2. kern.vt.fb.default_mode + * + * Example of a mode specific to the LVDS connector: + * kern.vt.fb.modes.LVDS="1024x768" + * + * Example of a mode applied to all connectors not having a + * connector-specific mode: + * kern.vt.fb.default_mode="640x480" + */ + snprintf(tunable, sizeof(tunable), "kern.vt.fb.modes.%s", + connector_name); + if (bootverbose) { + printf("[drm] Connector %s: get mode from tunables:\n", connector_name); + printf("[drm] - %s\n", tunable); + printf("[drm] - kern.vt.fb.default_mode\n"); + } + options = kern_getenv(tunable); + if (options == NULL) + options = kern_getenv("kern.vt.fb.default_mode"); + + return (options); +} diff --git a/sys/compat/linuxkpi/common/src/linux_hdmi.c b/sys/compat/linuxkpi/common/src/linux_hdmi.c index 947be761dfa4..fc47693e913c 100644 --- a/sys/compat/linuxkpi/common/src/linux_hdmi.c +++ b/sys/compat/linuxkpi/common/src/linux_hdmi.c @@ -21,6 +21,9 @@ * DEALINGS IN THE SOFTWARE. */ +#ifdef __linux__ +#include <drm/display/drm_dp.h> +#endif #include <linux/bitops.h> #include <linux/bug.h> #include <linux/errno.h> @@ -381,12 +384,34 @@ static int hdmi_audio_infoframe_check_only(const struct hdmi_audio_infoframe *fr * * Returns 0 on success or a negative error code on failure. */ -int hdmi_audio_infoframe_check(struct hdmi_audio_infoframe *frame) +int hdmi_audio_infoframe_check(const struct hdmi_audio_infoframe *frame) { return hdmi_audio_infoframe_check_only(frame); } EXPORT_SYMBOL(hdmi_audio_infoframe_check); +static void +hdmi_audio_infoframe_pack_payload(const struct hdmi_audio_infoframe *frame, + u8 *buffer) +{ + u8 channels; + + if (frame->channels >= 2) + channels = frame->channels - 1; + else + channels = 0; + + buffer[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); + buffer[1] = ((frame->sample_frequency & 0x7) << 2) | + (frame->sample_size & 0x3); + buffer[2] = frame->coding_type_ext & 0x1f; + buffer[3] = frame->channel_allocation; + buffer[4] = (frame->level_shift_value & 0xf) << 3; + + if (frame->downmix_inhibit) + buffer[4] |= BIT(7); +} + /** * hdmi_audio_infoframe_pack_only() - write HDMI audio infoframe to binary buffer * @frame: HDMI audio infoframe @@ -404,7 +429,6 @@ EXPORT_SYMBOL(hdmi_audio_infoframe_check); ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, void *buffer, size_t size) { - unsigned char channels; u8 *ptr = buffer; size_t length; int ret; @@ -420,28 +444,13 @@ ssize_t hdmi_audio_infoframe_pack_only(const struct hdmi_audio_infoframe *frame, memset(buffer, 0, size); - if (frame->channels >= 2) - channels = frame->channels - 1; - else - channels = 0; - ptr[0] = frame->type; ptr[1] = frame->version; ptr[2] = frame->length; ptr[3] = 0; /* checksum */ - /* start infoframe payload */ - ptr += HDMI_INFOFRAME_HEADER_SIZE; - - ptr[0] = ((frame->coding_type & 0xf) << 4) | (channels & 0x7); - ptr[1] = ((frame->sample_frequency & 0x7) << 2) | - (frame->sample_size & 0x3); - ptr[2] = frame->coding_type_ext & 0x1f; - ptr[3] = frame->channel_allocation; - ptr[4] = (frame->level_shift_value & 0xf) << 3; - - if (frame->downmix_inhibit) - ptr[4] |= BIT(7); + hdmi_audio_infoframe_pack_payload(frame, + ptr + HDMI_INFOFRAME_HEADER_SIZE); hdmi_infoframe_set_checksum(buffer, length); @@ -479,6 +488,45 @@ ssize_t hdmi_audio_infoframe_pack(struct hdmi_audio_infoframe *frame, } EXPORT_SYMBOL(hdmi_audio_infoframe_pack); +#ifdef __linux__ +/** + * hdmi_audio_infoframe_pack_for_dp - Pack a HDMI Audio infoframe for DisplayPort + * + * @frame: HDMI Audio infoframe + * @sdp: Secondary data packet for DisplayPort. + * @dp_version: DisplayPort version to be encoded in the header + * + * Packs a HDMI Audio Infoframe to be sent over DisplayPort. This function + * fills the secondary data packet to be used for DisplayPort. + * + * Return: Number of total written bytes or a negative errno on failure. + */ +ssize_t +hdmi_audio_infoframe_pack_for_dp(const struct hdmi_audio_infoframe *frame, + struct dp_sdp *sdp, u8 dp_version) +{ + int ret; + + ret = hdmi_audio_infoframe_check(frame); + if (ret) + return ret; + + memset(sdp->db, 0, sizeof(sdp->db)); + + /* Secondary-data packet header */ + sdp->sdp_header.HB0 = 0; + sdp->sdp_header.HB1 = frame->type; + sdp->sdp_header.HB2 = DP_SDP_AUDIO_INFOFRAME_HB2; + sdp->sdp_header.HB3 = (dp_version & 0x3f) << 2; + + hdmi_audio_infoframe_pack_payload(frame, sdp->db); + + /* Return size = frame length + four HB for sdp_header */ + return frame->length + 4; +} +EXPORT_SYMBOL(hdmi_audio_infoframe_pack_for_dp); +#endif + /** * hdmi_vendor_infoframe_init() - initialize an HDMI vendor infoframe * @frame: HDMI vendor infoframe diff --git a/sys/modules/linuxkpi_video/Makefile b/sys/modules/linuxkpi_video/Makefile index a9562eaf4735..f2ee3438ac82 100644 --- a/sys/modules/linuxkpi_video/Makefile +++ b/sys/modules/linuxkpi_video/Makefile @@ -3,6 +3,7 @@ KMOD= linuxkpi_video SRCS= linux_hdmi.c \ linux_aperture.c \ + linux_cmdline.c \ linuxkpi_videokmod.c SRCS+= ${LINUXKPI_GENSRCS}