Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 0/5] Add support for getting EDID over ACPI to DRM
This series adds the ability to fetch the EDID through ACPI for laptop panels. Drivers need to opt into the behavior. In this series it's enabled by default for all eDP or LVDS panels with AMDGPU and certain panels for Nouveau. Mario Limonciello (5): drm: Stop using `select ACPI_VIDEO` in all drivers drm: Stop using `select BACKLIGHT_CLASS_DEVICE` drm: Add support to get EDID from ACPI drm/amd: Fetch the EDID from _DDC if available for eDP drm/nouveau: Use drm_edid_read_acpi() helper drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/amd/amdgpu/Kconfig | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + .../gpu/drm/amd/amdgpu/amdgpu_connectors.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 + drivers/gpu/drm/bridge/Kconfig | 2 +- drivers/gpu/drm/drm_edid.c | 109 ++++++++++++++++-- drivers/gpu/drm/fsl-dcu/Kconfig | 2 +- drivers/gpu/drm/gma500/Kconfig | 7 +- drivers/gpu/drm/gud/Kconfig | 2 +- drivers/gpu/drm/i915/Kconfig | 9 +- drivers/gpu/drm/nouveau/Kconfig | 9 +- drivers/gpu/drm/nouveau/nouveau_acpi.c | 27 ----- drivers/gpu/drm/nouveau/nouveau_acpi.h | 2 - drivers/gpu/drm/nouveau/nouveau_connector.c | 35 +++--- drivers/gpu/drm/radeon/Kconfig | 9 +- drivers/gpu/drm/renesas/shmobile/Kconfig | 2 +- drivers/gpu/drm/solomon/Kconfig | 2 +- drivers/gpu/drm/tilcdc/Kconfig | 2 +- drivers/gpu/drm/tiny/Kconfig | 14 +-- drivers/gpu/drm/xe/Kconfig | 8 +- drivers/platform/loongarch/Kconfig | 2 +- drivers/platform/x86/Kconfig | 4 +- drivers/staging/olpc_dcon/Kconfig | 2 +- drivers/usb/misc/Kconfig | 2 +- drivers/video/fbdev/core/Kconfig | 2 +- include/drm/drm_connector.h | 6 + include/drm/drm_edid.h | 1 + 30 files changed, 165 insertions(+), 123 deletions(-) -- 2.34.1
Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 1/5] drm: Stop using `select ACPI_VIDEO` in all drivers
Many DRM drivers (ab)use `select ACPI_VIDEO` and to avoid problems will then select all the dependencies for ACPI_VIDEO. This creates a soft dependency, but makes it very hard to use ACPI_VIDEO in DRM core. Switch everything else over to use `depends on ACPI_VIDEO` instead. Signed-off-by: Mario Limonciello <mario.limonciello at amd.com> --- drivers/gpu/drm/amd/amdgpu/Kconfig | 9 +-------- drivers/gpu/drm/gma500/Kconfig | 7 +------ drivers/gpu/drm/i915/Kconfig | 9 +-------- drivers/gpu/drm/nouveau/Kconfig | 9 +-------- drivers/gpu/drm/radeon/Kconfig | 9 +-------- drivers/gpu/drm/xe/Kconfig | 8 +------- drivers/platform/loongarch/Kconfig | 2 +- drivers/staging/olpc_dcon/Kconfig | 2 +- drivers/video/fbdev/core/Kconfig | 2 +- 9 files changed, 9 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 22d88f8ef527..49c3b6eeef76 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig @@ -4,6 +4,7 @@ config DRM_AMDGPU tristate "AMD GPU" depends on DRM && PCI && MMU depends on !UML + depends on ACPI_VIDEO || !ACPI select FW_LOADER select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HDMI_HELPER @@ -17,18 +18,10 @@ config DRM_AMDGPU select HWMON select I2C select I2C_ALGOBIT - select BACKLIGHT_CLASS_DEVICE select INTERVAL_TREE select DRM_BUDDY select DRM_SUBALLOC_HELPER select DRM_EXEC - # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work - # ACPI_VIDEO's dependencies must also be selected. - select INPUT if ACPI - select ACPI_VIDEO if ACPI - # On x86 ACPI_VIDEO also needs ACPI_WMI - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 help Choose this option if you have a recent AMD Radeon graphics card. diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig index efb4a2dd2f80..a974cdde4b9c 100644 --- a/drivers/gpu/drm/gma500/Kconfig +++ b/drivers/gpu/drm/gma500/Kconfig @@ -2,16 +2,11 @@ config DRM_GMA500 tristate "Intel GMA500/600/3600/3650 KMS Framebuffer" depends on DRM && PCI && X86 && MMU + depends on ACPI_VIDEO || !ACPI select DRM_KMS_HELPER select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION select I2C select I2C_ALGOBIT - # GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915 - select ACPI_VIDEO if ACPI - select BACKLIGHT_CLASS_DEVICE if ACPI - select INPUT if ACPI - select X86_PLATFORM_DEVICES if ACPI - select ACPI_WMI if ACPI help Say yes for an experimental 2D KMS framebuffer driver for the Intel GMA500 (Poulsbo), Intel GMA600 (Moorestown/Oak Trail) and diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index b5d6e3352071..e99405c18c22 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -4,6 +4,7 @@ config DRM_I915 depends on DRM depends on X86 && PCI depends on !PREEMPT_RT + depends on ACPI_VIDEO || !ACPI select INTEL_GTT if X86 select INTERVAL_TREE # we need shmfs for the swappable backing store, and in particular @@ -22,14 +23,6 @@ config DRM_I915 select I2C select I2C_ALGOBIT select IRQ_WORK - # i915 depends on ACPI_VIDEO when ACPI is enabled - # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select BACKLIGHT_CLASS_DEVICE if ACPI - select INPUT if ACPI - select X86_PLATFORM_DEVICES if ACPI - select ACPI_WMI if ACPI - select ACPI_VIDEO if ACPI - select ACPI_BUTTON if ACPI select SYNC_FILE select IOSF_MBI if X86 select CRC32 diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 1e6aaf95ff7c..a3768484cbf5 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -2,6 +2,7 @@ config DRM_NOUVEAU tristate "Nouveau (NVIDIA) cards" depends on DRM && PCI && MMU + depends on ACPI_VIDEO || !ACPI select IOMMU_API select FW_LOADER select DRM_DISPLAY_DP_HELPER @@ -15,16 +16,8 @@ config DRM_NOUVEAU select DRM_SCHED select I2C select I2C_ALGOBIT - select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 - select MXM_WMI if ACPI && X86 select POWER_SUPPLY - # Similar to i915, we need to select ACPI_VIDEO and it's dependencies - select BACKLIGHT_CLASS_DEVICE if ACPI && X86 - select INPUT if ACPI && X86 select THERMAL if ACPI && X86 - select ACPI_VIDEO if ACPI && X86 select SND_HDA_COMPONENT if SND_HDA_CORE help Choose this option for open-source NVIDIA support. diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index f98356be0af2..05d134bb1cb2 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig @@ -4,6 +4,7 @@ config DRM_RADEON tristate "ATI Radeon" depends on DRM && PCI && MMU depends on AGP || !AGP + depends on ACPI_VIDEO || !ACPI select FW_LOADER select DRM_DISPLAY_DP_HELPER select DRM_DISPLAY_HELPER @@ -15,17 +16,9 @@ config DRM_RADEON select SND_HDA_COMPONENT if SND_HDA_CORE select POWER_SUPPLY select HWMON - select BACKLIGHT_CLASS_DEVICE select INTERVAL_TREE select I2C select I2C_ALGOBIT - # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work - # ACPI_VIDEO's dependencies must also be selected. - select INPUT if ACPI - select ACPI_VIDEO if ACPI - # On x86 ACPI_VIDEO also needs ACPI_WMI - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 help Choose this option if you have an ATI Radeon graphics card. There are both PCI and AGP versions. You don't need to choose this to diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index e36ae1f0d885..8a20f5a4d516 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -2,6 +2,7 @@ config DRM_XE tristate "Intel Xe Graphics" depends on DRM && PCI && MMU && (m || (y && KUNIT=y)) && 64BIT + depends on ACPI_VIDEO || !ACPI select INTERVAL_TREE # we need shmfs for the swappable backing store, and in particular # the shmem_readpage() which depends upon tmpfs @@ -19,13 +20,6 @@ config DRM_XE select DRM_MIPI_DSI select RELAY select IRQ_WORK - # xe depends on ACPI_VIDEO when ACPI is enabled - # but for select to work, need to select ACPI_VIDEO's dependencies, ick - select BACKLIGHT_CLASS_DEVICE if ACPI - select INPUT if ACPI - select ACPI_VIDEO if X86 && ACPI - select ACPI_BUTTON if ACPI - select ACPI_WMI if X86 && ACPI select SYNC_FILE select IOSF_MBI select CRC32 diff --git a/drivers/platform/loongarch/Kconfig b/drivers/platform/loongarch/Kconfig index 5633e4d73991..2c55bc98c727 100644 --- a/drivers/platform/loongarch/Kconfig +++ b/drivers/platform/loongarch/Kconfig @@ -22,7 +22,7 @@ config LOONGSON_LAPTOP depends on BACKLIGHT_CLASS_DEVICE depends on INPUT depends on MACH_LOONGSON64 - select ACPI_VIDEO + depends on ACPI_VIDEO select INPUT_SPARSEKMAP default y help diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig index d0ba34cc32f7..e1fe1f2b767a 100644 --- a/drivers/staging/olpc_dcon/Kconfig +++ b/drivers/staging/olpc_dcon/Kconfig @@ -4,7 +4,7 @@ config FB_OLPC_DCON depends on OLPC && FB && BROKEN depends on I2C depends on GPIO_CS5535 && ACPI - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE help In order to support very low power operation, the XO laptop uses a secondary Display CONtroller, or DCON. This secondary controller diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig index db09fe87fcd4..d5c9249cdb5d 100644 --- a/drivers/video/fbdev/core/Kconfig +++ b/drivers/video/fbdev/core/Kconfig @@ -179,7 +179,7 @@ config FB_SYSMEM_HELPERS_DEFERRED config FB_BACKLIGHT tristate depends on FB - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" -- 2.34.1
Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 2/5] drm: Stop using `select BACKLIGHT_CLASS_DEVICE`
Many drivers ab(use) `select BACKLIGHT_CLASS_DEVICE` to avoid dependency problems. This however makes it impossible for DRM core to be able to add a dependency on ACPI_VIDEO. Switch users of `select BACKLIGHT_CLASS_DEVICE` to `depends on BACKLIGHT_CLASS_DEVICE`. Signed-off-by: Mario Limonciello <mario.limonciello at amd.com> --- drivers/gpu/drm/bridge/Kconfig | 2 +- drivers/gpu/drm/fsl-dcu/Kconfig | 2 +- drivers/gpu/drm/gud/Kconfig | 2 +- drivers/gpu/drm/renesas/shmobile/Kconfig | 2 +- drivers/gpu/drm/solomon/Kconfig | 2 +- drivers/gpu/drm/tilcdc/Kconfig | 2 +- drivers/gpu/drm/tiny/Kconfig | 14 +++++++------- drivers/platform/x86/Kconfig | 4 ++-- drivers/usb/misc/Kconfig | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index efd996f6c138..c4e0d506a389 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -218,9 +218,9 @@ config DRM_NXP_PTN3460 config DRM_PARADE_PS8622 tristate "Parade eDP/LVDS bridge" depends on OF + depends on BACKLIGHT_CLASS_DEVICE select DRM_PANEL select DRM_KMS_HELPER - select BACKLIGHT_CLASS_DEVICE help Parade eDP-LVDS bridge chip driver. diff --git a/drivers/gpu/drm/fsl-dcu/Kconfig b/drivers/gpu/drm/fsl-dcu/Kconfig index 5ca71ef87325..93202786bec5 100644 --- a/drivers/gpu/drm/fsl-dcu/Kconfig +++ b/drivers/gpu/drm/fsl-dcu/Kconfig @@ -2,7 +2,7 @@ config DRM_FSL_DCU tristate "DRM Support for Freescale DCU" depends on DRM && OF && ARM && COMMON_CLK - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/gud/Kconfig b/drivers/gpu/drm/gud/Kconfig index 9c1e61f9eec3..44553514ad64 100644 --- a/drivers/gpu/drm/gud/Kconfig +++ b/drivers/gpu/drm/gud/Kconfig @@ -3,10 +3,10 @@ config DRM_GUD tristate "GUD USB Display" depends on DRM && USB && MMU + depends on BACKLIGHT_CLASS_DEVICE select LZ4_COMPRESS select DRM_KMS_HELPER select DRM_GEM_SHMEM_HELPER - select BACKLIGHT_CLASS_DEVICE help This is a DRM display driver for GUD USB Displays or display adapters. diff --git a/drivers/gpu/drm/renesas/shmobile/Kconfig b/drivers/gpu/drm/renesas/shmobile/Kconfig index 027220b8fe1c..6b36dee443eb 100644 --- a/drivers/gpu/drm/renesas/shmobile/Kconfig +++ b/drivers/gpu/drm/renesas/shmobile/Kconfig @@ -3,7 +3,7 @@ config DRM_SHMOBILE tristate "DRM Support for SH Mobile" depends on DRM && PM depends on ARCH_RENESAS || ARCH_SHMOBILE || COMPILE_TEST - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select VIDEOMODE_HELPERS diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig index c3ee956c2bb9..2b36ac8e0913 100644 --- a/drivers/gpu/drm/solomon/Kconfig +++ b/drivers/gpu/drm/solomon/Kconfig @@ -1,7 +1,7 @@ config DRM_SSD130X tristate "DRM support for Solomon SSD13xx OLED displays" depends on DRM && MMU - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER help diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index d3bd2d7a181e..640adf075bba 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -2,12 +2,12 @@ config DRM_TILCDC tristate "DRM Support for TI LCDC Display Controller" depends on DRM && OF && ARM + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_BRIDGE select DRM_PANEL_BRIDGE select VIDEOMODE_HELPERS - select BACKLIGHT_CLASS_DEVICE help Choose this option if you have an TI SoC with LCDC display controller, for example AM33xx in beagle-bone, DA8xx, or diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index f6889f649bc1..d5160a6b5d72 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -67,10 +67,10 @@ config DRM_OFDRM config DRM_PANEL_MIPI_DBI tristate "DRM support for MIPI DBI compatible panels" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE select VIDEOMODE_HELPERS help Say Y here if you want to enable support for MIPI DBI compatible @@ -99,10 +99,10 @@ config DRM_SIMPLEDRM config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE help DRM driver for the following HX8357D panels: * YX350HV15-T 3.5" 340x350 TFT (Adafruit 3.5") @@ -112,7 +112,7 @@ config TINYDRM_HX8357D config TINYDRM_ILI9163 tristate "DRM support for ILI9163 display panels" depends on DRM && SPI - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE select DRM_GEM_DMA_HELPER select DRM_KMS_HELPER select DRM_MIPI_DBI @@ -137,10 +137,10 @@ config TINYDRM_ILI9225 config TINYDRM_ILI9341 tristate "DRM support for ILI9341 display panels" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE help DRM driver for the following Ilitek ILI9341 panels: * YX240QV29-T 2.4" 240x320 TFT (Adafruit 2.4") @@ -150,10 +150,10 @@ config TINYDRM_ILI9341 config TINYDRM_ILI9486 tristate "DRM support for ILI9486 display panels" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE help DRM driver for the following Ilitek ILI9486 panels: * PISCREEN 3.5" 320x480 TFT (Ozzmaker 3.5") @@ -164,10 +164,10 @@ config TINYDRM_ILI9486 config TINYDRM_MI0283QT tristate "DRM support for MI0283QT" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE help DRM driver for the Multi-Inno MI0283QT display panel If M is selected the module will be called mi0283qt. @@ -201,10 +201,10 @@ config TINYDRM_ST7586 config TINYDRM_ST7735R tristate "DRM support for Sitronix ST7715R/ST7735R display panels" depends on DRM && SPI + depends on BACKLIGHT_CLASS_DEVICE select DRM_KMS_HELPER select DRM_GEM_DMA_HELPER select DRM_MIPI_DBI - select BACKLIGHT_CLASS_DEVICE help DRM driver for Sitronix ST7715R/ST7735R with one of the following LCDs: diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index bdd302274b9a..509bcf6ac88b 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -753,7 +753,7 @@ config SAMSUNG_LAPTOP config SAMSUNG_Q10 tristate "Samsung Q10 Extras" depends on ACPI - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE help This driver provides support for backlight control on Samsung Q10 and related laptops, including Dell Latitude X200. @@ -852,7 +852,7 @@ config ACPI_CMPC tristate "CMPC Laptop Extras" depends on ACPI && INPUT depends on RFKILL || RFKILL=n - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE help Support for Intel Classmate PC ACPI devices, including some keys as input device, backlight device, tablet and accelerometer diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index c510af7baa0d..2251ddabbfb8 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -139,7 +139,7 @@ config USB_IDMOUSE config USB_APPLEDISPLAY tristate "Apple Cinema Display support" - select BACKLIGHT_CLASS_DEVICE + depends on BACKLIGHT_CLASS_DEVICE help Say Y here if you want to control the backlight of Apple Cinema Displays over USB. This driver provides a sysfs interface. -- 2.34.1
Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 3/5] drm: Add support to get EDID from ACPI
Some manufacturers have intentionally put an EDID that differs from the EDID on the internal panel on laptops. Drivers that prefer to fetch this EDID can set a bit on the drm_connector to indicate that the DRM EDID helpers should try to fetch it and it is preferred if it's present. Signed-off-by: Mario Limonciello <mario.limonciello at amd.com> --- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/drm_edid.c | 109 +++++++++++++++++++++++++++++++++--- include/drm/drm_connector.h | 6 ++ include/drm/drm_edid.h | 1 + 4 files changed, 109 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 872edb47bb53..3db89e6af01d 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -8,6 +8,7 @@ menuconfig DRM tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA + depends on (ACPI_VIDEO || ACPI_VIDEO=n) select DRM_PANEL_ORIENTATION_QUIRKS select DRM_KMS_HELPER if DRM_FBDEV_EMULATION select FB_CORE if DRM_FBDEV_EMULATION diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 923c4423151c..cdc30c6d05d5 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -28,6 +28,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <acpi/video.h> #include <linux/bitfield.h> #include <linux/cec.h> #include <linux/hdmi.h> @@ -2188,6 +2189,58 @@ drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len) return ret == xfers ? 0 : -1; } +/** + * drm_do_probe_acpi_edid() - get EDID information via ACPI _DDC + * @data: struct drm_connector + * @buf: EDID data buffer to be filled + * @block: 128 byte EDID block to start fetching from + * @len: EDID data buffer length to fetch + * + * Try to fetch EDID information by calling acpi_video_get_edid() function. + * + * Return: 0 on success or error code on failure. + */ +static int +drm_do_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len) +{ + struct drm_connector *connector = data; + struct drm_device *ddev = connector->dev; + struct acpi_device *acpidev = ACPI_COMPANION(ddev->dev); + unsigned char start = block * EDID_LENGTH; + void *edid; + int r; + + if (!acpidev) + return -ENODEV; + + switch (connector->connector_type) { + case DRM_MODE_CONNECTOR_LVDS: + case DRM_MODE_CONNECTOR_eDP: + break; + default: + return -EINVAL; + } + + /* fetch the entire edid from BIOS */ + r = acpi_video_get_edid(acpidev, ACPI_VIDEO_DISPLAY_LCD, -1, &edid); + if (r < 0) { + DRM_DEBUG_KMS("Failed to get EDID from ACPI: %d\n", r); + return r; + } + if (len > r || start > r || start + len > r) { + r = -EINVAL; + goto cleanup; + } + + memcpy(buf, edid + start, len); + r = 0; + +cleanup: + kfree(edid); + + return r; +} + static void connector_bad_edid(struct drm_connector *connector, const struct edid *edid, int num_blocks) { @@ -2621,7 +2674,8 @@ EXPORT_SYMBOL(drm_probe_ddc); * @connector: connector we're probing * @adapter: I2C adapter to use for DDC * - * Poke the given I2C channel to grab EDID data if possible. If found, + * If the connector allows it, try to fetch EDID data using ACPI. If not found + * poke the given I2C channel to grab EDID data if possible. If found, * attach it to the connector. * * Return: Pointer to valid EDID or NULL if we couldn't find any. @@ -2629,20 +2683,50 @@ EXPORT_SYMBOL(drm_probe_ddc); struct edid *drm_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) { - struct edid *edid; + struct edid *edid = NULL; if (connector->force == DRM_FORCE_OFF) return NULL; - if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter)) - return NULL; + if (connector->acpi_edid_allowed) + edid = _drm_do_get_edid(connector, drm_do_probe_acpi_edid, connector, NULL); + + if (!edid) { + if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter)) + return NULL; + edid = _drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter, NULL); + } - edid = _drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter, NULL); drm_connector_update_edid_property(connector, edid); return edid; } EXPORT_SYMBOL(drm_get_edid); +/** + * drm_edid_read_acpi - get EDID data, if available + * @connector: connector we're probing + * + * Use the BIOS to attempt to grab EDID data if possible. + * + * The returned pointer must be freed using drm_edid_free(). + * + * Return: Pointer to valid EDID or NULL if we couldn't find any. + */ +const struct drm_edid *drm_edid_read_acpi(struct drm_connector *connector) +{ + const struct drm_edid *drm_edid; + + if (connector->force == DRM_FORCE_OFF) + return NULL; + + drm_edid = drm_edid_read_custom(connector, drm_do_probe_acpi_edid, connector); + + /* Note: Do *not* call connector updates here. */ + + return drm_edid; +} +EXPORT_SYMBOL(drm_edid_read_acpi); + /** * drm_edid_read_custom - Read EDID data using given EDID block read function * @connector: Connector to use @@ -2727,10 +2811,11 @@ const struct drm_edid *drm_edid_read_ddc(struct drm_connector *connector, EXPORT_SYMBOL(drm_edid_read_ddc); /** - * drm_edid_read - Read EDID data using connector's I2C adapter + * drm_edid_read - Read EDID data using BIOS or connector's I2C adapter * @connector: Connector to use * - * Read EDID using the connector's I2C adapter. + * Read EDID from BIOS if allowed by connector or by using the connector's + * I2C adapter. * * The EDID may be overridden using debugfs override_edid or firmware EDID * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority @@ -2742,10 +2827,18 @@ EXPORT_SYMBOL(drm_edid_read_ddc); */ const struct drm_edid *drm_edid_read(struct drm_connector *connector) { + const struct drm_edid *drm_edid = NULL; + if (drm_WARN_ON(connector->dev, !connector->ddc)) return NULL; - return drm_edid_read_ddc(connector, connector->ddc); + if (connector->acpi_edid_allowed) + drm_edid = drm_edid_read_acpi(connector); + + if (!drm_edid) + drm_edid = drm_edid_read_ddc(connector, connector->ddc); + + return drm_edid; } EXPORT_SYMBOL(drm_edid_read); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index fe88d7fc6b8f..74ed47f37a69 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1886,6 +1886,12 @@ struct drm_connector { /** @hdr_sink_metadata: HDR Metadata Information read from sink */ struct hdr_sink_metadata hdr_sink_metadata; + + /** + * @acpi_edid_allowed: Get the EDID from the BIOS, if available. + * This is only applicable to eDP and LVDS displays. + */ + bool acpi_edid_allowed; }; #define obj_to_connector(x) container_of(x, struct drm_connector, base) diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 7923bc00dc7a..1c1ee927de9c 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -459,5 +459,6 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid); const u8 *drm_find_edid_extension(const struct drm_edid *drm_edid, int ext_id, int *ext_index); +const struct drm_edid *drm_edid_read_acpi(struct drm_connector *connector); #endif /* __DRM_EDID_H__ */ -- 2.34.1
Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 4/5] drm/amd: Fetch the EDID from _DDC if available for eDP
Some manufacturers have intentionally put an EDID that differs from the EDID on the internal panel on laptops. Attempt to fetch this EDID if it exists and prefer it over the EDID that is provided by the panel. If a user prefers to use the EDID from the panel, offer a module parameter that would disable this. Signed-off-by: Mario Limonciello <mario.limonciello at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 3 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 ++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +++- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 2 ++ 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 312dfaec7b4a..fcec39a62a39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -215,6 +215,7 @@ extern int amdgpu_smartshift_bias; extern int amdgpu_use_xgmi_p2p; extern int amdgpu_mtype_local; extern bool enforce_isolation; +extern bool acpi_edid; #ifdef CONFIG_HSA_AMD extern int sched_policy; extern bool debug_evictions; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 9caba10315a8..9165a199ac9b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -281,6 +281,9 @@ static void amdgpu_connector_get_edid(struct drm_connector *connector) if (amdgpu_connector->edid) return; + /* if the BIOS specifies the EDID via _DDC, prefer this */ + connector->acpi_edid_allowed = acpi_edid; + /* on hw with routers, select right port */ if (amdgpu_connector->router.ddc_valid) amdgpu_i2c_router_select_ddc_port(amdgpu_connector); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 161ecf9b4174..9676df447a57 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -166,6 +166,7 @@ uint amdgpu_sdma_phase_quantum = 32; char *amdgpu_disable_cu; char *amdgpu_virtual_display; bool enforce_isolation; +bool acpi_edid = true; /* * OverDrive(bit 14) disabled by default * GFX DCS(bit 19) disabled by default @@ -990,6 +991,13 @@ MODULE_PARM_DESC(wbrf, "Enable Wifi RFI interference mitigation (0 = disabled, 1 = enabled, -1 = auto(default)"); module_param_named(wbrf, amdgpu_wbrf, int, 0444); +/** + * DOC: acpi_edid (bool) + * Try to fetch EDID for eDP display from BIOS using ACPI _DDC method. + */ +module_param(acpi_edid, bool, 0444); +MODULE_PARM_DESC(acpi_edid, "Fetch EDID for eDP display from BIOS"); + /* These devices are not supported by amdgpu. * They are supported by the mach64, r128, radeon drivers */ diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 467796d97313..504577ea36e7 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6649,8 +6649,10 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) * Note: drm_get_edid gets edid in the following order: * 1) override EDID if set via edid_override debugfs, * 2) firmware EDID if set via edid_firmware module parameter - * 3) regular DDC read. + * 3) ACPI EDID if allowed via module parameter + * 4) regular DDC read. */ + connector->acpi_edid_allowed = acpi_edid; edid = drm_get_edid(connector, &amdgpu_connector->ddc_bus->aux.ddc); if (!edid) { DRM_ERROR("No EDID found on connector: %s.\n", connector->name); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 85b7f58a7f35..d570a1b6141b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -910,6 +910,8 @@ enum dc_edid_status dm_helpers_read_local_edid( * do check sum and retry to make sure read correct edid. */ do { + /* prefer ACPI over panel for eDP */ + connector->acpi_edid_allowed = acpi_edid; edid = drm_get_edid(&aconnector->base, ddc); -- 2.34.1
Mario Limonciello
2024-Feb-14 21:57 UTC
[PATCH v6 5/5] drm/nouveau: Use drm_edid_read_acpi() helper
Rather than inventing a wrapper to acpi_video_get_edid() use the one provided by drm. This fixes two problems: 1. A memory leak that the memory provided by the ACPI call was never freed. 2. Validation of the BIOS provided blob. Convert the usage in nouveau_connector_detect_lvds() to use struct drm_edid at the same time. Signed-off-by: Mario Limonciello <mario.limonciello at amd.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 27 ---------------- drivers/gpu/drm/nouveau/nouveau_acpi.h | 2 -- drivers/gpu/drm/nouveau/nouveau_connector.c | 35 +++++++++------------ 3 files changed, 14 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 8f0c69aad248..de9daafb3fbb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -360,33 +360,6 @@ void nouveau_unregister_dsm_handler(void) {} void nouveau_switcheroo_optimus_dsm(void) {} #endif -void * -nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) -{ - struct acpi_device *acpidev; - int type, ret; - void *edid; - - switch (connector->connector_type) { - case DRM_MODE_CONNECTOR_LVDS: - case DRM_MODE_CONNECTOR_eDP: - type = ACPI_VIDEO_DISPLAY_LCD; - break; - default: - return NULL; - } - - acpidev = ACPI_COMPANION(dev->dev); - if (!acpidev) - return NULL; - - ret = acpi_video_get_edid(acpidev, type, -1, &edid); - if (ret < 0) - return NULL; - - return kmemdup(edid, EDID_LENGTH, GFP_KERNEL); -} - bool nouveau_acpi_video_backlight_use_native(void) { return acpi_video_backlight_use_native(); diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.h b/drivers/gpu/drm/nouveau/nouveau_acpi.h index e39dd8b94b8b..6a3def8e6cca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -10,7 +10,6 @@ bool nouveau_is_v1_dsm(void); void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); void nouveau_switcheroo_optimus_dsm(void); -void *nouveau_acpi_edid(struct drm_device *, struct drm_connector *); bool nouveau_acpi_video_backlight_use_native(void); void nouveau_acpi_video_register_backlight(void); #else @@ -19,7 +18,6 @@ static inline bool nouveau_is_v1_dsm(void) { return false; }; static inline void nouveau_register_dsm_handler(void) {} static inline void nouveau_unregister_dsm_handler(void) {} static inline void nouveau_switcheroo_optimus_dsm(void) {} -static inline void *nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return NULL; } static inline bool nouveau_acpi_video_backlight_use_native(void) { return true; } static inline void nouveau_acpi_video_register_backlight(void) {} #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 856b3ef5edb8..492035dc8453 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -687,22 +687,13 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; - struct edid *edid = NULL; + const struct drm_edid *drm_edid = NULL; enum drm_connector_status status = connector_status_disconnected; nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) goto out; - /* Try retrieving EDID via DDC */ - if (!drm->vbios.fp_no_ddc) { - status = nouveau_connector_detect(connector, force); - if (status == connector_status_connected) { - edid = nv_connector->edid; - goto out; - } - } - /* On some laptops (Sony, i'm looking at you) there appears to * be no direct way of accessing the panel's EDID. The only * option available to us appears to be to ask ACPI for help.. @@ -712,10 +703,14 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * the nouveau decides an entry in the VBIOS FP mode table is * valid - it's not (rh#613284) */ - if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - edid = nouveau_acpi_edid(dev, connector); - if (edid) { - status = connector_status_connected; + if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) + connector->acpi_edid_allowed = true; + + /* Try retrieving EDID via BIOS or DDC */ + if (!drm->vbios.fp_no_ddc || nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { + status = nouveau_connector_detect(connector, force); + if (status == connector_status_connected) { + drm_edid = drm_edid_alloc(nv_connector->edid, EDID_LENGTH); goto out; } } @@ -734,12 +729,9 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * stored for the panel stored in them. */ if (!drm->vbios.fp_no_ddc) { - edid = (struct edid *)nouveau_bios_embedded_edid(dev); - if (edid) { - edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - if (edid) - status = connector_status_connected; - } + drm_edid = drm_edid_alloc(nouveau_bios_embedded_edid(dev), EDID_LENGTH); + if (drm_edid) + status = connector_status_connected; } out: @@ -750,7 +742,8 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) status = connector_status_unknown; #endif - nouveau_connector_set_edid(nv_connector, edid); + drm_edid_connector_update(connector, drm_edid); + drm_edid_free(drm_edid); if (nv_encoder) nouveau_connector_set_encoder(connector, nv_encoder); return status; -- 2.34.1