summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h1
-rw-r--r--drivers/gpu/drm/arm/Kconfig1
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c7
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c17
-rw-r--r--drivers/gpu/drm/bridge/Kconfig3
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c5
-rw-r--r--drivers/gpu/drm/drm_cache.c2
-rw-r--r--drivers/gpu/drm/drm_connector.c3
-rw-r--r--drivers/gpu/drm/drm_edid.c15
-rw-r--r--drivers/gpu/drm/drm_of.c7
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c8
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c7
-rw-r--r--drivers/gpu/drm/i915/Makefile1
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c16
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
-rw-r--r--drivers/gpu/drm/i915/intel_pch.c2
-rw-r--r--drivers/gpu/drm/i915/intel_pch.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c10
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c8
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c7
-rw-r--r--drivers/gpu/drm/mcde/mcde_drv.c7
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c8
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_rdma.c9
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_crtc.c15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c36
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h1
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c12
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c10
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_pll.c6
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c15
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/hs.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dmem.c3
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c8
-rw-r--r--drivers/gpu/drm/panel/Kconfig1
-rw-r--r--drivers/gpu/drm/panel/panel-abt-y030xx067a.c4
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9322.c4
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9341.c3
-rw-r--r--drivers/gpu/drm/panel/panel-innolux-ej030na.c4
-rw-r--r--drivers/gpu/drm/panel/panel-lg-lb035q02.c4
-rw-r--r--drivers/gpu/drm/panel/panel-lg-lg4573.c4
-rw-r--r--drivers/gpu/drm/panel/panel-nec-nl8048hl11.c4
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt39016.c4
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-db7430.c3
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-ld9040.c4
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6d27a1.c3
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c3
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c2
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7789v.c4
-rw-r--r--drivers/gpu/drm/panel/panel-sony-acx565akm.c4
-rw-r--r--drivers/gpu/drm/panel/panel-tpo-td028ttec1.c4
-rw-r--r--drivers/gpu/drm/panel/panel-tpo-td043mtea1.c4
-rw-r--r--drivers/gpu/drm/panel/panel-tpo-tpg110.c3
-rw-r--r--drivers/gpu/drm/panel/panel-widechips-ws2401.c3
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c28
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.h4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c7
-rw-r--r--drivers/gpu/drm/selftests/test-drm_plane_helper.c8
-rw-r--r--drivers/gpu/drm/sprd/sprd_drm.c7
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c7
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c11
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.h8
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9163.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c4
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c4
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c4
-rw-r--r--drivers/gpu/drm/tiny/panel-mipi-dbi.c4
-rw-r--r--drivers/gpu/drm/tiny/repaper.c4
-rw-r--r--drivers/gpu/drm/tiny/st7586.c4
-rw-r--r--drivers/gpu/drm/tiny/st7735r.c4
-rw-r--r--drivers/gpu/drm/ttm/ttm_range_manager.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c7
-rw-r--r--drivers/gpu/drm/xen/xen_drm_front_evtchnl.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-csi.c6
-rw-r--r--drivers/gpu/vga/Kconfig19
-rw-r--r--drivers/gpu/vga/Makefile1
-rw-r--r--drivers/gpu/vga/vgaarb.c1567
86 files changed, 189 insertions, 1896 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 3a29d857640b..7e3a7fcb9fe6 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -24,6 +24,7 @@
#include <linux/hmm.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
+#include <linux/migrate.h>
#include "amdgpu_sync.h"
#include "amdgpu_object.h"
#include "amdgpu_vm.h"
@@ -221,7 +222,6 @@ svm_migrate_get_vram_page(struct svm_range *prange, unsigned long pfn)
page = pfn_to_page(pfn);
svm_range_bo_ref(prange->svm_bo);
page->zone_device_data = prange->svm_bo;
- get_page(page);
lock_page(page);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index f36062be9ca8..9967a73d5b0f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -26,6 +26,7 @@
#include <linux/hashtable.h>
#include <linux/mmu_notifier.h>
+#include <linux/memremap.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/atomic.h>
diff --git a/drivers/gpu/drm/arm/Kconfig b/drivers/gpu/drm/arm/Kconfig
index 58a242871b28..6e3f1d600541 100644
--- a/drivers/gpu/drm/arm/Kconfig
+++ b/drivers/gpu/drm/arm/Kconfig
@@ -6,6 +6,7 @@ config DRM_HDLCD
depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
depends on COMMON_CLK
select DRM_KMS_HELPER
+ select DRM_GEM_CMA_HELPER
help
Choose this option if you have an ARM High Definition Colour LCD
controller.
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index 51e51ff299b7..ba16895690f1 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -93,11 +93,6 @@ static const struct component_master_ops komeda_master_ops = {
.unbind = komeda_unbind,
};
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static void komeda_add_slave(struct device *master,
struct component_match **match,
struct device_node *np,
@@ -107,7 +102,7 @@ static void komeda_add_slave(struct device *master,
remote = of_graph_get_remote_node(np, port, endpoint);
if (remote) {
- drm_of_component_match_add(master, match, compare_of, remote);
+ drm_of_component_match_add(master, match, component_compare_of, remote);
of_node_put(remote);
}
}
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 4f9b0a9f13e3..0643887800b4 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -177,17 +177,6 @@ static void armada_drm_unbind(struct device *dev)
drm_mm_takedown(&priv->linear);
}
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
-static int compare_dev_name(struct device *dev, void *data)
-{
- const char *name = data;
- return !strcmp(dev_name(dev), name);
-}
-
static void armada_add_endpoints(struct device *dev,
struct component_match **match, struct device_node *dev_node)
{
@@ -196,7 +185,7 @@ static void armada_add_endpoints(struct device *dev,
for_each_endpoint_of_node(dev_node, ep) {
remote = of_graph_get_remote_port_parent(ep);
if (remote && of_device_is_available(remote))
- drm_of_component_match_add(dev, match, compare_of,
+ drm_of_component_match_add(dev, match, component_compare_of,
remote);
of_node_put(remote);
}
@@ -213,7 +202,7 @@ static int armada_drm_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
int ret;
- ret = drm_of_component_probe(dev, compare_dev_name, &armada_master_ops);
+ ret = drm_of_component_probe(dev, component_compare_dev_name, &armada_master_ops);
if (ret != -EINVAL)
return ret;
@@ -223,7 +212,7 @@ static int armada_drm_probe(struct platform_device *pdev)
int i;
for (i = 0; devices[i]; i++)
- component_match_add(dev, &match, compare_dev_name,
+ component_match_add(dev, &match, component_compare_dev_name,
devices[i]);
if (i == 0) {
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index c86f5be4dfe0..007e5a282f67 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -8,7 +8,6 @@ config DRM_BRIDGE
config DRM_PANEL_BRIDGE
def_bool y
depends on DRM_BRIDGE
- depends on DRM_KMS_HELPER
select DRM_PANEL
help
DRM bridge wrapper of DRM panels
@@ -30,7 +29,7 @@ config DRM_CDNS_DSI
config DRM_CHIPONE_ICN6211
tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
depends on OF
- depends on DRM_KMS_HELPER
+ select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL_BRIDGE
help
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 38616aab12ac..fb6c588b0f71 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -1758,6 +1758,7 @@ static inline void ti_sn_gpio_unregister(void) {}
static void ti_sn65dsi86_runtime_disable(void *data)
{
+ pm_runtime_dont_use_autosuspend(data);
pm_runtime_disable(data);
}
@@ -1817,11 +1818,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
"failed to get reference clock\n");
pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(pdata->dev, 500);
+ pm_runtime_use_autosuspend(pdata->dev);
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev);
if (ret)
return ret;
- pm_runtime_set_autosuspend_delay(pdata->dev, 500);
- pm_runtime_use_autosuspend(pdata->dev);
ti_sn65dsi86_debugfs_init(pdata);
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
index c3e6e615bf09..7051c9c909c2 100644
--- a/drivers/gpu/drm/drm_cache.c
+++ b/drivers/gpu/drm/drm_cache.c
@@ -27,10 +27,10 @@
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
-
#include <linux/cc_platform.h>
#include <linux/export.h>
#include <linux/highmem.h>
+#include <linux/ioport.h>
#include <linux/iosys-map.h>
#include <xen/xen.h>
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index a50c82bc2b2f..76a8c707c34b 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2330,6 +2330,9 @@ EXPORT_SYMBOL(drm_connector_atomic_hdr_metadata_equal);
void drm_connector_set_vrr_capable_property(
struct drm_connector *connector, bool capable)
{
+ if (!connector->vrr_capable_property)
+ return;
+
drm_object_property_set_value(&connector->base,
connector->vrr_capable_property,
capable);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 561f53831e29..cc7bd58369df 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -4859,7 +4859,8 @@ bool drm_detect_monitor_audio(struct edid *edid)
if (!edid_ext)
goto end;
- has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
+ has_audio = (edid_ext[0] == CEA_EXT &&
+ (edid_ext[3] & EDID_BASIC_AUDIO) != 0);
if (has_audio) {
DRM_DEBUG_KMS("Monitor has basic audio support\n");
@@ -5187,10 +5188,14 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
/* The existence of a CEA block should imply RGB support */
info->color_formats = DRM_COLOR_FORMAT_RGB444;
- if (edid_ext[3] & EDID_CEA_YCRCB444)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
- if (edid_ext[3] & EDID_CEA_YCRCB422)
- info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
+
+ /* CTA DisplayID Data Block does not have byte #3 */
+ if (edid_ext[0] == CEA_EXT) {
+ if (edid_ext[3] & EDID_CEA_YCRCB444)
+ info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
+ if (edid_ext[3] & EDID_CEA_YCRCB422)
+ info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
+ }
if (cea_db_offsets(edid_ext, &start, &end))
return;
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index 9d90cd75c457..026e4e29a0f3 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -18,11 +18,6 @@
* properties.
*/
-static void drm_release_of(struct device *dev, void *data)
-{
- of_node_put(data);
-}
-
/**
* drm_of_crtc_port_mask - find the mask of a registered CRTC by port OF node
* @dev: DRM device
@@ -94,7 +89,7 @@ void drm_of_component_match_add(struct device *master,
struct device_node *node)
{
of_node_get(node);
- component_match_add_release(master, matchptr, drm_release_of,
+ component_match_add_release(master, matchptr, component_release_of,
compare, node);
}
EXPORT_SYMBOL_GPL(drm_of_component_match_add);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 0b756ecb1bc2..1d2b4fb4bcf8 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -574,18 +574,6 @@ static const struct component_master_ops etnaviv_master_ops = {
.unbind = etnaviv_unbind,
};
-static int compare_of(struct device *dev, void *data)
-{
- struct device_node *np = data;
-
- return dev->of_node == np;
-}
-
-static int compare_str(struct device *dev, void *data)
-{
- return !strcmp(dev_name(dev), data);
-}
-
static int etnaviv_pdev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -603,14 +591,14 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
first_node = core_node;
drm_of_component_match_add(&pdev->dev, &match,
- compare_of, core_node);
+ component_compare_of, core_node);
}
} else {
char **names = dev->platform_data;
unsigned i;
for (i = 0; names[i]; i++)
- component_match_add(dev, &match, compare_str, names[i]);
+ component_match_add(dev, &match, component_compare_dev_name, names[i]);
}
/*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index c68498497c0b..424ea23eec32 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -212,11 +212,6 @@ static struct exynos_drm_driver_info exynos_drm_drivers[] = {
}
};
-static int compare_dev(struct device *dev, void *data)
-{
- return dev == (struct device *)data;
-}
-
static struct component_match *exynos_drm_match_add(struct device *dev)
{
struct component_match *match = NULL;
@@ -234,8 +229,7 @@ static struct component_match *exynos_drm_match_add(struct device *dev)
if (!(info->flags & DRM_FIMC_DEVICE) ||
exynos_drm_check_fimc_device(d) == 0)
- component_match_add(dev, &match,
- compare_dev, d);
+ component_match_add(dev, &match, component_compare_dev, d);
p = d;
}
put_device(p);
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 3cf057269f2a..2af51df6dca7 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -204,11 +204,6 @@ err_mode_config_cleanup:
return ret;
}
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static int kirin_drm_kms_cleanup(struct drm_device *dev)
{
drm_kms_helper_poll_fini(dev);
@@ -279,7 +274,7 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
if (!remote)
return -ENODEV;
- drm_of_component_match_add(dev, &match, compare_of, remote);
+ drm_of_component_match_add(dev, &match, component_compare_of, remote);
of_node_put(remote);
return component_master_add_with_match(dev, &kirin_drm_ops, match);
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 9d588d936e3d..7df74a71d454 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -18,6 +18,7 @@ subdir-ccflags-y += -Wno-unused-parameter
subdir-ccflags-y += -Wno-type-limits
subdir-ccflags-y += -Wno-missing-field-initializers
subdir-ccflags-y += -Wno-sign-compare
+subdir-ccflags-y += -Wno-shift-negative-value
subdir-ccflags-y += $(call cc-disable-warning, unused-but-set-variable)
subdir-ccflags-y += $(call cc-disable-warning, frame-address)
subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index ad1564ca7269..adf58c58513b 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -992,7 +992,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state)
* cause.
*/
if (!intel_can_enable_sagv(dev_priv, new_bw_state)) {
- allowed_points = BIT(max_bw_point);
+ allowed_points &= ADLS_PSF_PT_MASK;
+ allowed_points |= BIT(max_bw_point);
drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n",
max_bw_point);
}
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 1aa5bdc7b0dc..6512f014cad4 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -1836,6 +1836,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
bool has_hdmi_sink)
{
struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi);
+ enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port);
if (clock < 25000)
return MODE_CLOCK_LOW;
@@ -1856,6 +1857,14 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi,
if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
return MODE_CLOCK_RANGE;
+ /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */
+ if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200)
+ return MODE_CLOCK_RANGE;
+
+ /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */
+ if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800)
+ return MODE_CLOCK_RANGE;
+
/*
* SNPS PHYs' MPLLB table-based programming can only handle a fixed
* set of link rates.
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 5895b89df03a..bff8c2d73cdf 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -1439,6 +1439,13 @@ static inline u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private
PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
}
+static inline u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
+{
+ return IS_ALDERLAKE_P(dev_priv) ?
+ ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE :
+ PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
+}
+
static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -1543,7 +1550,13 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- u32 val = PSR2_MAN_TRK_CTL_ENABLE;
+ u32 val = 0;
+
+ if (!IS_ALDERLAKE_P(dev_priv))
+ val = PSR2_MAN_TRK_CTL_ENABLE;
+
+ /* SF partial frame enable has to be set even on full update */
+ val |= man_trk_ctl_partial_frame_bit_get(dev_priv);
if (full_update) {
/*
@@ -1563,7 +1576,6 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
} else {
drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4);
- val |= PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1);
val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1);
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
index 9bb551b83e7a..92cb88248391 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -57,7 +57,7 @@ struct __guc_ads_blob {
struct guc_gt_system_info system_info;
struct guc_engine_usage engine_usage;
/* From here on, location is dynamic! Refer to above diagram. */
- struct guc_mmio_reg regset[0];
+ struct guc_mmio_reg regset[];
} __packed;
#define ads_blob_read(guc_, field_) \
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index d134838b3458..fa14da84362e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -947,7 +947,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915)
(GRAPHICS_VER(i915) >= (from) && GRAPHICS_VER(i915) <= (until))
#define MEDIA_VER(i915) (INTEL_INFO(i915)->media.ver)
-#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.arch, \
+#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.ver, \
INTEL_INFO(i915)->media.rel)
#define IS_MEDIA_VER(i915, from, until) \
(MEDIA_VER(i915) >= (from) && MEDIA_VER(i915) <= (until))
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4da10e131216..3c87d77d2cf6 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2320,6 +2320,7 @@
#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val)
#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0)
#define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val)
+#define ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31)
#define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14)
#define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13)
diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c
index 4f7a61d5502e..4cce044efde2 100644
--- a/drivers/gpu/drm/i915/intel_pch.c
+++ b/drivers/gpu/drm/i915/intel_pch.c
@@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
/* Comet Lake V PCH is based on KBP, which is SPT compatible */
return PCH_SPT;
case INTEL_PCH_ICP_DEVICE_ID_TYPE:
+ case INTEL_PCH_ICP2_DEVICE_ID_TYPE:
drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n");
drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));
return PCH_ICP;
@@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
!IS_GEN9_BC(dev_priv));
return PCH_TGP;
case INTEL_PCH_JSP_DEVICE_ID_TYPE:
- case INTEL_PCH_JSP2_DEVICE_ID_TYPE:
drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n");
drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv));
return PCH_JSP;
diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h
index 6fd20408f7bf..b7a8cf409d48 100644
--- a/drivers/gpu/drm/i915/intel_pch.h
+++ b/drivers/gpu/drm/i915/intel_pch.h
@@ -50,11 +50,11 @@ enum intel_pch {
#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680
#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380
#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480
+#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880
#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00
#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080
#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380
#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80
-#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880
#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80
#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
#define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 71f7fba2c9e2..9333f732cda8 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3698,8 +3698,7 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv)
MISSING_CASE(DISPLAY_VER(dev_priv));
}
- /* Default to an unusable block time */
- dev_priv->sagv_block_time_us = -1;
+ dev_priv->sagv_block_time_us = 0;
}
/*
@@ -5645,7 +5644,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state,
result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1;
result->enable = true;
- if (DISPLAY_VER(dev_priv) < 12)
+ if (DISPLAY_VER(dev_priv) < 12 && dev_priv->sagv_block_time_us)
result->can_sagv = latency >= dev_priv->sagv_block_time_us;
}
@@ -5678,7 +5677,10 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state,
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0;
struct skl_wm_level *levels = plane_wm->wm;
- unsigned int latency = dev_priv->wm.skl_latency[0] + dev_priv->sagv_block_time_us;
+ unsigned int latency = 0;
+
+ if (dev_priv->sagv_block_time_us)
+ latency = dev_priv->sagv_block_time_us + dev_priv->wm.skl_latency[0];
skl_compute_plane_wm(crtc_state, plane, 0, latency,
wm_params, &levels[0],
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index a8aba0141ce7..06cb1a59b9bc 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -217,14 +217,6 @@ static int imx_pd_bridge_atomic_check(struct drm_bridge *bridge,
if (!imx_pd_format_supported(bus_fmt))
return -EINVAL;
- if (bus_flags &
- ~(DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_DE_HIGH |
- DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
- DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)) {
- dev_warn(imxpd->dev, "invalid bus_flags (%x)\n", bus_flags);
- return -EINVAL;
- }
-
bridge_state->output_bus_cfg.flags = bus_flags;
bridge_state->input_bus_cfg.flags = bus_flags;
imx_crtc_state->bus_flags = bus_flags;
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index dcf44cb00821..ac52b49bf901 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1371,11 +1371,6 @@ static int ingenic_drm_bind_with_components(struct device *dev)
return ingenic_drm_bind(dev, true);
}
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static void ingenic_drm_unbind(struct device *dev)
{
struct ingenic_drm *priv = dev_get_drvdata(dev);
@@ -1409,7 +1404,7 @@ static int ingenic_drm_probe(struct platform_device *pdev)
if (!np)
return ingenic_drm_bind(dev, false);
- drm_of_component_match_add(dev, &match, compare_of, np);
+ drm_of_component_match_add(dev, &match, component_compare_of, np);
of_node_put(np);
return component_master_add_with_match(dev, &ingenic_master_ops, match);
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
index 0b2910e69b42..e601baa87e55 100644
--- a/drivers/gpu/drm/mcde/mcde_drv.c
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -265,11 +265,6 @@ static struct platform_driver *const mcde_component_drivers[] = {
&mcde_dsi_driver,
};
-static int mcde_compare_dev(struct device *dev, void *data)
-{
- return dev == data;
-}
-
static int mcde_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -399,7 +394,7 @@ static int mcde_probe(struct platform_device *pdev)
while ((d = platform_find_device_by_driver(p, drv))) {
put_device(p);
- component_match_add(dev, &match, mcde_compare_dev, d);
+ component_match_add(dev, &match, component_compare_dev, d);
p = d;
}
put_device(p);
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 2146299e5f52..17cd9b932298 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -11,6 +11,7 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_disp_drv.h"
@@ -414,9 +415,13 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
return ret;
}
+ pm_runtime_enable(dev);
+
ret = component_add(dev, &mtk_disp_ovl_component_ops);
- if (ret)
+ if (ret) {
+ pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+ }
return ret;
}
@@ -424,6 +429,7 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
static int mtk_disp_ovl_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
+ pm_runtime_disable(&pdev->dev);
return 0;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index d41a3970b944..662e91d9d45f 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -9,6 +9,7 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk-cmdq.h>
#include "mtk_disp_drv.h"
@@ -327,9 +328,13 @@ static int mtk_disp_rdma_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
+ pm_runtime_enable(dev);
+
ret = component_add(dev, &mtk_disp_rdma_component_ops);
- if (ret)
+ if (ret) {
+ pm_runtime_disable(dev);
dev_err(dev, "Failed to add component: %d\n", ret);
+ }
return ret;
}
@@ -338,6 +343,8 @@ static int mtk_disp_rdma_remove(struct platform_device *pdev)
{
component_del(&pdev->dev, &mtk_disp_rdma_component_ops);
+ pm_runtime_disable(&pdev->dev);
+
return 0;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
index 8cc0a1283d7c..ede435d2c1ef 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -12,7 +12,6 @@
#include <linux/soc/mediatek/mtk-mutex.h>
#include <asm/barrier.h>
-#include <soc/mediatek/smi.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@@ -663,15 +662,15 @@ static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
- ret = mtk_smi_larb_get(comp->larb_dev);
- if (ret) {
- DRM_ERROR("Failed to get larb: %d\n", ret);
+ ret = pm_runtime_resume_and_get(comp->dev);
+ if (ret < 0) {
+ DRM_DEV_ERROR(comp->dev, "Failed to enable power domain: %d\n", ret);
return;
}
ret = mtk_crtc_ddp_hw_init(mtk_crtc);
if (ret) {
- mtk_smi_larb_put(comp->larb_dev);
+ pm_runtime_put(comp->dev);
return;
}
@@ -684,7 +683,7 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
{
struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
struct mtk_ddp_comp *comp = mtk_crtc->ddp_comp[0];
- int i;
+ int i, ret;
DRM_DEBUG_DRIVER("%s %d\n", __func__, crtc->base.id);
if (!mtk_crtc->enabled)
@@ -714,7 +713,9 @@ static void mtk_drm_crtc_atomic_disable(struct drm_crtc *crtc,
drm_crtc_vblank_off(crtc);
mtk_crtc_ddp_hw_fini(mtk_crtc);
- mtk_smi_larb_put(comp->larb_dev);
+ ret = pm_runtime_put(comp->dev);
+ if (ret < 0)
+ DRM_DEV_ERROR(comp->dev, "Failed to disable power domain: %d\n", ret);
mtk_crtc->enabled = false;
}
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index b4b682bc1991..2e99aee13dfe 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -447,37 +447,15 @@ unsigned int mtk_drm_find_possible_crtc_by_comp(struct drm_device *drm,
return ret;
}
-static int mtk_ddp_get_larb_dev(struct device_node *node, struct mtk_ddp_comp *comp,
- struct device *dev)
-{
- struct device_node *larb_node;
- struct platform_device *larb_pdev;
-
- larb_node = of_parse_phandle(node, "mediatek,larb", 0);
- if (!larb_node) {
- dev_err(dev, "Missing mediadek,larb phandle in %pOF node\n", node);
- return -EINVAL;
- }
-
- larb_pdev = of_find_device_by_node(larb_node);
- if (!larb_pdev) {
- dev_warn(dev, "Waiting for larb device %pOF\n", larb_node);
- of_node_put(larb_node);
- return -EPROBE_DEFER;
- }
- of_node_put(larb_node);
- comp->larb_dev = &larb_pdev->dev;
-
- return 0;
-}
-
int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
enum mtk_ddp_comp_id comp_id)
{
struct platform_device *comp_pdev;
enum mtk_ddp_comp_type type;
struct mtk_ddp_comp_dev *priv;
+#if IS_REACHABLE(CONFIG_MTK_CMDQ)
int ret;
+#endif
if (comp_id < 0 || comp_id >= DDP_COMPONENT_ID_MAX)
return -EINVAL;
@@ -493,16 +471,6 @@ int mtk_ddp_comp_init(struct device_node *node, struct mtk_ddp_comp *comp,
}
comp->dev = &comp_pdev->dev;
- /* Only DMA capable components need the LARB property */
- if (type == MTK_DISP_OVL ||
- type == MTK_DISP_OVL_2L ||
- type == MTK_DISP_RDMA ||
- type == MTK_DISP_WDMA) {
- ret = mtk_ddp_get_larb_dev(node, comp, comp->dev);
- if (ret)
- return ret;
- }
-
if (type == MTK_DISP_AAL ||
type == MTK_DISP_BLS ||
type == MTK_DISP_CCORR ||
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
index 4c6a98662305..ad267bb8fc9b 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h
@@ -71,7 +71,6 @@ struct mtk_ddp_comp_funcs {
struct mtk_ddp_comp {
struct device *dev;
int irq;
- struct device *larb_dev;
enum mtk_ddp_comp_id id;
const struct mtk_ddp_comp_funcs *funcs;
};
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index dd029307be7d..247c6ff277ef 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -372,11 +372,6 @@ static const struct drm_driver mtk_drm_driver = {
.minor = DRIVER_MINOR,
};
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static int mtk_drm_bind(struct device *dev)
{
struct mtk_drm_private *private = dev_get_drvdata(dev);
@@ -617,7 +612,7 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type == MTK_DSI) {
dev_info(dev, "Adding component match for %pOF\n",
node);
- drm_of_component_match_add(dev, &match, compare_of,
+ drm_of_component_match_add(dev, &match, component_compare_of,
node);
}
@@ -648,11 +643,8 @@ err_pm:
pm_runtime_disable(dev);
err_node:
of_node_put(private->mutex_node);
- for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) {
+ for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
of_node_put(private->comp_node[i]);
- if (private->ddp_comp[i].larb_dev)
- put_device(private->ddp_comp[i].larb_dev);
- }
return ret;
}
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 93a7a033a3e8..edae79f41153 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -425,14 +425,6 @@ static int __maybe_unused meson_drv_pm_resume(struct device *dev)
return drm_mode_config_helper_resume(priv->drm);
}
-static int compare_of(struct device *dev, void *data)
-{
- DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n",
- dev->of_node, data);
-
- return dev->of_node == data;
-}
-
static void meson_drv_shutdown(struct platform_device *pdev)
{
struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
@@ -475,7 +467,7 @@ static int meson_drv_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "parent %pOF remote match add %pOF parent %s\n",
np, remote, dev_name(&pdev->dev));
- component_match_add(&pdev->dev, &match, compare_of, remote);
+ component_match_add(&pdev->dev, &match, component_compare_of, remote);
of_node_put(remote);
diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c
index e9ae22b4f813..52be08b744ad 100644
--- a/drivers/gpu/drm/mgag200/mgag200_pll.c
+++ b/drivers/gpu/drm/mgag200/mgag200_pll.c
@@ -404,9 +404,9 @@ mgag200_pixpll_update_g200wb(struct mgag200_pll *pixpll, const struct mgag200_pl
udelay(50);
/* program pixel pll register */
- WREG_DAC(MGA1064_PIX_PLLC_N, xpixpllcn);
- WREG_DAC(MGA1064_PIX_PLLC_M, xpixpllcm);
- WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
+ WREG_DAC(MGA1064_WB_PIX_PLLC_N, xpixpllcn);
+ WREG_DAC(MGA1064_WB_PIX_PLLC_M, xpixpllcm);
+ WREG_DAC(MGA1064_WB_PIX_PLLC_P, xpixpllcp);
udelay(50);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 61c81af23ba7..affa95eb05fc 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1050,15 +1050,6 @@ static const struct dev_pm_ops msm_pm_ops = {
*/
/*
- * NOTE: duplication of the same code as exynos or imx (or probably any other).
- * so probably some room for some helpers
- */
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
-/*
* Identify what components need to be added by parsing what remote-endpoints
* our MDP output ports are connected to. In the case of LVDS on MDP4, there
* is no external component that we need to add since LVDS is within MDP4
@@ -1115,7 +1106,7 @@ static int add_components_mdp(struct device *mdp_dev,
if (of_device_is_available(intf))
drm_of_component_match_add(master_dev, matchptr,
- compare_of, intf);
+ component_compare_of, intf);
of_node_put(intf);
}
@@ -1161,7 +1152,7 @@ static int add_display_components(struct platform_device *pdev,
put_device(mdp_dev);
/* add the MDP component itself */
- drm_of_component_match_add(dev, matchptr, compare_of,
+ drm_of_component_match_add(dev, matchptr, component_compare_of,
mdp_dev->of_node);
break;
case KMS_MDP4:
@@ -1200,7 +1191,7 @@ static int add_gpu_components(struct device *dev,
return 0;
if (of_device_is_available(np))
- drm_of_component_match_add(dev, matchptr, compare_of, np);
+ drm_of_component_match_add(dev, matchptr, component_compare_of, np);
of_node_put(np);
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/hs.h b/drivers/gpu/drm/nouveau/include/nvfw/hs.h
index 64d0d32200c2..b53bbc4cd130 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/hs.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/hs.h
@@ -23,7 +23,7 @@ struct nvfw_hs_load_header {
u32 data_dma_base;
u32 data_size;
u32 num_apps;
- u32 apps[0];
+ u32 apps[];
};
const struct nvfw_hs_load_header *
diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c
index 3828aafd3ac4..7ba66ad68a8a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dmem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c
@@ -39,6 +39,8 @@
#include <linux/sched/mm.h>
#include <linux/hmm.h>
+#include <linux/memremap.h>
+#include <linux/migrate.h>
/*
* FIXME: this is ugly right now we are using TTM to allocate vram and we pin
@@ -324,7 +326,6 @@ nouveau_dmem_page_alloc_locked(struct nouveau_drm *drm)
return NULL;
}
- get_page(page);
lock_page(page);
return page;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 46a5a1016e37..31a5b81ee9fc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -35,6 +35,7 @@
#include <linux/sched/mm.h>
#include <linux/sort.h>
#include <linux/hmm.h>
+#include <linux/memremap.h>
#include <linux/rmap.h>
struct nouveau_svm {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index d0d52c1d4aee..992cc285f2fe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -133,7 +133,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
* or equal to the system's PAGE_SIZE, with a preference if
* both are equal.
*/
- pgsize_bitmap = tdev->iommu.domain->ops->pgsize_bitmap;
+ pgsize_bitmap = tdev->iommu.domain->pgsize_bitmap;
if (pgsize_bitmap & PAGE_SIZE) {
tdev->iommu.pgshift = PAGE_SHIFT;
} else {
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 69b3e15b9356..0399f3390a0a 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1344,12 +1344,6 @@ static const struct component_master_ops dss_component_ops = {
.unbind = dss_unbind,
};
-static int dss_component_compare(struct device *dev, void *data)
-{
- struct device *child = data;
- return dev == child;
-}
-
struct dss_component_match_data {
struct device *dev;
struct component_match **match;
@@ -1379,7 +1373,7 @@ static int dss_add_child_component(struct device *dev, void *data)
return device_for_each_child(dev, cmatch,
dss_add_child_component);
- component_match_add(cmatch->dev, match, dss_component_compare, dev);
+ component_match_add(cmatch->dev, match, component_compare_dev, dev);
return 0;
}
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index bb2e47229c68..ddf5f38e8731 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -107,6 +107,7 @@ config DRM_PANEL_EDP
select VIDEOMODE_HELPERS
select DRM_DP_AUX_BUS
select DRM_DP_HELPER
+ select DRM_KMS_HELPER
help
DRM panel driver for dumb eDP panels that need at most a regulator and
a GPIO to be powered up. Optionally a backlight can be attached so
diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
index f043b484055b..ed626fdc08e8 100644
--- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
+++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c
@@ -293,15 +293,13 @@ static int y030xx067a_probe(struct spi_device *spi)
return 0;
}
-static int y030xx067a_remove(struct spi_device *spi)
+static void y030xx067a_remove(struct spi_device *spi)
{
struct y030xx067a *priv = spi_get_drvdata(spi);
drm_panel_remove(&priv->panel);
drm_panel_disable(&priv->panel);
drm_panel_unprepare(&priv->panel);
-
- return 0;
}
static const struct drm_display_mode y030xx067a_modes[] = {
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
index 8e84df9a0033..3dfafa585127 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
@@ -896,14 +896,12 @@ static int ili9322_probe(struct spi_device *spi)
return 0;
}
-static int ili9322_remove(struct spi_device *spi)
+static void ili9322_remove(struct spi_device *spi)
{
struct ili9322 *ili = spi_get_drvdata(spi);
ili9322_power_off(ili);
drm_panel_remove(&ili->panel);
-
- return 0;
}
/*
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
index 2c3378a259b1..a07ef26234e5 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -728,7 +728,7 @@ static int ili9341_probe(struct spi_device *spi)
return -1;
}
-static int ili9341_remove(struct spi_device *spi)
+static void ili9341_remove(struct spi_device *spi)
{
const struct spi_device_id *id = spi_get_device_id(spi);
struct ili9341 *ili = spi_get_drvdata(spi);
@@ -741,7 +741,6 @@ static int ili9341_remove(struct spi_device *spi)
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
}
- return 0;
}
static void ili9341_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
index c558de3f99be..e3b1daa0cb72 100644
--- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c
+++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c
@@ -219,15 +219,13 @@ static int ej030na_probe(struct spi_device *spi)
return 0;
}
-static int ej030na_remove(struct spi_device *spi)
+static void ej030na_remove(struct spi_device *spi)
{
struct ej030na *priv = spi_get_drvdata(spi);
drm_panel_remove(&priv->panel);
drm_panel_disable(&priv->panel);
drm_panel_unprepare(&priv->panel);
-
- return 0;
}
static const struct drm_display_mode ej030na_modes[] = {
diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
index f3183b68704f..9d0d4faa3f58 100644
--- a/drivers/gpu/drm/panel/panel-lg-lb035q02.c
+++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c
@@ -203,14 +203,12 @@ static int lb035q02_probe(struct spi_device *spi)
return 0;
}
-static int lb035q02_remove(struct spi_device *spi)
+static void lb035q02_remove(struct spi_device *spi)
{
struct lb035q02_device *lcd = spi_get_drvdata(spi);
drm_panel_remove(&lcd->panel);
drm_panel_disable(&lcd->panel);
-
- return 0;
}
static const struct of_device_id lb035q02_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c
index 8e5160af1de5..cf246d15b7b6 100644
--- a/drivers/gpu/drm/panel/panel-lg-lg4573.c
+++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c
@@ -266,14 +266,12 @@ static int lg4573_probe(struct spi_device *spi)
return 0;
}
-static int lg4573_remove(struct spi_device *spi)
+static void lg4573_remove(struct spi_device *spi)
{
struct lg4573 *ctx = spi_get_drvdata(spi);
lg4573_display_off(ctx);
drm_panel_remove(&ctx->panel);
-
- return 0;
}
static const struct of_device_id lg4573_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
index 6e5ab1debc8b..81c5c541a351 100644
--- a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
+++ b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
@@ -212,15 +212,13 @@ static int nl8048_probe(struct spi_device *spi)
return 0;
}
-static int nl8048_remove(struct spi_device *spi)
+static void nl8048_remove(struct spi_device *spi)
{
struct nl8048_panel *lcd = spi_get_drvdata(spi);
drm_panel_remove(&lcd->panel);
drm_panel_disable(&lcd->panel);
drm_panel_unprepare(&lcd->panel);
-
- return 0;
}
static const struct of_device_id nl8048_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c
index d036853db865..f58cfb10b58a 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c
@@ -292,7 +292,7 @@ static int nt39016_probe(struct spi_device *spi)
return 0;
}
-static int nt39016_remove(struct spi_device *spi)
+static void nt39016_remove(struct spi_device *spi)
{
struct nt39016 *panel = spi_get_drvdata(spi);
@@ -300,8 +300,6 @@ static int nt39016_remove(struct spi_device *spi)
nt39016_disable(&panel->drm_panel);
nt39016_unprepare(&panel->drm_panel);
-
- return 0;
}
static const struct drm_display_mode kd035g6_display_modes[] = {
diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c
index ead479719f00..04640c5256a8 100644
--- a/drivers/gpu/drm/panel/panel-samsung-db7430.c
+++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c
@@ -314,12 +314,11 @@ static int db7430_probe(struct spi_device *spi)
return 0;
}
-static int db7430_remove(struct spi_device *spi)
+static void db7430_remove(struct spi_device *spi)
{
struct db7430 *db = spi_get_drvdata(spi);
drm_panel_remove(&db->panel);
- return 0;
}
/*
diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c
index c4b388850a13..01eb211f32f7 100644
--- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c
+++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c
@@ -358,14 +358,12 @@ static int ld9040_probe(struct spi_device *spi)
return 0;
}
-static int ld9040_remove(struct spi_device *spi)
+static void ld9040_remove(struct spi_device *spi)
{
struct ld9040 *ctx = spi_get_drvdata(spi);
ld9040_power_off(ctx);
drm_panel_remove(&ctx->panel);
-
- return 0;
}
static const struct of_device_id ld9040_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
index 1696ceb36aa0..2adb223a895c 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c
@@ -291,12 +291,11 @@ static int s6d27a1_probe(struct spi_device *spi)
return 0;
}
-static int s6d27a1_remove(struct spi_device *spi)
+static void s6d27a1_remove(struct spi_device *spi)
{
struct s6d27a1 *ctx = spi_get_drvdata(spi);
drm_panel_remove(&ctx->panel);
- return 0;
}
static const struct of_device_id s6d27a1_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
index c178d962b0d5..d99afcc672ca 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c
@@ -62,10 +62,9 @@ static int s6e63m0_spi_probe(struct spi_device *spi)
s6e63m0_spi_dcs_write, false);
}
-static int s6e63m0_spi_remove(struct spi_device *spi)
+static void s6e63m0_spi_remove(struct spi_device *spi)
{
s6e63m0_remove(&spi->dev);
- return 0;
}
static const struct of_device_id s6e63m0_spi_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index c09eb5ad65fc..a34f4198a534 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -2017,7 +2017,7 @@ static const struct display_timing innolux_g070y2_l01_timing = {
static const struct panel_desc innolux_g070y2_l01 = {
.timings = &innolux_g070y2_l01_timing,
.num_timings = 1,
- .bpc = 6,
+ .bpc = 8,
.size = {
.width = 152,
.height = 91,
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c
index 61e565524542..bbc4569cbcdc 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c
@@ -387,13 +387,11 @@ static int st7789v_probe(struct spi_device *spi)
return 0;
}
-static int st7789v_remove(struct spi_device *spi)
+static void st7789v_remove(struct spi_device *spi)
{
struct st7789v *ctx = spi_get_drvdata(spi);
drm_panel_remove(&ctx->panel);
-
- return 0;
}
static const struct of_device_id st7789v_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
index ba0b3ead150f..0d7541a33f87 100644
--- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -655,7 +655,7 @@ static int acx565akm_probe(struct spi_device *spi)
return 0;
}
-static int acx565akm_remove(struct spi_device *spi)
+static void acx565akm_remove(struct spi_device *spi)
{
struct acx565akm_panel *lcd = spi_get_drvdata(spi);
@@ -666,8 +666,6 @@ static int acx565akm_remove(struct spi_device *spi)
drm_panel_disable(&lcd->panel);
drm_panel_unprepare(&lcd->panel);
-
- return 0;
}
static const struct of_device_id acx565akm_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
index ba0c00d1a001..4dbf8b88f264 100644
--- a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
+++ b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
@@ -350,15 +350,13 @@ static int td028ttec1_probe(struct spi_device *spi)
return 0;
}
-static int td028ttec1_remove(struct spi_device *spi)
+static void td028ttec1_remove(struct spi_device *spi)
{
struct td028ttec1_panel *lcd = spi_get_drvdata(spi);
drm_panel_remove(&lcd->panel);
drm_panel_disable(&lcd->panel);
drm_panel_unprepare(&lcd->panel);
-
- return 0;
}
static const struct of_device_id td028ttec1_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
index 1866cdb8f9c1..cf4609bb9b1d 100644
--- a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
+++ b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
@@ -463,7 +463,7 @@ static int td043mtea1_probe(struct spi_device *spi)
return 0;
}
-static int td043mtea1_remove(struct spi_device *spi)
+static void td043mtea1_remove(struct spi_device *spi)
{
struct td043mtea1_panel *lcd = spi_get_drvdata(spi);
@@ -472,8 +472,6 @@ static int td043mtea1_remove(struct spi_device *spi)
drm_panel_unprepare(&lcd->panel);
sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group);
-
- return 0;
}
static const struct of_device_id td043mtea1_of_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
index e3791dad6830..0b1f5a11a055 100644
--- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c
+++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
@@ -450,12 +450,11 @@ static int tpg110_probe(struct spi_device *spi)
return 0;
}
-static int tpg110_remove(struct spi_device *spi)
+static void tpg110_remove(struct spi_device *spi)
{
struct tpg110 *tpg = spi_get_drvdata(spi);
drm_panel_remove(&tpg->panel);
- return 0;
}
static const struct of_device_id tpg110_match[] = {
diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
index 8bc976f54b80..236f3cb2b594 100644
--- a/drivers/gpu/drm/panel/panel-widechips-ws2401.c
+++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
@@ -407,12 +407,11 @@ static int ws2401_probe(struct spi_device *spi)
return 0;
}
-static int ws2401_remove(struct spi_device *spi)
+static void ws2401_remove(struct spi_device *spi)
{
struct ws2401 *ws = spi_get_drvdata(spi);
drm_panel_remove(&ws->panel);
- return 0;
}
/*
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 4740cc14beb8..d3e6c93739bf 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -586,6 +586,13 @@ static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
return drm_dp_channel_eq_ok(link_status, min(port->lanes, sink_lanes));
}
+static void cdn_dp_audio_handle_plugged_change(struct cdn_dp_device *dp,
+ bool plugged)
+{
+ if (dp->codec_dev)
+ dp->plugged_cb(dp->codec_dev, plugged);
+}
+
static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
{
struct cdn_dp_device *dp = encoder_to_dp(encoder);
@@ -641,6 +648,9 @@ static void cdn_dp_encoder_enable(struct drm_encoder *encoder)
DRM_DEV_ERROR(dp->dev, "Failed to valid video %d\n", ret);
goto out;
}
+
+ cdn_dp_audio_handle_plugged_change(dp, true);
+
out:
mutex_unlock(&dp->lock);
}
@@ -651,6 +661,8 @@ static void cdn_dp_encoder_disable(struct drm_encoder *encoder)
int ret;
mutex_lock(&dp->lock);
+ cdn_dp_audio_handle_plugged_change(dp, false);
+
if (dp->active) {
ret = cdn_dp_disable(dp);
if (ret) {
@@ -846,11 +858,27 @@ static int cdn_dp_audio_get_eld(struct device *dev, void *data,
return 0;
}
+static int cdn_dp_audio_hook_plugged_cb(struct device *dev, void *data,
+ hdmi_codec_plugged_cb fn,
+ struct device *codec_dev)
+{
+ struct cdn_dp_device *dp = dev_get_drvdata(dev);
+
+ mutex_lock(&dp->lock);
+ dp->plugged_cb = fn;
+ dp->codec_dev = codec_dev;
+ cdn_dp_audio_handle_plugged_change(dp, dp->connected);
+ mutex_unlock(&dp->lock);
+
+ return 0;
+}
+
static const struct hdmi_codec_ops audio_codec_ops = {
.hw_params = cdn_dp_audio_hw_params,
.audio_shutdown = cdn_dp_audio_shutdown,
.mute_stream = cdn_dp_audio_mute_stream,
.get_eld = cdn_dp_audio_get_eld,
+ .hook_plugged_cb = cdn_dp_audio_hook_plugged_cb,
.no_capture_mute = 1,
};
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h
index 0d044146f4e9..6d0c5032ef3a 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.h
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h
@@ -10,6 +10,7 @@
#include <drm/dp/drm_dp_helper.h>
#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
+#include <sound/hdmi-codec.h>
#include "rockchip_drm_drv.h"
@@ -101,5 +102,8 @@ struct cdn_dp_device {
u8 dpcd[DP_RECEIVER_CAP_SIZE];
bool sink_has_audio;
+
+ hdmi_codec_plugged_cb plugged_cb;
+ struct device *codec_dev;
};
#endif /* _CDN_DP_CORE_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index ac190e2b1f7a..4eaeb430c83a 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -290,11 +290,6 @@ int rockchip_drm_endpoint_is_subdriver(struct device_node *ep)
return false;
}
-static int compare_dev(struct device *dev, void *data)
-{
- return dev == (struct device *)data;
-}
-
static void rockchip_drm_match_remove(struct device *dev)
{
struct device_link *link;
@@ -321,7 +316,7 @@ static struct component_match *rockchip_drm_match_add(struct device *dev)
break;
device_link_add(dev, d, DL_FLAG_STATELESS);
- component_match_add(dev, &match, compare_dev, d);
+ component_match_add(dev, &match, component_compare_dev, d);
} while (true);
}
diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c b/drivers/gpu/drm/selftests/test-drm_plane_helper.c
index ceebeede55ea..b61273e9c403 100644
--- a/drivers/gpu/drm/selftests/test-drm_plane_helper.c
+++ b/drivers/gpu/drm/selftests/test-drm_plane_helper.c
@@ -77,7 +77,7 @@ int igt_check_plane_state(void *ignored)
{
int ret;
- const struct drm_crtc_state crtc_state = {
+ static const struct drm_crtc_state crtc_state = {
.crtc = ZERO_SIZE_PTR,
.enable = true,
.active = true,
@@ -87,14 +87,14 @@ int igt_check_plane_state(void *ignored)
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
},
};
- struct drm_plane plane = {
+ static struct drm_plane plane = {
.dev = NULL
};
- struct drm_framebuffer fb = {
+ static struct drm_framebuffer fb = {
.width = 2048,
.height = 2048
};
- struct drm_plane_state plane_state = {
+ static struct drm_plane_state plane_state = {
.plane = &plane,
.crtc = ZERO_SIZE_PTR,
.fb = &fb,
diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c
index a60ecdd67d98..b8fc1c6a0cb8 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.c
+++ b/drivers/gpu/drm/sprd/sprd_drm.c
@@ -133,14 +133,9 @@ static const struct component_master_ops drm_component_ops = {
.unbind = sprd_drm_unbind,
};
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static int sprd_drm_probe(struct platform_device *pdev)
{
- return drm_of_component_probe(&pdev->dev, compare_of, &drm_component_ops);
+ return drm_of_component_probe(&pdev->dev, component_compare_of, &drm_component_ops);
}
static int sprd_drm_remove(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 860b2230aa08..d858209cf8de 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -144,11 +144,6 @@ static const struct drm_driver sti_driver = {
.minor = DRIVER_MINOR,
};
-static int compare_of(struct device *dev, void *data)
-{
- return dev->of_node == data;
-}
-
static int sti_init(struct drm_device *ddev)
{
struct sti_private *private;
@@ -244,7 +239,7 @@ static int sti_platform_probe(struct platform_device *pdev)
child_np = of_get_next_available_child(node, NULL);
while (child_np) {
- drm_of_component_match_add(dev, &match, compare_of,
+ drm_of_component_match_add(dev, &match, component_compare_of,
child_np);
child_np = of_get_next_available_child(node, child_np);
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a3fd441dd9ad..6a9ba8a77c77 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -202,15 +202,6 @@ static bool sun4i_drv_node_is_tcon_top(struct device_node *node)
!!of_match_node(sun8i_tcon_top_of_table, node);
}
-static int compare_of(struct device *dev, void *data)
-{
- DRM_DEBUG_DRIVER("Comparing of node %pOF with %pOF\n",
- dev->of_node,
- data);
-
- return dev->of_node == data;
-}
-
/*
* The encoder drivers use drm_of_find_possible_crtcs to get upstream
* crtcs from the device tree using of_graph. For the results to be
@@ -330,7 +321,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
of_device_is_available(node))) {
/* Add current component */
DRM_DEBUG_DRIVER("Adding component %pOF\n", node);
- drm_of_component_match_add(dev, match, compare_of, node);
+ drm_of_component_match_add(dev, match, component_compare_of, node);
count++;
}
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.h b/drivers/gpu/drm/sun4i/sun8i_mixer.h
index 145833a9d82d..5b3fbee18671 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -111,10 +111,10 @@
/* format 13 is semi-planar YUV411 VUVU */
#define SUN8I_MIXER_FBFMT_YUV411 14
/* format 15 doesn't exist */
-/* format 16 is P010 YVU */
-#define SUN8I_MIXER_FBFMT_P010_YUV 17
-/* format 18 is P210 YVU */
-#define SUN8I_MIXER_FBFMT_P210_YUV 19
+#define SUN8I_MIXER_FBFMT_P010_YUV 16
+/* format 17 is P010 YVU */
+#define SUN8I_MIXER_FBFMT_P210_YUV 18
+/* format 19 is P210 YVU */
/* format 20 is packed YVU444 10-bit */
/* format 21 is packed YUV444 10-bit */
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index 9b33c05732aa..ebb025543f8d 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -263,14 +263,12 @@ static int hx8357d_probe(struct spi_device *spi)
return 0;
}
-static int hx8357d_remove(struct spi_device *spi)
+static void hx8357d_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void hx8357d_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index bcc181351236..fc8ed245b0bc 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -193,14 +193,12 @@ static int ili9163_probe(struct spi_device *spi)
return 0;
}
-static int ili9163_remove(struct spi_device *spi)
+static void ili9163_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void ili9163_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index 976d3209f164..cc92eb9f2a07 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -411,14 +411,12 @@ static int ili9225_probe(struct spi_device *spi)
return 0;
}
-static int ili9225_remove(struct spi_device *spi)
+static void ili9225_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void ili9225_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 37e0c33399c8..5b8cc770ee7b 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -225,14 +225,12 @@ static int ili9341_probe(struct spi_device *spi)
return 0;
}
-static int ili9341_remove(struct spi_device *spi)
+static void ili9341_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void ili9341_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index e9a63f4b2993..6d655e18e0aa 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -243,14 +243,12 @@ static int ili9486_probe(struct spi_device *spi)
return 0;
}
-static int ili9486_remove(struct spi_device *spi)
+static void ili9486_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void ili9486_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index 023de49e7a8e..5e060f6910bb 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -233,14 +233,12 @@ static int mi0283qt_probe(struct spi_device *spi)
return 0;
}
-static int mi0283qt_remove(struct spi_device *spi)
+static void mi0283qt_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void mi0283qt_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 7f8c6c51387f..c759ff9c2c87 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -336,14 +336,12 @@ static int panel_mipi_dbi_spi_probe(struct spi_device *spi)
return 0;
}
-static int panel_mipi_dbi_spi_remove(struct spi_device *spi)
+static void panel_mipi_dbi_spi_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void panel_mipi_dbi_spi_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index 5c74e236b16d..37b6bb90e46e 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -1118,14 +1118,12 @@ static int repaper_probe(struct spi_device *spi)
return 0;
}
-static int repaper_remove(struct spi_device *spi)
+static void repaper_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void repaper_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index 51b9b9fb3ead..3f38faa1cd8c 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -360,14 +360,12 @@ static int st7586_probe(struct spi_device *spi)
return 0;
}
-static int st7586_remove(struct spi_device *spi)
+static void st7586_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void st7586_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
index fc40dd10efa8..29d618093e94 100644
--- a/drivers/gpu/drm/tiny/st7735r.c
+++ b/drivers/gpu/drm/tiny/st7735r.c
@@ -247,14 +247,12 @@ static int st7735r_probe(struct spi_device *spi)
return 0;
}
-static int st7735r_remove(struct spi_device *spi)
+static void st7735r_remove(struct spi_device *spi)
{
struct drm_device *drm = spi_get_drvdata(spi);
drm_dev_unplug(drm);
drm_atomic_helper_shutdown(drm);
-
- return 0;
}
static void st7735r_shutdown(struct spi_device *spi)
diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c
index 8cd4f3fb9f79..d91666721dc6 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -89,7 +89,7 @@ static int ttm_range_man_alloc(struct ttm_resource_manager *man,
spin_unlock(&rman->lock);
if (unlikely(ret)) {
- ttm_resource_fini(man, *res);
+ ttm_resource_fini(man, &node->base);
kfree(node);
return ret;
}
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index a03053c8e22c..162bc18e7497 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -189,11 +189,6 @@ static struct drm_driver vc4_drm_driver = {
.patchlevel = DRIVER_PATCHLEVEL,
};
-static int compare_dev(struct device *dev, void *data)
-{
- return dev == data;
-}
-
static void vc4_match_add_drivers(struct device *dev,
struct component_match **match,
struct platform_driver *const *drivers,
@@ -207,7 +202,7 @@ static void vc4_match_add_drivers(struct device *dev,
while ((d = platform_find_device_by_driver(p, drv))) {
put_device(p);
- component_match_add(dev, match, compare_dev, d);
+ component_match_add(dev, match, component_compare_dev, d);
p = d;
}
put_device(p);
diff --git a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c
index e10d95dddb99..08b526eeec16 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c
@@ -148,7 +148,7 @@ static void evtchnl_free(struct xen_drm_front_info *front_info,
/* end access and free the page */
if (evtchnl->gref != GRANT_INVALID_REF)
- gnttab_end_foreign_access(evtchnl->gref, 0, page);
+ gnttab_end_foreign_access(evtchnl->gref, page);
memset(evtchnl, 0, sizeof(*evtchnl));
}
diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c
index a9639d098893..778bc26d3ba5 100644
--- a/drivers/gpu/ipu-v3/ipu-csi.c
+++ b/drivers/gpu/ipu-v3/ipu-csi.c
@@ -357,11 +357,11 @@ static int fill_csi_bus_cfg(struct ipu_csi_bus_config *csicfg,
switch (mbus_cfg->type) {
case V4L2_MBUS_PARALLEL:
csicfg->ext_vsync = 1;
- csicfg->vsync_pol = (mbus_cfg->flags &
+ csicfg->vsync_pol = (mbus_cfg->bus.parallel.flags &
V4L2_MBUS_VSYNC_ACTIVE_LOW) ? 1 : 0;
- csicfg->hsync_pol = (mbus_cfg->flags &
+ csicfg->hsync_pol = (mbus_cfg->bus.parallel.flags &
V4L2_MBUS_HSYNC_ACTIVE_LOW) ? 1 : 0;
- csicfg->pixclk_pol = (mbus_cfg->flags &
+ csicfg->pixclk_pol = (mbus_cfg->bus.parallel.flags &
V4L2_MBUS_PCLK_SAMPLE_FALLING) ? 1 : 0;
csicfg->clk_mode = IPU_CSI_CLK_MODE_GATED_CLK;
break;
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index 1ad4c4ef0b5e..eb8b14ab22c3 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -1,23 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-config VGA_ARB
- bool "VGA Arbitration" if EXPERT
- default y
- depends on (PCI && !S390)
- help
- Some "legacy" VGA devices implemented on PCI typically have the same
- hard-decoded addresses as they did on ISA. When multiple PCI devices
- are accessed at same time they need some kind of coordination. Please
- see Documentation/gpu/vgaarbiter.rst for more details. Select this to
- enable VGA arbiter.
-
-config VGA_ARB_MAX_GPUS
- int "Maximum number of GPUs"
- default 16
- depends on VGA_ARB
- help
- Reserves space in the kernel to maintain resource locking for
- multiple GPUS. The overhead for each GPU is very small.
-
config VGA_SWITCHEROO
bool "Laptop Hybrid Graphics - GPU switching support"
depends on X86
diff --git a/drivers/gpu/vga/Makefile b/drivers/gpu/vga/Makefile
index e92064442d60..9800620deda3 100644
--- a/drivers/gpu/vga/Makefile
+++ b/drivers/gpu/vga/Makefile
@@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VGA_ARB) += vgaarb.o
obj-$(CONFIG_VGA_SWITCHEROO) += vga_switcheroo.o
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
deleted file mode 100644
index 569930552957..000000000000
--- a/drivers/gpu/vga/vgaarb.c
+++ /dev/null
@@ -1,1567 +0,0 @@
-/*
- * vgaarb.c: Implements the VGA arbitration. For details refer to
- * Documentation/gpu/vgaarbiter.rst
- *
- *
- * (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
- * (C) Copyright 2007 Paulo R. Zanoni <przanoni@gmail.com>
- * (C) Copyright 2007, 2009 Tiago Vignatti <vignatti@freedesktop.org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS
- * IN THE SOFTWARE.
- *
- */
-
-#define pr_fmt(fmt) "vgaarb: " fmt
-
-#define vgaarb_dbg(dev, fmt, arg...) dev_dbg(dev, "vgaarb: " fmt, ##arg)
-#define vgaarb_info(dev, fmt, arg...) dev_info(dev, "vgaarb: " fmt, ##arg)
-#define vgaarb_err(dev, fmt, arg...) dev_err(dev, "vgaarb: " fmt, ##arg)
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/sched/signal.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/poll.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/screen_info.h>
-#include <linux/vt.h>
-#include <linux/console.h>
-#include <linux/acpi.h>
-
-#include <linux/uaccess.h>
-
-#include <linux/vgaarb.h>
-
-static void vga_arbiter_notify_clients(void);
-/*
- * We keep a list of all vga devices in the system to speed
- * up the various operations of the arbiter
- */
-struct vga_device {
- struct list_head list;
- struct pci_dev *pdev;
- unsigned int decodes; /* what does it decodes */
- unsigned int owns; /* what does it owns */
- unsigned int locks; /* what does it locks */
- unsigned int io_lock_cnt; /* legacy IO lock count */
- unsigned int mem_lock_cnt; /* legacy MEM lock count */
- unsigned int io_norm_cnt; /* normal IO count */
- unsigned int mem_norm_cnt; /* normal MEM count */
- bool bridge_has_one_vga;
- unsigned int (*set_decode)(struct pci_dev *pdev, bool decode);
-};
-
-static LIST_HEAD(vga_list);
-static int vga_count, vga_decode_count;
-static bool vga_arbiter_used;
-static DEFINE_SPINLOCK(vga_lock);
-static DECLARE_WAIT_QUEUE_HEAD(vga_wait_queue);
-
-
-static const char *vga_iostate_to_str(unsigned int iostate)
-{
- /* Ignore VGA_RSRC_IO and VGA_RSRC_MEM */
- iostate &= VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
- switch (iostate) {
- case VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM:
- return "io+mem";
- case VGA_RSRC_LEGACY_IO:
- return "io";
- case VGA_RSRC_LEGACY_MEM:
- return "mem";
- }
- return "none";
-}
-
-static int vga_str_to_iostate(char *buf, int str_size, int *io_state)
-{
- /* we could in theory hand out locks on IO and mem
- * separately to userspace but it can cause deadlocks */
- if (strncmp(buf, "none", 4) == 0) {
- *io_state = VGA_RSRC_NONE;
- return 1;
- }
-
- /* XXX We're not chekcing the str_size! */
- if (strncmp(buf, "io+mem", 6) == 0)
- goto both;
- else if (strncmp(buf, "io", 2) == 0)
- goto both;
- else if (strncmp(buf, "mem", 3) == 0)
- goto both;
- return 0;
-both:
- *io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
- return 1;
-}
-
-/* this is only used a cookie - it should not be dereferenced */
-static struct pci_dev *vga_default;
-
-static void vga_arb_device_card_gone(struct pci_dev *pdev);
-
-/* Find somebody in our list */
-static struct vga_device *vgadev_find(struct pci_dev *pdev)
-{
- struct vga_device *vgadev;
-
- list_for_each_entry(vgadev, &vga_list, list)
- if (pdev == vgadev->pdev)
- return vgadev;
- return NULL;
-}
-
-/**
- * vga_default_device - return the default VGA device, for vgacon
- *
- * This can be defined by the platform. The default implementation
- * is rather dumb and will probably only work properly on single
- * vga card setups and/or x86 platforms.
- *
- * If your VGA default device is not PCI, you'll have to return
- * NULL here. In this case, I assume it will not conflict with
- * any PCI card. If this is not true, I'll have to define two archs
- * hooks for enabling/disabling the VGA default device if that is
- * possible. This may be a problem with real _ISA_ VGA cards, in
- * addition to a PCI one. I don't know at this point how to deal
- * with that card. Can theirs IOs be disabled at all ? If not, then
- * I suppose it's a matter of having the proper arch hook telling
- * us about it, so we basically never allow anybody to succeed a
- * vga_get()...
- */
-struct pci_dev *vga_default_device(void)
-{
- return vga_default;
-}
-EXPORT_SYMBOL_GPL(vga_default_device);
-
-void vga_set_default_device(struct pci_dev *pdev)
-{
- if (vga_default == pdev)
- return;
-
- pci_dev_put(vga_default);
- vga_default = pci_dev_get(pdev);
-}
-
-/**
- * vga_remove_vgacon - deactivete vga console
- *
- * Unbind and unregister vgacon in case pdev is the default vga
- * device. Can be called by gpu drivers on initialization to make
- * sure vga register access done by vgacon will not disturb the
- * device.
- *
- * @pdev: pci device.
- */
-#if !defined(CONFIG_VGA_CONSOLE)
-int vga_remove_vgacon(struct pci_dev *pdev)
-{
- return 0;
-}
-#elif !defined(CONFIG_DUMMY_CONSOLE)
-int vga_remove_vgacon(struct pci_dev *pdev)
-{
- return -ENODEV;
-}
-#else
-int vga_remove_vgacon(struct pci_dev *pdev)
-{
- int ret = 0;
-
- if (pdev != vga_default)
- return 0;
- vgaarb_info(&pdev->dev, "deactivate vga console\n");
-
- console_lock();
- if (con_is_bound(&vga_con))
- ret = do_take_over_console(&dummy_con, 0,
- MAX_NR_CONSOLES - 1, 1);
- if (ret == 0) {
- ret = do_unregister_con_driver(&vga_con);
-
- /* Ignore "already unregistered". */
- if (ret == -ENODEV)
- ret = 0;
- }
- console_unlock();
-
- return ret;
-}
-#endif
-EXPORT_SYMBOL(vga_remove_vgacon);
-
-/* If we don't ever use VGA arb we should avoid
- turning off anything anywhere due to old X servers getting
- confused about the boot device not being VGA */
-static void vga_check_first_use(void)
-{
- /* we should inform all GPUs in the system that
- * VGA arb has occurred and to try and disable resources
- * if they can */
- if (!vga_arbiter_used) {
- vga_arbiter_used = true;
- vga_arbiter_notify_clients();
- }
-}
-
-static struct vga_device *__vga_tryget(struct vga_device *vgadev,
- unsigned int rsrc)
-{
- struct device *dev = &vgadev->pdev->dev;
- unsigned int wants, legacy_wants, match;
- struct vga_device *conflict;
- unsigned int pci_bits;
- u32 flags = 0;
-
- /* Account for "normal" resources to lock. If we decode the legacy,
- * counterpart, we need to request it as well
- */
- if ((rsrc & VGA_RSRC_NORMAL_IO) &&
- (vgadev->decodes & VGA_RSRC_LEGACY_IO))
- rsrc |= VGA_RSRC_LEGACY_IO;
- if ((rsrc & VGA_RSRC_NORMAL_MEM) &&
- (vgadev->decodes & VGA_RSRC_LEGACY_MEM))
- rsrc |= VGA_RSRC_LEGACY_MEM;
-
- vgaarb_dbg(dev, "%s: %d\n", __func__, rsrc);
- vgaarb_dbg(dev, "%s: owns: %d\n", __func__, vgadev->owns);
-
- /* Check what resources we need to acquire */
- wants = rsrc & ~vgadev->owns;
-
- /* We already own everything, just mark locked & bye bye */
- if (wants == 0)
- goto lock_them;
-
- /* We don't need to request a legacy resource, we just enable
- * appropriate decoding and go
- */
- legacy_wants = wants & VGA_RSRC_LEGACY_MASK;
- if (legacy_wants == 0)
- goto enable_them;
-
- /* Ok, we don't, let's find out how we need to kick off */
- list_for_each_entry(conflict, &vga_list, list) {
- unsigned int lwants = legacy_wants;
- unsigned int change_bridge = 0;
-
- /* Don't conflict with myself */
- if (vgadev == conflict)
- continue;
-
- /* We have a possible conflict. before we go further, we must
- * check if we sit on the same bus as the conflicting device.
- * if we don't, then we must tie both IO and MEM resources
- * together since there is only a single bit controlling
- * VGA forwarding on P2P bridges
- */
- if (vgadev->pdev->bus != conflict->pdev->bus) {
- change_bridge = 1;
- lwants = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
- }
-
- /* Check if the guy has a lock on the resource. If he does,
- * return the conflicting entry
- */
- if (conflict->locks & lwants)
- return conflict;
-
- /* Ok, now check if it owns the resource we want. We can
- * lock resources that are not decoded, therefore a device
- * can own resources it doesn't decode.
- */
- match = lwants & conflict->owns;
- if (!match)
- continue;
-
- /* looks like he doesn't have a lock, we can steal
- * them from him
- */
-
- flags = 0;
- pci_bits = 0;
-
- /* If we can't control legacy resources via the bridge, we
- * also need to disable normal decoding.
- */
- if (!conflict->bridge_has_one_vga) {
- if ((match & conflict->decodes) & VGA_RSRC_LEGACY_MEM)
- pci_bits |= PCI_COMMAND_MEMORY;
- if ((match & conflict->decodes) & VGA_RSRC_LEGACY_IO)
- pci_bits |= PCI_COMMAND_IO;
-
- if (pci_bits)
- flags |= PCI_VGA_STATE_CHANGE_DECODES;
- }
-
- if (change_bridge)
- flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
-
- pci_set_vga_state(conflict->pdev, false, pci_bits, flags);
- conflict->owns &= ~match;
-
- /* If we disabled normal decoding, reflect it in owns */
- if (pci_bits & PCI_COMMAND_MEMORY)
- conflict->owns &= ~VGA_RSRC_NORMAL_MEM;
- if (pci_bits & PCI_COMMAND_IO)
- conflict->owns &= ~VGA_RSRC_NORMAL_IO;
- }
-
-enable_them:
- /* ok dude, we got it, everybody conflicting has been disabled, let's
- * enable us. Mark any bits in "owns" regardless of whether we
- * decoded them. We can lock resources we don't decode, therefore
- * we must track them via "owns".
- */
- flags = 0;
- pci_bits = 0;
-
- if (!vgadev->bridge_has_one_vga) {
- flags |= PCI_VGA_STATE_CHANGE_DECODES;
- if (wants & (VGA_RSRC_LEGACY_MEM|VGA_RSRC_NORMAL_MEM))
- pci_bits |= PCI_COMMAND_MEMORY;
- if (wants & (VGA_RSRC_LEGACY_IO|VGA_RSRC_NORMAL_IO))
- pci_bits |= PCI_COMMAND_IO;
- }
- if (wants & VGA_RSRC_LEGACY_MASK)
- flags |= PCI_VGA_STATE_CHANGE_BRIDGE;
-
- pci_set_vga_state(vgadev->pdev, true, pci_bits, flags);
-
- vgadev->owns |= wants;
-lock_them:
- vgadev->locks |= (rsrc & VGA_RSRC_LEGACY_MASK);
- if (rsrc & VGA_RSRC_LEGACY_IO)
- vgadev->io_lock_cnt++;
- if (rsrc & VGA_RSRC_LEGACY_MEM)
- vgadev->mem_lock_cnt++;
- if (rsrc & VGA_RSRC_NORMAL_IO)
- vgadev->io_norm_cnt++;
- if (rsrc & VGA_RSRC_NORMAL_MEM)
- vgadev->mem_norm_cnt++;
-
- return NULL;
-}
-
-static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
-{
- struct device *dev = &vgadev->pdev->dev;
- unsigned int old_locks = vgadev->locks;
-
- vgaarb_dbg(dev, "%s\n", __func__);
-
- /* Update our counters, and account for equivalent legacy resources
- * if we decode them
- */
- if ((rsrc & VGA_RSRC_NORMAL_IO) && vgadev->io_norm_cnt > 0) {
- vgadev->io_norm_cnt--;
- if (vgadev->decodes & VGA_RSRC_LEGACY_IO)
- rsrc |= VGA_RSRC_LEGACY_IO;
- }
- if ((rsrc & VGA_RSRC_NORMAL_MEM) && vgadev->mem_norm_cnt > 0) {
- vgadev->mem_norm_cnt--;
- if (vgadev->decodes & VGA_RSRC_LEGACY_MEM)
- rsrc |= VGA_RSRC_LEGACY_MEM;
- }
- if ((rsrc & VGA_RSRC_LEGACY_IO) && vgadev->io_lock_cnt > 0)
- vgadev->io_lock_cnt--;
- if ((rsrc & VGA_RSRC_LEGACY_MEM) && vgadev->mem_lock_cnt > 0)
- vgadev->mem_lock_cnt--;
-
- /* Just clear lock bits, we do lazy operations so we don't really
- * have to bother about anything else at this point
- */
- if (vgadev->io_lock_cnt == 0)
- vgadev->locks &= ~VGA_RSRC_LEGACY_IO;
- if (vgadev->mem_lock_cnt == 0)
- vgadev->locks &= ~VGA_RSRC_LEGACY_MEM;
-
- /* Kick the wait queue in case somebody was waiting if we actually
- * released something
- */
- if (old_locks != vgadev->locks)
- wake_up_all(&vga_wait_queue);
-}
-
-/**
- * vga_get - acquire & locks VGA resources
- * @pdev: pci device of the VGA card or NULL for the system default
- * @rsrc: bit mask of resources to acquire and lock
- * @interruptible: blocking should be interruptible by signals ?
- *
- * This function acquires VGA resources for the given card and mark those
- * resources locked. If the resource requested are "normal" (and not legacy)
- * resources, the arbiter will first check whether the card is doing legacy
- * decoding for that type of resource. If yes, the lock is "converted" into a
- * legacy resource lock.
- *
- * The arbiter will first look for all VGA cards that might conflict and disable
- * their IOs and/or Memory access, including VGA forwarding on P2P bridges if
- * necessary, so that the requested resources can be used. Then, the card is
- * marked as locking these resources and the IO and/or Memory accesses are
- * enabled on the card (including VGA forwarding on parent P2P bridges if any).
- *
- * This function will block if some conflicting card is already locking one of
- * the required resources (or any resource on a different bus segment, since P2P
- * bridges don't differentiate VGA memory and IO afaik). You can indicate
- * whether this blocking should be interruptible by a signal (for userland
- * interface) or not.
- *
- * Must not be called at interrupt time or in atomic context. If the card
- * already owns the resources, the function succeeds. Nested calls are
- * supported (a per-resource counter is maintained)
- *
- * On success, release the VGA resource again with vga_put().
- *
- * Returns:
- *
- * 0 on success, negative error code on failure.
- */
-int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
-{
- struct vga_device *vgadev, *conflict;
- unsigned long flags;
- wait_queue_entry_t wait;
- int rc = 0;
-
- vga_check_first_use();
- /* The one who calls us should check for this, but lets be sure... */
- if (pdev == NULL)
- pdev = vga_default_device();
- if (pdev == NULL)
- return 0;
-
- for (;;) {
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL) {
- spin_unlock_irqrestore(&vga_lock, flags);
- rc = -ENODEV;
- break;
- }
- conflict = __vga_tryget(vgadev, rsrc);
- spin_unlock_irqrestore(&vga_lock, flags);
- if (conflict == NULL)
- break;
-
-
- /* We have a conflict, we wait until somebody kicks the
- * work queue. Currently we have one work queue that we
- * kick each time some resources are released, but it would
- * be fairly easy to have a per device one so that we only
- * need to attach to the conflicting device
- */
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&vga_wait_queue, &wait);
- set_current_state(interruptible ?
- TASK_INTERRUPTIBLE :
- TASK_UNINTERRUPTIBLE);
- if (interruptible && signal_pending(current)) {
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&vga_wait_queue, &wait);
- rc = -ERESTARTSYS;
- break;
- }
- schedule();
- remove_wait_queue(&vga_wait_queue, &wait);
- }
- return rc;
-}
-EXPORT_SYMBOL(vga_get);
-
-/**
- * vga_tryget - try to acquire & lock legacy VGA resources
- * @pdev: pci devivce of VGA card or NULL for system default
- * @rsrc: bit mask of resources to acquire and lock
- *
- * This function performs the same operation as vga_get(), but will return an
- * error (-EBUSY) instead of blocking if the resources are already locked by
- * another card. It can be called in any context
- *
- * On success, release the VGA resource again with vga_put().
- *
- * Returns:
- *
- * 0 on success, negative error code on failure.
- */
-static int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
-{
- struct vga_device *vgadev;
- unsigned long flags;
- int rc = 0;
-
- vga_check_first_use();
-
- /* The one who calls us should check for this, but lets be sure... */
- if (pdev == NULL)
- pdev = vga_default_device();
- if (pdev == NULL)
- return 0;
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL) {
- rc = -ENODEV;
- goto bail;
- }
- if (__vga_tryget(vgadev, rsrc))
- rc = -EBUSY;
-bail:
- spin_unlock_irqrestore(&vga_lock, flags);
- return rc;
-}
-
-/**
- * vga_put - release lock on legacy VGA resources
- * @pdev: pci device of VGA card or NULL for system default
- * @rsrc: but mask of resource to release
- *
- * This fuction releases resources previously locked by vga_get() or
- * vga_tryget(). The resources aren't disabled right away, so that a subsequence
- * vga_get() on the same card will succeed immediately. Resources have a
- * counter, so locks are only released if the counter reaches 0.
- */
-void vga_put(struct pci_dev *pdev, unsigned int rsrc)
-{
- struct vga_device *vgadev;
- unsigned long flags;
-
- /* The one who calls us should check for this, but lets be sure... */
- if (pdev == NULL)
- pdev = vga_default_device();
- if (pdev == NULL)
- return;
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL)
- goto bail;
- __vga_put(vgadev, rsrc);
-bail:
- spin_unlock_irqrestore(&vga_lock, flags);
-}
-EXPORT_SYMBOL(vga_put);
-
-/*
- * Rules for using a bridge to control a VGA descendant decoding: if a bridge
- * has only one VGA descendant then it can be used to control the VGA routing
- * for that device. It should always use the bridge closest to the device to
- * control it. If a bridge has a direct VGA descendant, but also have a sub-
- * bridge VGA descendant then we cannot use that bridge to control the direct
- * VGA descendant. So for every device we register, we need to iterate all
- * its parent bridges so we can invalidate any devices using them properly.
- */
-static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
-{
- struct vga_device *same_bridge_vgadev;
- struct pci_bus *new_bus, *bus;
- struct pci_dev *new_bridge, *bridge;
-
- vgadev->bridge_has_one_vga = true;
-
- if (list_empty(&vga_list))
- return;
-
- /* okay iterate the new devices bridge hierarachy */
- new_bus = vgadev->pdev->bus;
- while (new_bus) {
- new_bridge = new_bus->self;
-
- /* go through list of devices already registered */
- list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
- bus = same_bridge_vgadev->pdev->bus;
- bridge = bus->self;
-
- /* see if the share a bridge with this device */
- if (new_bridge == bridge) {
- /*
- * If their direct parent bridge is the same
- * as any bridge of this device then it can't
- * be used for that device.
- */
- same_bridge_vgadev->bridge_has_one_vga = false;
- }
-
- /*
- * Now iterate the previous devices bridge hierarchy.
- * If the new devices parent bridge is in the other
- * devices hierarchy then we can't use it to control
- * this device
- */
- while (bus) {
- bridge = bus->self;
-
- if (bridge && bridge == vgadev->pdev->bus->self)
- vgadev->bridge_has_one_vga = false;
-
- bus = bus->parent;
- }
- }
- new_bus = new_bus->parent;
- }
-}
-
-/*
- * Currently, we assume that the "initial" setup of the system is
- * not sane, that is we come up with conflicting devices and let
- * the arbiter's client decides if devices decodes or not legacy
- * things.
- */
-static bool vga_arbiter_add_pci_device(struct pci_dev *pdev)
-{
- struct vga_device *vgadev;
- unsigned long flags;
- struct pci_bus *bus;
- struct pci_dev *bridge;
- u16 cmd;
-
- /* Only deal with VGA class devices */
- if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
- return false;
-
- /* Allocate structure */
- vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
- if (vgadev == NULL) {
- vgaarb_err(&pdev->dev, "failed to allocate VGA arbiter data\n");
- /*
- * What to do on allocation failure ? For now, let's just do
- * nothing, I'm not sure there is anything saner to be done.
- */
- return false;
- }
-
- /* Take lock & check for duplicates */
- spin_lock_irqsave(&vga_lock, flags);
- if (vgadev_find(pdev) != NULL) {
- BUG_ON(1);
- goto fail;
- }
- vgadev->pdev = pdev;
-
- /* By default, assume we decode everything */
- vgadev->decodes = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
- VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
-
- /* by default mark it as decoding */
- vga_decode_count++;
- /* Mark that we "own" resources based on our enables, we will
- * clear that below if the bridge isn't forwarding
- */
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- if (cmd & PCI_COMMAND_IO)
- vgadev->owns |= VGA_RSRC_LEGACY_IO;
- if (cmd & PCI_COMMAND_MEMORY)
- vgadev->owns |= VGA_RSRC_LEGACY_MEM;
-
- /* Check if VGA cycles can get down to us */
- bus = pdev->bus;
- while (bus) {
- bridge = bus->self;
- if (bridge) {
- u16 l;
-
- pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
- if (!(l & PCI_BRIDGE_CTL_VGA)) {
- vgadev->owns = 0;
- break;
- }
- }
- bus = bus->parent;
- }
-
- /* Deal with VGA default device. Use first enabled one
- * by default if arch doesn't have it's own hook
- */
- if (vga_default == NULL &&
- ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
- vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
- vga_set_default_device(pdev);
- }
-
- vga_arbiter_check_bridge_sharing(vgadev);
-
- /* Add to the list */
- list_add_tail(&vgadev->list, &vga_list);
- vga_count++;
- vgaarb_info(&pdev->dev, "VGA device added: decodes=%s,owns=%s,locks=%s\n",
- vga_iostate_to_str(vgadev->decodes),
- vga_iostate_to_str(vgadev->owns),
- vga_iostate_to_str(vgadev->locks));
-
- spin_unlock_irqrestore(&vga_lock, flags);
- return true;
-fail:
- spin_unlock_irqrestore(&vga_lock, flags);
- kfree(vgadev);
- return false;
-}
-
-static bool vga_arbiter_del_pci_device(struct pci_dev *pdev)
-{
- struct vga_device *vgadev;
- unsigned long flags;
- bool ret = true;
-
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL) {
- ret = false;
- goto bail;
- }
-
- if (vga_default == pdev)
- vga_set_default_device(NULL);
-
- if (vgadev->decodes & (VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM))
- vga_decode_count--;
-
- /* Remove entry from list */
- list_del(&vgadev->list);
- vga_count--;
- /* Notify userland driver that the device is gone so it discards
- * it's copies of the pci_dev pointer
- */
- vga_arb_device_card_gone(pdev);
-
- /* Wake up all possible waiters */
- wake_up_all(&vga_wait_queue);
-bail:
- spin_unlock_irqrestore(&vga_lock, flags);
- kfree(vgadev);
- return ret;
-}
-
-/* this is called with the lock */
-static inline void vga_update_device_decodes(struct vga_device *vgadev,
- int new_decodes)
-{
- struct device *dev = &vgadev->pdev->dev;
- int old_decodes, decodes_removed, decodes_unlocked;
-
- old_decodes = vgadev->decodes;
- decodes_removed = ~new_decodes & old_decodes;
- decodes_unlocked = vgadev->locks & decodes_removed;
- vgadev->decodes = new_decodes;
-
- vgaarb_info(dev, "changed VGA decodes: olddecodes=%s,decodes=%s:owns=%s\n",
- vga_iostate_to_str(old_decodes),
- vga_iostate_to_str(vgadev->decodes),
- vga_iostate_to_str(vgadev->owns));
-
- /* if we removed locked decodes, lock count goes to zero, and release */
- if (decodes_unlocked) {
- if (decodes_unlocked & VGA_RSRC_LEGACY_IO)
- vgadev->io_lock_cnt = 0;
- if (decodes_unlocked & VGA_RSRC_LEGACY_MEM)
- vgadev->mem_lock_cnt = 0;
- __vga_put(vgadev, decodes_unlocked);
- }
-
- /* change decodes counter */
- if (old_decodes & VGA_RSRC_LEGACY_MASK &&
- !(new_decodes & VGA_RSRC_LEGACY_MASK))
- vga_decode_count--;
- if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
- new_decodes & VGA_RSRC_LEGACY_MASK)
- vga_decode_count++;
- vgaarb_dbg(dev, "decoding count now is: %d\n", vga_decode_count);
-}
-
-static void __vga_set_legacy_decoding(struct pci_dev *pdev,
- unsigned int decodes,
- bool userspace)
-{
- struct vga_device *vgadev;
- unsigned long flags;
-
- decodes &= VGA_RSRC_LEGACY_MASK;
-
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL)
- goto bail;
-
- /* don't let userspace futz with kernel driver decodes */
- if (userspace && vgadev->set_decode)
- goto bail;
-
- /* update the device decodes + counter */
- vga_update_device_decodes(vgadev, decodes);
-
- /* XXX if somebody is going from "doesn't decode" to "decodes" state
- * here, additional care must be taken as we may have pending owner
- * ship of non-legacy region ...
- */
-bail:
- spin_unlock_irqrestore(&vga_lock, flags);
-}
-
-/**
- * vga_set_legacy_decoding
- * @pdev: pci device of the VGA card
- * @decodes: bit mask of what legacy regions the card decodes
- *
- * Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
- * Memory, both, or none. All cards default to both, the card driver (fbdev for
- * example) should tell the arbiter if it has disabled legacy decoding, so the
- * card can be left out of the arbitration process (and can be safe to take
- * interrupts at any time.
- */
-void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes)
-{
- __vga_set_legacy_decoding(pdev, decodes, false);
-}
-EXPORT_SYMBOL(vga_set_legacy_decoding);
-
-/**
- * vga_client_register - register or unregister a VGA arbitration client
- * @pdev: pci device of the VGA client
- * @set_decode: vga decode change callback
- *
- * Clients have two callback mechanisms they can use.
- *
- * @set_decode callback: If a client can disable its GPU VGA resource, it
- * will get a callback from this to set the encode/decode state.
- *
- * Rationale: we cannot disable VGA decode resources unconditionally some single
- * GPU laptops seem to require ACPI or BIOS access to the VGA registers to
- * control things like backlights etc. Hopefully newer multi-GPU laptops do
- * something saner, and desktops won't have any special ACPI for this. The
- * driver will get a callback when VGA arbitration is first used by userspace
- * since some older X servers have issues.
- *
- * This function does not check whether a client for @pdev has been registered
- * already.
- *
- * To unregister just call vga_client_unregister().
- *
- * Returns: 0 on success, -1 on failure
- */
-int vga_client_register(struct pci_dev *pdev,
- unsigned int (*set_decode)(struct pci_dev *pdev, bool decode))
-{
- int ret = -ENODEV;
- struct vga_device *vgadev;
- unsigned long flags;
-
- spin_lock_irqsave(&vga_lock, flags);
- vgadev = vgadev_find(pdev);
- if (!vgadev)
- goto bail;
-
- vgadev->set_decode = set_decode;
- ret = 0;
-
-bail:
- spin_unlock_irqrestore(&vga_lock, flags);
- return ret;
-
-}
-EXPORT_SYMBOL(vga_client_register);
-
-/*
- * Char driver implementation
- *
- * Semantics is:
- *
- * open : open user instance of the arbitrer. by default, it's
- * attached to the default VGA device of the system.
- *
- * close : close user instance, release locks
- *
- * read : return a string indicating the status of the target.
- * an IO state string is of the form {io,mem,io+mem,none},
- * mc and ic are respectively mem and io lock counts (for
- * debugging/diagnostic only). "decodes" indicate what the
- * card currently decodes, "owns" indicates what is currently
- * enabled on it, and "locks" indicates what is locked by this
- * card. If the card is unplugged, we get "invalid" then for
- * card_ID and an -ENODEV error is returned for any command
- * until a new card is targeted
- *
- * "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
- *
- * write : write a command to the arbiter. List of commands is:
- *
- * target <card_ID> : switch target to card <card_ID> (see below)
- * lock <io_state> : acquires locks on target ("none" is invalid io_state)
- * trylock <io_state> : non-blocking acquire locks on target
- * unlock <io_state> : release locks on target
- * unlock all : release all locks on target held by this user
- * decodes <io_state> : set the legacy decoding attributes for the card
- *
- * poll : event if something change on any card (not just the target)
- *
- * card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
- * to go back to the system default card (TODO: not implemented yet).
- * Currently, only PCI is supported as a prefix, but the userland API may
- * support other bus types in the future, even if the current kernel
- * implementation doesn't.
- *
- * Note about locks:
- *
- * The driver keeps track of which user has what locks on which card. It
- * supports stacking, like the kernel one. This complexifies the implementation
- * a bit, but makes the arbiter more tolerant to userspace problems and able
- * to properly cleanup in all cases when a process dies.
- * Currently, a max of 16 cards simultaneously can have locks issued from
- * userspace for a given user (file descriptor instance) of the arbiter.
- *
- * If the device is hot-unplugged, there is a hook inside the module to notify
- * they being added/removed in the system and automatically added/removed in
- * the arbiter.
- */
-
-#define MAX_USER_CARDS CONFIG_VGA_ARB_MAX_GPUS
-#define PCI_INVALID_CARD ((struct pci_dev *)-1UL)
-
-/*
- * Each user has an array of these, tracking which cards have locks
- */
-struct vga_arb_user_card {
- struct pci_dev *pdev;
- unsigned int mem_cnt;
- unsigned int io_cnt;
-};
-
-struct vga_arb_private {
- struct list_head list;
- struct pci_dev *target;
- struct vga_arb_user_card cards[MAX_USER_CARDS];
- spinlock_t lock;
-};
-
-static LIST_HEAD(vga_user_list);
-static DEFINE_SPINLOCK(vga_user_lock);
-
-
-/*
- * This function gets a string in the format: "PCI:domain:bus:dev.fn" and
- * returns the respective values. If the string is not in this format,
- * it returns 0.
- */
-static int vga_pci_str_to_vars(char *buf, int count, unsigned int *domain,
- unsigned int *bus, unsigned int *devfn)
-{
- int n;
- unsigned int slot, func;
-
-
- n = sscanf(buf, "PCI:%x:%x:%x.%x", domain, bus, &slot, &func);
- if (n != 4)
- return 0;
-
- *devfn = PCI_DEVFN(slot, func);
-
- return 1;
-}
-
-static ssize_t vga_arb_read(struct file *file, char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct vga_arb_private *priv = file->private_data;
- struct vga_device *vgadev;
- struct pci_dev *pdev;
- unsigned long flags;
- size_t len;
- int rc;
- char *lbuf;
-
- lbuf = kmalloc(1024, GFP_KERNEL);
- if (lbuf == NULL)
- return -ENOMEM;
-
- /* Shields against vga_arb_device_card_gone (pci_dev going
- * away), and allows access to vga list
- */
- spin_lock_irqsave(&vga_lock, flags);
-
- /* If we are targeting the default, use it */
- pdev = priv->target;
- if (pdev == NULL || pdev == PCI_INVALID_CARD) {
- spin_unlock_irqrestore(&vga_lock, flags);
- len = sprintf(lbuf, "invalid");
- goto done;
- }
-
- /* Find card vgadev structure */
- vgadev = vgadev_find(pdev);
- if (vgadev == NULL) {
- /* Wow, it's not in the list, that shouldn't happen,
- * let's fix us up and return invalid card
- */
- if (pdev == priv->target)
- vga_arb_device_card_gone(pdev);
- spin_unlock_irqrestore(&vga_lock, flags);
- len = sprintf(lbuf, "invalid");
- goto done;
- }
-
- /* Fill the buffer with infos */
- len = snprintf(lbuf, 1024,
- "count:%d,PCI:%s,decodes=%s,owns=%s,locks=%s(%d:%d)\n",
- vga_decode_count, pci_name(pdev),
- vga_iostate_to_str(vgadev->decodes),
- vga_iostate_to_str(vgadev->owns),
- vga_iostate_to_str(vgadev->locks),
- vgadev->io_lock_cnt, vgadev->mem_lock_cnt);
-
- spin_unlock_irqrestore(&vga_lock, flags);
-done:
-
- /* Copy that to user */
- if (len > count)
- len = count;
- rc = copy_to_user(buf, lbuf, len);
- kfree(lbuf);
- if (rc)
- return -EFAULT;
- return len;
-}
-
-/*
- * TODO: To avoid parsing inside kernel and to improve the speed we may
- * consider use ioctl here
- */
-static ssize_t vga_arb_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct vga_arb_private *priv = file->private_data;
- struct vga_arb_user_card *uc = NULL;
- struct pci_dev *pdev;
-
- unsigned int io_state;
-
- char kbuf[64], *curr_pos;
- size_t remaining = count;
-
- int ret_val;
- int i;
-
- if (count >= sizeof(kbuf))
- return -EINVAL;
- if (copy_from_user(kbuf, buf, count))
- return -EFAULT;
- curr_pos = kbuf;
- kbuf[count] = '\0'; /* Just to make sure... */
-
- if (strncmp(curr_pos, "lock ", 5) == 0) {
- curr_pos += 5;
- remaining -= 5;
-
- pr_debug("client 0x%p called 'lock'\n", priv);
-
- if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
- ret_val = -EPROTO;
- goto done;
- }
- if (io_state == VGA_RSRC_NONE) {
- ret_val = -EPROTO;
- goto done;
- }
-
- pdev = priv->target;
- if (priv->target == NULL) {
- ret_val = -ENODEV;
- goto done;
- }
-
- vga_get_uninterruptible(pdev, io_state);
-
- /* Update the client's locks lists... */
- for (i = 0; i < MAX_USER_CARDS; i++) {
- if (priv->cards[i].pdev == pdev) {
- if (io_state & VGA_RSRC_LEGACY_IO)
- priv->cards[i].io_cnt++;
- if (io_state & VGA_RSRC_LEGACY_MEM)
- priv->cards[i].mem_cnt++;
- break;
- }
- }
-
- ret_val = count;
- goto done;
- } else if (strncmp(curr_pos, "unlock ", 7) == 0) {
- curr_pos += 7;
- remaining -= 7;
-
- pr_debug("client 0x%p called 'unlock'\n", priv);
-
- if (strncmp(curr_pos, "all", 3) == 0)
- io_state = VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM;
- else {
- if (!vga_str_to_iostate
- (curr_pos, remaining, &io_state)) {
- ret_val = -EPROTO;
- goto done;
- }
- /* TODO: Add this?
- if (io_state == VGA_RSRC_NONE) {
- ret_val = -EPROTO;
- goto done;
- }
- */
- }
-
- pdev = priv->target;
- if (priv->target == NULL) {
- ret_val = -ENODEV;
- goto done;
- }
- for (i = 0; i < MAX_USER_CARDS; i++) {
- if (priv->cards[i].pdev == pdev)
- uc = &priv->cards[i];
- }
-
- if (!uc) {
- ret_val = -EINVAL;
- goto done;
- }
-
- if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) {
- ret_val = -EINVAL;
- goto done;
- }
-
- if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) {
- ret_val = -EINVAL;
- goto done;
- }
-
- vga_put(pdev, io_state);
-
- if (io_state & VGA_RSRC_LEGACY_IO)
- uc->io_cnt--;
- if (io_state & VGA_RSRC_LEGACY_MEM)
- uc->mem_cnt--;
-
- ret_val = count;
- goto done;
- } else if (strncmp(curr_pos, "trylock ", 8) == 0) {
- curr_pos += 8;
- remaining -= 8;
-
- pr_debug("client 0x%p called 'trylock'\n", priv);
-
- if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
- ret_val = -EPROTO;
- goto done;
- }
- /* TODO: Add this?
- if (io_state == VGA_RSRC_NONE) {
- ret_val = -EPROTO;
- goto done;
- }
- */
-
- pdev = priv->target;
- if (priv->target == NULL) {
- ret_val = -ENODEV;
- goto done;
- }
-
- if (vga_tryget(pdev, io_state)) {
- /* Update the client's locks lists... */
- for (i = 0; i < MAX_USER_CARDS; i++) {
- if (priv->cards[i].pdev == pdev) {
- if (io_state & VGA_RSRC_LEGACY_IO)
- priv->cards[i].io_cnt++;
- if (io_state & VGA_RSRC_LEGACY_MEM)
- priv->cards[i].mem_cnt++;
- break;
- }
- }
- ret_val = count;
- goto done;
- } else {
- ret_val = -EBUSY;
- goto done;
- }
-
- } else if (strncmp(curr_pos, "target ", 7) == 0) {
- unsigned int domain, bus, devfn;
- struct vga_device *vgadev;
-
- curr_pos += 7;
- remaining -= 7;
- pr_debug("client 0x%p called 'target'\n", priv);
- /* if target is default */
- if (!strncmp(curr_pos, "default", 7))
- pdev = pci_dev_get(vga_default_device());
- else {
- if (!vga_pci_str_to_vars(curr_pos, remaining,
- &domain, &bus, &devfn)) {
- ret_val = -EPROTO;
- goto done;
- }
- pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
- if (!pdev) {
- pr_debug("invalid PCI address %04x:%02x:%02x.%x\n",
- domain, bus, PCI_SLOT(devfn),
- PCI_FUNC(devfn));
- ret_val = -ENODEV;
- goto done;
- }
-
- pr_debug("%s ==> %04x:%02x:%02x.%x pdev %p\n", curr_pos,
- domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
- pdev);
- }
-
- vgadev = vgadev_find(pdev);
- pr_debug("vgadev %p\n", vgadev);
- if (vgadev == NULL) {
- if (pdev) {
- vgaarb_dbg(&pdev->dev, "not a VGA device\n");
- pci_dev_put(pdev);
- }
-
- ret_val = -ENODEV;
- goto done;
- }
-
- priv->target = pdev;
- for (i = 0; i < MAX_USER_CARDS; i++) {
- if (priv->cards[i].pdev == pdev)
- break;
- if (priv->cards[i].pdev == NULL) {
- priv->cards[i].pdev = pdev;
- priv->cards[i].io_cnt = 0;
- priv->cards[i].mem_cnt = 0;
- break;
- }
- }
- if (i == MAX_USER_CARDS) {
- vgaarb_dbg(&pdev->dev, "maximum user cards (%d) number reached, ignoring this one!\n",
- MAX_USER_CARDS);
- pci_dev_put(pdev);
- /* XXX: which value to return? */
- ret_val = -ENOMEM;
- goto done;
- }
-
- ret_val = count;
- pci_dev_put(pdev);
- goto done;
-
-
- } else if (strncmp(curr_pos, "decodes ", 8) == 0) {
- curr_pos += 8;
- remaining -= 8;
- pr_debug("client 0x%p called 'decodes'\n", priv);
-
- if (!vga_str_to_iostate(curr_pos, remaining, &io_state)) {
- ret_val = -EPROTO;
- goto done;
- }
- pdev = priv->target;
- if (priv->target == NULL) {
- ret_val = -ENODEV;
- goto done;
- }
-
- __vga_set_legacy_decoding(pdev, io_state, true);
- ret_val = count;
- goto done;
- }
- /* If we got here, the message written is not part of the protocol! */
- return -EPROTO;
-
-done:
- return ret_val;
-}
-
-static __poll_t vga_arb_fpoll(struct file *file, poll_table *wait)
-{
- pr_debug("%s\n", __func__);
-
- poll_wait(file, &vga_wait_queue, wait);
- return EPOLLIN;
-}
-
-static int vga_arb_open(struct inode *inode, struct file *file)
-{
- struct vga_arb_private *priv;
- unsigned long flags;
-
- pr_debug("%s\n", __func__);
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL)
- return -ENOMEM;
- spin_lock_init(&priv->lock);
- file->private_data = priv;
-
- spin_lock_irqsave(&vga_user_lock, flags);
- list_add(&priv->list, &vga_user_list);
- spin_unlock_irqrestore(&vga_user_lock, flags);
-
- /* Set the client' lists of locks */
- priv->target = vga_default_device(); /* Maybe this is still null! */
- priv->cards[0].pdev = priv->target;
- priv->cards[0].io_cnt = 0;
- priv->cards[0].mem_cnt = 0;
-
-
- return 0;
-}
-
-static int vga_arb_release(struct inode *inode, struct file *file)
-{
- struct vga_arb_private *priv = file->private_data;
- struct vga_arb_user_card *uc;
- unsigned long flags;
- int i;
-
- pr_debug("%s\n", __func__);
-
- spin_lock_irqsave(&vga_user_lock, flags);
- list_del(&priv->list);
- for (i = 0; i < MAX_USER_CARDS; i++) {
- uc = &priv->cards[i];
- if (uc->pdev == NULL)
- continue;
- vgaarb_dbg(&uc->pdev->dev, "uc->io_cnt == %d, uc->mem_cnt == %d\n",
- uc->io_cnt, uc->mem_cnt);
- while (uc->io_cnt--)
- vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
- while (uc->mem_cnt--)
- vga_put(uc->pdev, VGA_RSRC_LEGACY_MEM);
- }
- spin_unlock_irqrestore(&vga_user_lock, flags);
-
- kfree(priv);
-
- return 0;
-}
-
-static void vga_arb_device_card_gone(struct pci_dev *pdev)
-{
-}
-
-/*
- * callback any registered clients to let them know we have a
- * change in VGA cards
- */
-static void vga_arbiter_notify_clients(void)
-{
- struct vga_device *vgadev;
- unsigned long flags;
- uint32_t new_decodes;
- bool new_state;
-
- if (!vga_arbiter_used)
- return;
-
- spin_lock_irqsave(&vga_lock, flags);
- list_for_each_entry(vgadev, &vga_list, list) {
- if (vga_count > 1)
- new_state = false;
- else
- new_state = true;
- if (vgadev->set_decode) {
- new_decodes = vgadev->set_decode(vgadev->pdev,
- new_state);
- vga_update_device_decodes(vgadev, new_decodes);
- }
- }
- spin_unlock_irqrestore(&vga_lock, flags);
-}
-
-static int pci_notify(struct notifier_block *nb, unsigned long action,
- void *data)
-{
- struct device *dev = data;
- struct pci_dev *pdev = to_pci_dev(dev);
- bool notify = false;
-
- vgaarb_dbg(dev, "%s\n", __func__);
-
- /* For now we're only intereted in devices added and removed. I didn't
- * test this thing here, so someone needs to double check for the
- * cases of hotplugable vga cards. */
- if (action == BUS_NOTIFY_ADD_DEVICE)
- notify = vga_arbiter_add_pci_device(pdev);
- else if (action == BUS_NOTIFY_DEL_DEVICE)
- notify = vga_arbiter_del_pci_device(pdev);
-
- if (notify)
- vga_arbiter_notify_clients();
- return 0;
-}
-
-static struct notifier_block pci_notifier = {
- .notifier_call = pci_notify,
-};
-
-static const struct file_operations vga_arb_device_fops = {
- .read = vga_arb_read,
- .write = vga_arb_write,
- .poll = vga_arb_fpoll,
- .open = vga_arb_open,
- .release = vga_arb_release,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice vga_arb_device = {
- MISC_DYNAMIC_MINOR, "vga_arbiter", &vga_arb_device_fops
-};
-
-#if defined(CONFIG_ACPI)
-static bool vga_arb_integrated_gpu(struct device *dev)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
-
- return adev && !strcmp(acpi_device_hid(adev), ACPI_VIDEO_HID);
-}
-#else
-static bool vga_arb_integrated_gpu(struct device *dev)
-{
- return false;
-}
-#endif
-
-static void __init vga_arb_select_default_device(void)
-{
- struct pci_dev *pdev, *found = NULL;
- struct vga_device *vgadev;
-
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
- u64 base = screen_info.lfb_base;
- u64 size = screen_info.lfb_size;
- u64 limit;
- resource_size_t start, end;
- unsigned long flags;
- int i;
-
- if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
- base |= (u64)screen_info.ext_lfb_base << 32;
-
- limit = base + size;
-
- list_for_each_entry(vgadev, &vga_list, list) {
- struct device *dev = &vgadev->pdev->dev;
- /*
- * Override vga_arbiter_add_pci_device()'s I/O based detection
- * as it may take the wrong device (e.g. on Apple system under
- * EFI).
- *
- * Select the device owning the boot framebuffer if there is
- * one.
- */
-
- /* Does firmware framebuffer belong to us? */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- flags = pci_resource_flags(vgadev->pdev, i);
-
- if ((flags & IORESOURCE_MEM) == 0)
- continue;
-
- start = pci_resource_start(vgadev->pdev, i);
- end = pci_resource_end(vgadev->pdev, i);
-
- if (!start || !end)
- continue;
-
- if (base < start || limit >= end)
- continue;
-
- if (!vga_default_device())
- vgaarb_info(dev, "setting as boot device\n");
- else if (vgadev->pdev != vga_default_device())
- vgaarb_info(dev, "overriding boot device\n");
- vga_set_default_device(vgadev->pdev);
- }
- }
-#endif
-
- if (!vga_default_device()) {
- list_for_each_entry_reverse(vgadev, &vga_list, list) {
- struct device *dev = &vgadev->pdev->dev;
- u16 cmd;
-
- pdev = vgadev->pdev;
- pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
- found = pdev;
- if (vga_arb_integrated_gpu(dev))
- break;
- }
- }
- }
-
- if (found) {
- vgaarb_info(&found->dev, "setting as boot device (VGA legacy resources not available)\n");
- vga_set_default_device(found);
- return;
- }
-
- if (!vga_default_device()) {
- vgadev = list_first_entry_or_null(&vga_list,
- struct vga_device, list);
- if (vgadev) {
- struct device *dev = &vgadev->pdev->dev;
- vgaarb_info(dev, "setting as boot device (VGA legacy resources not available)\n");
- vga_set_default_device(vgadev->pdev);
- }
- }
-}
-
-static int __init vga_arb_device_init(void)
-{
- int rc;
- struct pci_dev *pdev;
- struct vga_device *vgadev;
-
- rc = misc_register(&vga_arb_device);
- if (rc < 0)
- pr_err("error %d registering device\n", rc);
-
- bus_register_notifier(&pci_bus_type, &pci_notifier);
-
- /* We add all PCI devices satisfying VGA class in the arbiter by
- * default */
- pdev = NULL;
- while ((pdev =
- pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
- PCI_ANY_ID, pdev)) != NULL)
- vga_arbiter_add_pci_device(pdev);
-
- list_for_each_entry(vgadev, &vga_list, list) {
- struct device *dev = &vgadev->pdev->dev;
-
- if (vgadev->bridge_has_one_vga)
- vgaarb_info(dev, "bridge control possible\n");
- else
- vgaarb_info(dev, "no bridge control possible\n");
- }
-
- vga_arb_select_default_device();
-
- pr_info("loaded\n");
- return rc;
-}
-subsys_initcall(vga_arb_device_init);